[flutter_runner][a11y] integrate settings manager and test

Ties the accessiblity features and enablement to the settings manager.

Adds a test for platform view creation triggering registration.

Reshuffles some mock classes for reusability.

Change-Id: I9cdb2fa15df86f3ca115b5ec35771f4b2479a2b1
Bug: MI4-1478
diff --git a/runtime/flutter_runner/BUILD.gn b/runtime/flutter_runner/BUILD.gn
index 87cd378..68424c0 100644
--- a/runtime/flutter_runner/BUILD.gn
+++ b/runtime/flutter_runner/BUILD.gn
@@ -443,6 +443,7 @@
     "accessibility_bridge_fakes.cc",
     "accessibility_bridge_fakes.h",
     "accessibility_bridge_unittest.cc",
+    "flutter_runner_fakes.h",
     "fuchsia_accessibility.cc",
     "fuchsia_accessibility.h",
     "fuchsia_accessibility_unittest.cc",
@@ -450,24 +451,39 @@
     "fuchsia_font_manager.h",
     "fuchsia_font_manager_unittest.cc",
     "logging.h",
+    "platform_view.cc",
+    "platform_view.h",
+    "platform_view_unittest.cc",
+    "surface.cc",
+    "surface.h",
+    "vsync_recorder.cc",
+    "vsync_recorder.h",
+    "vsync_waiter.cc",
+    "vsync_waiter.h",
   ]
 
   deps = [
     "$flutter_root/lib/ui",
+    "$flutter_root/shell/common",
     "//garnet/public/lib/gtest",
     "//sdk/fidl/fuchsia.accessibility",
     "//sdk/fidl/fuchsia.accessibility.semantics",
     "//sdk/fidl/fuchsia.fonts",
+    "//sdk/fidl/fuchsia.modular",
     "//sdk/fidl/fuchsia.sys",
+    "//sdk/fidl/fuchsia.ui.scenic",
+    "//sdk/lib/ui/scenic/cpp",
     "//sdk/lib/sys/cpp",
     "//sdk/lib/sys/cpp/testing:unit",
     "//third_party/dart/runtime:libdart_jit",
     "//third_party/dart/runtime/platform:libdart_platform_jit",
     "//third_party/googletest:gtest_main",
     "//third_party/icu",
+    "//third_party/rapidjson",
     "//third_party/skia",
     "//topaz/runtime/dart/utils:inlines",
     "//topaz/runtime/dart/utils:vmo",
+    "//topaz/runtime/flutter_runner:jit",
     "//zircon/public/lib/fdio",
     "//zircon/public/lib/trace",
     "//zircon/public/lib/zx",
diff --git a/runtime/flutter_runner/flutter_runner_fakes.h b/runtime/flutter_runner/flutter_runner_fakes.h
new file mode 100644
index 0000000..0f70b6c
--- /dev/null
+++ b/runtime/flutter_runner/flutter_runner_fakes.h
@@ -0,0 +1,81 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOPAZ_RUNTIME_FLUTTER_RUNNER_PLATFORM_VIEW_FAKES_H_
+#define TOPAZ_RUNTIME_FLUTTER_RUNNER_PLATFORM_VIEW_FAKES_H_
+
+#include "fuchsia/accessibility/cpp/fidl.h"
+#include "fuchsia/accessibility/semantics/cpp/fidl.h"
+
+namespace flutter_runner_test {
+using fuchsia::accessibility::semantics::SemanticsManager;
+using AccessibilitySettingsManager = fuchsia::accessibility::SettingsManager;
+using AccessibilitySettingsWatcher = fuchsia::accessibility::SettingsWatcher;
+using AccessibilitySettingsProvider = fuchsia::accessibility::SettingsProvider;
+
+class MockSemanticsManager : public SemanticsManager {
+ public:
+  MockSemanticsManager() = default;
+  ~MockSemanticsManager() = default;
+
+  // |fuchsia::accessibility::semantics::SemanticsManager|:
+  void RegisterView(
+      fuchsia::ui::views::ViewRef view_ref,
+      fidl::InterfaceHandle<
+          fuchsia::accessibility::semantics::SemanticActionListener>
+          handle,
+      fidl::InterfaceRequest<fuchsia::accessibility::semantics::SemanticTree>
+          semantic_tree) override {
+    has_view_ref_ = true;
+  }
+
+  fidl::InterfaceRequestHandler<SemanticsManager> GetHandler(
+      async_dispatcher_t* dispatcher) {
+    return bindings_.GetHandler(this, dispatcher);
+  }
+
+  bool RegisterViewCalled() { return has_view_ref_; }
+
+ private:
+  bool has_view_ref_ = false;
+  fidl::BindingSet<SemanticsManager> bindings_;
+};
+
+class MockAccessibilitySettingsManager : public AccessibilitySettingsManager {
+ public:
+  MockAccessibilitySettingsManager(fuchsia::accessibility::Settings settings)
+      : settings_(std::move(settings)) {}
+  ~MockAccessibilitySettingsManager() = default;
+
+  // |fuchsia::accessibility::SettingsManager|
+  void RegisterSettingProvider(
+      fidl::InterfaceRequest<AccessibilitySettingsProvider>
+          settings_provider_request) override {}
+
+  // |fuchsia::accessibility::SettingsManager|
+  void Watch(
+      fidl::InterfaceHandle<AccessibilitySettingsWatcher> watcher) override {
+    watch_called_ = true;
+    auto proxy = watcher.Bind();
+    EXPECT_TRUE(proxy);
+    fuchsia::accessibility::Settings settings = fidl::Clone(settings_);
+    proxy->OnSettingsChange(std::move(settings));
+  }
+
+  fidl::InterfaceRequestHandler<AccessibilitySettingsManager> GetHandler(
+      async_dispatcher_t* dispatcher) {
+    return bindings_.GetHandler(this, dispatcher);
+  }
+
+  bool WatchCalled() { return watch_called_; }
+
+ private:
+  bool watch_called_ = false;
+  fuchsia::accessibility::Settings settings_;
+  fidl::BindingSet<AccessibilitySettingsManager> bindings_;
+};
+
+}  // namespace flutter_runner_test
+
+#endif  // TOPAZ_RUNTIME_FLUTTER_RUNNER_PLATFORM_VIEW_FAKES_H_
diff --git a/runtime/flutter_runner/fuchsia_accessibility_unittest.cc b/runtime/flutter_runner/fuchsia_accessibility_unittest.cc
index 1fcfaf4..ed7e1b7 100644
--- a/runtime/flutter_runner/fuchsia_accessibility_unittest.cc
+++ b/runtime/flutter_runner/fuchsia_accessibility_unittest.cc
@@ -11,38 +11,11 @@
 #include <lib/gtest/real_loop_fixture.h>
 #include <lib/sys/cpp/testing/service_directory_provider.h>
 
-namespace flutter_runner_a11y_test {
-using fuchsia::accessibility::semantics::SemanticsManager;
+#include "flutter_runner_fakes.h"
+
+namespace flutter_runner_test::flutter_runner_a11y_test {
 using FuchsiaAccessibilityTests = gtest::RealLoopFixture;
 
-class MockSemanticsManager : public SemanticsManager {
- public:
-  MockSemanticsManager() = default;
-  ~MockSemanticsManager() = default;
-
-  // |fuchsia::accessibility::semantics::SemanticsManager|:
-  void RegisterView(
-      fuchsia::ui::views::ViewRef view_ref,
-      fidl::InterfaceHandle<
-          fuchsia::accessibility::semantics::SemanticActionListener>
-          handle,
-      fidl::InterfaceRequest<fuchsia::accessibility::semantics::SemanticTree>
-          semantic_tree) override {
-    has_view_ref_ = true;
-  }
-
-  fidl::InterfaceRequestHandler<SemanticsManager> GetHandler(
-      async_dispatcher_t* dispatcher) {
-    return bindings_.GetHandler(this, dispatcher);
-  }
-
-  bool RegisterViewCalled() { return has_view_ref_; }
-
- private:
-  bool has_view_ref_ = false;
-  fidl::BindingSet<SemanticsManager> bindings_;
-};
-
 TEST_F(FuchsiaAccessibilityTests, RegisterViewRef) {
   MockSemanticsManager semantics_manager;
   sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
@@ -60,4 +33,4 @@
   EXPECT_TRUE(semantics_manager.RegisterViewCalled());
 }
 
-}  // namespace flutter_runner_a11y_test
+}  // namespace flutter_runner_test::flutter_runner_a11y_test
diff --git a/runtime/flutter_runner/meta/flutter_runner_tests.cmx b/runtime/flutter_runner/meta/flutter_runner_tests.cmx
index 80a31b3..2566fa7 100644
--- a/runtime/flutter_runner/meta/flutter_runner_tests.cmx
+++ b/runtime/flutter_runner/meta/flutter_runner_tests.cmx
@@ -3,6 +3,9 @@
         "binary": "test/flutter_runner_tests"
     },
     "sandbox": {
+        "features": [
+            "vulkan"
+        ],
         "services": [
             "fuchsia.accessibility.SettingsManager",
             "fuchsia.accessibility.semantics.SemanticsManager",
diff --git a/runtime/flutter_runner/platform_view.cc b/runtime/flutter_runner/platform_view.cc
index 6c17465..8d61c0b 100644
--- a/runtime/flutter_runner/platform_view.cc
+++ b/runtime/flutter_runner/platform_view.cc
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "fuchsia/accessibility/cpp/fidl.h"
 #define RAPIDJSON_HAS_STDSTRING 1
 
-#include "platform_view.h"
-
 #include <trace/event.h>
 
 #include <sstream>
@@ -13,7 +12,9 @@
 #include "flutter/fml/logging.h"
 #include "flutter/lib/ui/compositing/scene_host.h"
 #include "flutter/lib/ui/window/pointer_data.h"
+#include "flutter/lib/ui/window/window.h"
 #include "fuchsia/ui/views/cpp/fidl.h"
+#include "platform_view.h"
 #include "rapidjson/document.h"
 #include "rapidjson/stringbuffer.h"
 #include "rapidjson/writer.h"
@@ -101,6 +102,7 @@
       metrics_changed_callback_(std::move(session_metrics_did_change_callback)),
       size_change_hint_callback_(std::move(session_size_change_hint_callback)),
       ime_client_(this),
+      a11y_settings_watcher_binding_(this),
       surface_(std::make_unique<Surface>(debug_label_)),
       vsync_event_handle_(vsync_event_handle) {
   // Register all error handlers.
@@ -110,6 +112,8 @@
   SetInterfaceErrorHandler(clipboard_, "Clipboard");
   SetInterfaceErrorHandler(parent_environment_service_provider_,
                            "Parent Environment Service Provider");
+  SetInterfaceErrorHandler(a11y_settings_manager_,
+                           "Accessibility Settings Manager");
   // Access the clipboard.
   parent_environment_service_provider_ =
       parent_environment_service_provider_handle.Bind();
@@ -128,7 +132,14 @@
   view_ref_.Clone(&accessibility_view_ref);
   accessibility_bridge_ =
       std::make_unique<AccessibilityBridge>(FuchsiaAccessibility::Create(
-          std::move(runner_services), std::move(accessibility_view_ref)));
+          runner_services, std::move(accessibility_view_ref)));
+  // Register with the A11y Settings Manager
+  runner_services->Connect(fuchsia::accessibility::SettingsManager::Name_,
+                           a11y_settings_manager_.NewRequest().TakeChannel());
+  fidl::InterfaceHandle<fuchsia::accessibility::SettingsWatcher>
+      a11y_watcher_handle;
+  a11y_settings_watcher_binding_.Bind(a11y_watcher_handle.NewRequest());
+  a11y_settings_manager_->Watch(std::move(a11y_watcher_handle));
 }
 
 PlatformView::~PlatformView() = default;
@@ -145,6 +156,23 @@
                 std::placeholders::_1);
 }
 
+void PlatformView::OnSettingsChange(fuchsia::accessibility::Settings settings) {
+  int32_t flags = 0;
+  if (settings.has_color_inversion_enabled() &&
+      settings.color_inversion_enabled()) {
+    flags |=
+        static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors);
+  }
+  bool screen_reader_enabled =
+      settings.has_screen_reader_enabled() && settings.screen_reader_enabled();
+  if (screen_reader_enabled) {
+    flags |= static_cast<int32_t>(
+        flutter::AccessibilityFeatureFlag::kAccessibleNavigation);
+  }
+  SetSemanticsEnabled(screen_reader_enabled);
+  SetAccessibilityFeatures(flags);
+}
+
 void PlatformView::OnPropertiesChanged(
     const fuchsia::ui::gfx::ViewProperties& view_properties) {
   fuchsia::ui::gfx::BoundingBox layout_box =
diff --git a/runtime/flutter_runner/platform_view.h b/runtime/flutter_runner/platform_view.h
index d3d7b43..32edd72 100644
--- a/runtime/flutter_runner/platform_view.h
+++ b/runtime/flutter_runner/platform_view.h
@@ -40,7 +40,8 @@
 // thread.
 class PlatformView final : public flutter::PlatformView,
                            private fuchsia::ui::scenic::SessionListener,
-                           public fuchsia::ui::input::InputMethodEditorClient {
+                           public fuchsia::ui::input::InputMethodEditorClient,
+                           public fuchsia::accessibility::SettingsWatcher {
  public:
   PlatformView(PlatformView::Delegate& delegate, std::string debug_label,
                fuchsia::ui::views::ViewRefControl view_ref_control,
@@ -65,6 +66,9 @@
 
   void UpdateViewportMetrics(const fuchsia::ui::gfx::Metrics& metrics);
 
+  // |fuchsia::accessibility::SettingsWatcher|
+  void OnSettingsChange(fuchsia::accessibility::Settings settings) override;
+
  private:
   const std::string debug_label_;
   // TODO(MI4-2490): remove once ViewRefControl is passed to Scenic and kept
@@ -85,6 +89,8 @@
 
   fuchsia::sys::ServiceProviderPtr parent_environment_service_provider_;
   fuchsia::modular::ClipboardPtr clipboard_;
+  fuchsia::accessibility::SettingsManagerPtr a11y_settings_manager_;
+  fidl::Binding<fuchsia::accessibility::SettingsWatcher> a11y_settings_watcher_binding_;
   std::unique_ptr<Surface> surface_;
   flutter::LogicalMetrics metrics_;
   fuchsia::ui::gfx::Metrics scenic_metrics_;
diff --git a/runtime/flutter_runner/platform_view_unittest.cc b/runtime/flutter_runner/platform_view_unittest.cc
new file mode 100644
index 0000000..37afc90
--- /dev/null
+++ b/runtime/flutter_runner/platform_view_unittest.cc
@@ -0,0 +1,284 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "topaz/runtime/flutter_runner/platform_view.h"
+
+#include <gtest/gtest.h>
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/fidl/cpp/binding_set.h>
+#include <lib/fidl/cpp/interface_request.h>
+#include <lib/gtest/real_loop_fixture.h>
+#include <lib/sys/cpp/testing/service_directory_provider.h>
+
+#include <memory>
+#include <vector>
+
+#include "flutter/lib/ui/window/window.h"
+#include "flutter_runner_fakes.h"
+#include "fuchsia/ui/views/cpp/fidl.h"
+#include "googletest/googletest/include/gtest/gtest.h"
+
+namespace flutter_runner_test::flutter_runner_a11y_test {
+using PlatformViewTests = gtest::RealLoopFixture;
+
+class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
+ public:
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewCreated(std::unique_ptr<flutter::Surface> surface) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewDestroyed() {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewSetNextFrameCallback(fml::closure closure) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewSetViewportMetrics(
+      const flutter::ViewportMetrics& metrics) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewDispatchPlatformMessage(
+      fml::RefPtr<flutter::PlatformMessage> message) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewDispatchPointerDataPacket(
+      std::unique_ptr<flutter::PointerDataPacket> packet) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewDispatchSemanticsAction(int32_t id,
+                                             flutter::SemanticsAction action,
+                                             std::vector<uint8_t> args) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewSetSemanticsEnabled(bool enabled) {
+    semantics_enabled_ = enabled;
+  }
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
+    semantics_features_ = flags;
+  }
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewRegisterTexture(
+      std::shared_ptr<flutter::Texture> texture) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewUnregisterTexture(int64_t texture_id) {}
+  // |flutter::PlatformView::Delegate|
+  void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) {}
+
+  bool SemanticsEnabled() const { return semantics_enabled_; }
+  int32_t SemanticsFeatures() const { return semantics_features_; }
+
+ private:
+  bool semantics_enabled_ = false;
+  int32_t semantics_features_ = 0;
+};
+TEST_F(PlatformViewTests, SurvivesWhenSettingsManagerNotAvailable) {
+  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
+  MockPlatformViewDelegate delegate;
+  zx::eventpair a, b;
+  zx::eventpair::create(/* flags */ 0u, &a, &b);
+  auto view_ref = fuchsia::ui::views::ViewRef({
+      .reference = std::move(a),
+  });
+  auto view_ref_control = fuchsia::ui::views::ViewRefControl({
+      .reference = std::move(b),
+  });
+  flutter::TaskRunners task_runners =
+      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
+
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+
+  auto platform_view = flutter_runner::PlatformView(
+      delegate,                               // delegate
+      "test_platform_view",                   // label
+      std::move(view_ref_control),            // view_ref_control
+      std::move(view_ref),                    // view_ref
+      std::move(task_runners),                // task_runners
+      services_provider.service_directory(),  // runner_services
+      nullptr,  // parent_environment_service_provider_handle
+      nullptr,  // session_listener_request
+      nullptr,  // on_session_listener_error_callback
+      nullptr,  // session_metrics_did_change_callback
+      nullptr,  // session_size_change_hint_callback
+      0u        // vsync_event_handle
+  );
+
+  RunLoopUntilIdle();
+
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+}
+
+TEST_F(PlatformViewTests, RegistersWatcherAndEnablesSemantics) {
+  fuchsia::accessibility::Settings settings;
+  settings.set_screen_reader_enabled(true);
+  settings.set_color_inversion_enabled(true);
+  MockAccessibilitySettingsManager settings_manager =
+      MockAccessibilitySettingsManager(std::move(settings));
+  MockSemanticsManager semantics_manager = MockSemanticsManager();
+  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
+  services_provider.AddService(settings_manager.GetHandler(dispatcher()),
+                               AccessibilitySettingsManager::Name_);
+  services_provider.AddService(semantics_manager.GetHandler(dispatcher()),
+                               SemanticsManager::Name_);
+
+  MockPlatformViewDelegate delegate;
+  zx::eventpair a, b;
+  zx::eventpair::create(/* flags */ 0u, &a, &b);
+  auto view_ref = fuchsia::ui::views::ViewRef({
+      .reference = std::move(a),
+  });
+  auto view_ref_control = fuchsia::ui::views::ViewRefControl({
+      .reference = std::move(b),
+  });
+  flutter::TaskRunners task_runners =
+      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
+
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+
+  auto platform_view = flutter_runner::PlatformView(
+      delegate,                               // delegate
+      "test_platform_view",                   // label
+      std::move(view_ref_control),            // view_ref_control
+      std::move(view_ref),                    // view_ref
+      std::move(task_runners),                // task_runners
+      services_provider.service_directory(),  // runner_services
+      nullptr,  // parent_environment_service_provider_handle
+      nullptr,  // session_listener_request
+      nullptr,  // on_session_listener_error_callback
+      nullptr,  // session_metrics_did_change_callback
+      nullptr,  // session_size_change_hint_callback
+      0u        // vsync_event_handle
+  );
+
+  RunLoopUntilIdle();
+
+  EXPECT_TRUE(settings_manager.WatchCalled());
+  EXPECT_TRUE(delegate.SemanticsEnabled());
+  EXPECT_EQ(
+      delegate.SemanticsFeatures(),
+      static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors) |
+          static_cast<int32_t>(
+              flutter::AccessibilityFeatureFlag::kAccessibleNavigation));
+}
+
+TEST_F(PlatformViewTests, ChangesSettings) {
+  fuchsia::accessibility::Settings settings;
+  settings.set_screen_reader_enabled(true);
+  settings.set_color_inversion_enabled(true);
+  MockAccessibilitySettingsManager settings_manager =
+      MockAccessibilitySettingsManager(std::move(settings));
+  MockSemanticsManager semantics_manager = MockSemanticsManager();
+  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
+  services_provider.AddService(settings_manager.GetHandler(dispatcher()),
+                               AccessibilitySettingsManager::Name_);
+  services_provider.AddService(semantics_manager.GetHandler(dispatcher()),
+                               SemanticsManager::Name_);
+
+  MockPlatformViewDelegate delegate;
+  zx::eventpair a, b;
+  zx::eventpair::create(/* flags */ 0u, &a, &b);
+  auto view_ref = fuchsia::ui::views::ViewRef({
+      .reference = std::move(a),
+  });
+  auto view_ref_control = fuchsia::ui::views::ViewRefControl({
+      .reference = std::move(b),
+  });
+  flutter::TaskRunners task_runners =
+      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
+
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+
+  auto platform_view = flutter_runner::PlatformView(
+      delegate,                               // delegate
+      "test_platform_view",                   // label
+      std::move(view_ref_control),            // view_ref_control
+      std::move(view_ref),                    // view_ref
+      std::move(task_runners),                // task_runners
+      services_provider.service_directory(),  // runner_services
+      nullptr,  // parent_environment_service_provider_handle
+      nullptr,  // session_listener_request
+      nullptr,  // on_session_listener_error_callback
+      nullptr,  // session_metrics_did_change_callback
+      nullptr,  // session_size_change_hint_callback
+      0u        // vsync_event_handle
+  );
+
+  RunLoopUntilIdle();
+
+  EXPECT_TRUE(settings_manager.WatchCalled());
+  EXPECT_TRUE(delegate.SemanticsEnabled());
+  EXPECT_EQ(
+      delegate.SemanticsFeatures(),
+      static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors) |
+          static_cast<int32_t>(
+              flutter::AccessibilityFeatureFlag::kAccessibleNavigation));
+
+  fuchsia::accessibility::Settings screen_no_color_inversion;
+  screen_no_color_inversion.set_screen_reader_enabled(true);
+  screen_no_color_inversion.set_color_inversion_enabled(false);
+
+  platform_view.OnSettingsChange(std::move(screen_no_color_inversion));
+  EXPECT_TRUE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(),
+            static_cast<int32_t>(
+                flutter::AccessibilityFeatureFlag::kAccessibleNavigation));
+
+  fuchsia::accessibility::Settings disabled_settings;
+  disabled_settings.set_screen_reader_enabled(false);
+  disabled_settings.set_color_inversion_enabled(false);
+
+  platform_view.OnSettingsChange(std::move(disabled_settings));
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+}
+
+TEST_F(PlatformViewTests, RegistersWatcherAndSetsFeaturesWhenNoScreenReader) {
+  fuchsia::accessibility::Settings settings;
+  settings.set_color_inversion_enabled(true);
+  MockAccessibilitySettingsManager settings_manager =
+      MockAccessibilitySettingsManager(std::move(settings));
+  MockSemanticsManager semantics_manager = MockSemanticsManager();
+  sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
+  services_provider.AddService(settings_manager.GetHandler(dispatcher()),
+                               AccessibilitySettingsManager::Name_);
+  services_provider.AddService(semantics_manager.GetHandler(dispatcher()),
+                               SemanticsManager::Name_);
+
+  MockPlatformViewDelegate delegate;
+  zx::eventpair a, b;
+  zx::eventpair::create(/* flags */ 0u, &a, &b);
+  auto view_ref = fuchsia::ui::views::ViewRef({
+      .reference = std::move(a),
+  });
+  auto view_ref_control = fuchsia::ui::views::ViewRefControl({
+      .reference = std::move(b),
+  });
+  flutter::TaskRunners task_runners =
+      flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
+
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(delegate.SemanticsFeatures(), 0);
+
+  auto platform_view = flutter_runner::PlatformView(
+      delegate,                               // delegate
+      "test_platform_view",                   // label
+      std::move(view_ref_control),            // view_ref_control
+      std::move(view_ref),                    // view_ref
+      std::move(task_runners),                // task_runners
+      services_provider.service_directory(),  // runner_services
+      nullptr,  // parent_environment_service_provider_handle
+      nullptr,  // session_listener_request
+      nullptr,  // on_session_listener_error_callback
+      nullptr,  // session_metrics_did_change_callback
+      nullptr,  // session_size_change_hint_callback
+      0u        // vsync_event_handle
+  );
+
+  RunLoopUntilIdle();
+
+  EXPECT_TRUE(settings_manager.WatchCalled());
+  EXPECT_FALSE(delegate.SemanticsEnabled());
+  EXPECT_EQ(
+      delegate.SemanticsFeatures(),
+      static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kInvertColors));
+}
+
+}  // namespace flutter_runner_test::flutter_runner_a11y_test