[root-presenter][ui-input] add stub implementations of virtual keyboard protocols

As a first step towards implementing the virtual keyboard protocols
in root presenter, add some stubs that simply log requests.

Bug: 70949
Test: fx test -o root_presenter_unittests  -- --gtest_filter='Virtual*'
Test: manual (on astro, see below)
Change-Id: I0e69cb9d32de29e167c634c351d6b2740850a129

Manual test
-----------
1. fx shell run \
       fuchsia-pkg://fuchsia.com/web_engine_shell#meta/web_engine_shell.cmx \
       http://www.google.com
2. see log messages for ControllerCreator::Create(), and
   Controller::WatchVisibility()
3. tap search box
4. see log messages for Controller::SetTextType(), and
   Controller::RequestShow()
5. tap outside search box
6. see log message for Controller::RequestHide()

Change-Id: I8a687cc12469a3813e8a739a62b274f6bccd3062
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/510796
Fuchsia-Auto-Submit: Mukesh Agrawal <quiche@google.com>
Reviewed-by: Alice Neels <neelsa@google.com>
Commit-Queue: Mukesh Agrawal <quiche@google.com>
diff --git a/src/ui/bin/root_presenter/BUILD.gn b/src/ui/bin/root_presenter/BUILD.gn
index c870a639..2f76901 100644
--- a/src/ui/bin/root_presenter/BUILD.gn
+++ b/src/ui/bin/root_presenter/BUILD.gn
@@ -77,6 +77,7 @@
     ":factory_reset_manager",
     ":focus_dispatcher",
     "//sdk/fidl/fuchsia.accessibility",
+    "//sdk/fidl/fuchsia.input.virtualkeyboard",
     "//sdk/fidl/fuchsia.media.sounds",
     "//sdk/fidl/fuchsia.recovery",
     "//sdk/fidl/fuchsia.recovery.ui",
@@ -105,6 +106,7 @@
     ":displays",
     ":media_buttons_handler",
     ":safe_presenter",
+    ":virtual_keyboard",
     "//garnet/public/lib/fostr/fidl/fuchsia.input.report",
     "//garnet/public/lib/fostr/fidl/fuchsia.ui.input",
     "//sdk/fidl/fuchsia.accessibility",
@@ -246,3 +248,18 @@
   ]
   deps = [ "//src/lib/files" ]
 }
+
+source_set("virtual_keyboard") {
+  sources = [
+    "virtual_keyboard_controller.cc",
+    "virtual_keyboard_controller.h",
+    "virtual_keyboard_controller_creator.cc",
+    "virtual_keyboard_controller_creator.h",
+  ]
+
+  deps = [
+    "//sdk/fidl/fuchsia.input.virtualkeyboard",
+    "//sdk/lib/sys/cpp",
+    "//sdk/lib/syslog/cpp",
+  ]
+}
diff --git a/src/ui/bin/root_presenter/app.cc b/src/ui/bin/root_presenter/app.cc
index db4b1c4..4ade42a 100644
--- a/src/ui/bin/root_presenter/app.cc
+++ b/src/ui/bin/root_presenter/app.cc
@@ -42,7 +42,8 @@
       fdr_manager_(std::make_unique<FactoryResetManager>(*component_context_,
                                                          std::make_shared<MediaRetriever>())),
       focuser_binding_(this),
-      media_buttons_handler_() {
+      media_buttons_handler_(),
+      virtual_keyboard_controller_creator_(component_context) {
   FX_DCHECK(component_context_);
 
   input_reader_.Start();
@@ -252,6 +253,10 @@
     // instead, we add error handlers for cleanup on the a11y presentations when we register them.
 
     // Add Color Transform Handler.
+    //
+    // TODO(fxbug.dev/73838): refactor so that `fuchsia.ui.brightness.ColorAdjustmentHandler`
+    // and `fuchsia.ui.policy.DisplayBacklight` are added to outgoing services before entering
+    // the event loop.
     color_transform_handler_ = std::make_unique<ColorTransformHandler>(
         component_context_, compositor_->id(), session_.get(), safe_presenter_.get());
 
diff --git a/src/ui/bin/root_presenter/app.h b/src/ui/bin/root_presenter/app.h
index 6cccc9e..db30b23 100644
--- a/src/ui/bin/root_presenter/app.h
+++ b/src/ui/bin/root_presenter/app.h
@@ -6,6 +6,7 @@
 #define SRC_UI_BIN_ROOT_PRESENTER_APP_H_
 
 #include <fuchsia/accessibility/cpp/fidl.h>
+#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
 #include <fuchsia/ui/input/accessibility/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/policy/accessibility/cpp/fidl.h>
@@ -35,6 +36,7 @@
 #include "src/ui/bin/root_presenter/media_buttons_handler.h"
 #include "src/ui/bin/root_presenter/presentation.h"
 #include "src/ui/bin/root_presenter/safe_presenter.h"
+#include "src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h"
 #include "src/ui/lib/input_report_reader/input_reader.h"
 
 namespace root_presenter {
@@ -187,6 +189,8 @@
   // Used to dispatch the focus change messages to interested downstream clients.
   std::unique_ptr<FocusDispatcher> focus_dispatcher_;
 
+  VirtualKeyboardControllerCreator virtual_keyboard_controller_creator_;
+
   FXL_DISALLOW_COPY_AND_ASSIGN(App);
 };
 
diff --git a/src/ui/bin/root_presenter/services.config b/src/ui/bin/root_presenter/services.config
index df73e1f..658390d 100644
--- a/src/ui/bin/root_presenter/services.config
+++ b/src/ui/bin/root_presenter/services.config
@@ -1,5 +1,6 @@
 {
   "services": {
+    "fuchsia.input.virtualkeyboard.ControllerCreator": "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx",
     "fuchsia.recovery.FactoryResetStateNotifier": "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx",
     "fuchsia.recovery.policy.Device": "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx",
     "fuchsia.recovery.ui.FactoryResetCountdown": "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx",
diff --git a/src/ui/bin/root_presenter/tests/BUILD.gn b/src/ui/bin/root_presenter/tests/BUILD.gn
index d893f8e..37d5340 100644
--- a/src/ui/bin/root_presenter/tests/BUILD.gn
+++ b/src/ui/bin/root_presenter/tests/BUILD.gn
@@ -55,6 +55,8 @@
     "media_buttons_handler_unittest.cc",
     "root_presenter_unittest.cc",
     "safe_presenter_unittest.cc",
+    "virtual_keyboard_controller_creator_unittest.cc",
+    "virtual_keyboard_controller_unittest.cc",
   ]
 
   deps = [
@@ -81,6 +83,7 @@
     "//src/ui/bin/root_presenter:lib",
     "//src/ui/bin/root_presenter:media_buttons_handler",
     "//src/ui/bin/root_presenter:safe_presenter",
+    "//src/ui/bin/root_presenter:virtual_keyboard",
     "//src/ui/bin/root_presenter/tests/fakes",
     "//src/ui/lib/key_util",
     "//src/ui/testing:mock_input_device",
diff --git a/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_creator_unittest.cc b/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_creator_unittest.cc
new file mode 100644
index 0000000..d9015e6
--- /dev/null
+++ b/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_creator_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2021 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 "src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h"
+
+#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
+#include <lib/sys/cpp/component_context.h>
+#include <lib/sys/cpp/testing/component_context_provider.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
+#include <zircon/status.h>
+#include <zircon/types.h>
+
+#include <gtest/gtest.h>
+#include <src/lib/testing/loop_fixture/test_loop_fixture.h>
+
+namespace root_presenter {
+namespace virtual_keyboard_controller_creator {
+namespace {
+
+class VirtualKeyboardControllerCreatorTest : public gtest::TestLoopFixture {
+ protected:
+  auto* context_provider() { return &context_provider_; }
+
+ private:
+  sys::testing::ComponentContextProvider context_provider_;
+};
+
+TEST_F(VirtualKeyboardControllerCreatorTest, CtorRegistersPublicService) {
+  VirtualKeyboardControllerCreator controller_creator(context_provider()->context());
+
+  zx_status_t status = ZX_OK;
+  fuchsia::input::virtualkeyboard::ControllerCreatorPtr controller_creator_proxy;
+  context_provider()->ConnectToPublicService(controller_creator_proxy.NewRequest());
+  controller_creator_proxy.set_error_handler([&status](zx_status_t stat) { status = stat; });
+
+  fuchsia::input::virtualkeyboard::ControllerPtr controller_proxy;
+  auto view_ref_pair = scenic::ViewRefPair::New();
+  controller_creator_proxy->Create(std::move(view_ref_pair.view_ref),
+                                   fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC,
+                                   controller_proxy.NewRequest());
+  RunLoopUntilIdle();
+
+  ASSERT_EQ(ZX_OK, status) << "status = " << zx_status_get_string(status);
+}
+
+}  // namespace
+}  // namespace virtual_keyboard_controller_creator
+}  // namespace root_presenter
diff --git a/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_unittest.cc b/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_unittest.cc
new file mode 100644
index 0000000..86467b1
--- /dev/null
+++ b/src/ui/bin/root_presenter/tests/virtual_keyboard_controller_unittest.cc
@@ -0,0 +1,60 @@
+// Copyright 2021 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 "src/ui/bin/root_presenter/virtual_keyboard_controller.h"
+
+#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
+#include <fuchsia/ui/views/cpp/fidl.h>
+#include <lib/sys/cpp/component_context.h>
+#include <lib/sys/cpp/testing/component_context_provider.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
+
+#include <gtest/gtest.h>
+#include <src/lib/testing/loop_fixture/test_loop_fixture.h>
+
+namespace root_presenter {
+namespace virtual_keyboard_controller {
+namespace {
+
+class VirtualKeyboardControllerTest : public gtest::TestLoopFixture {
+ protected:
+  VirtualKeyboardControllerTest() { view_ref_pair_ = scenic::ViewRefPair::New(); }
+
+  fuchsia::ui::views::ViewRef view_ref() const {
+    fuchsia::ui::views::ViewRef clone;
+    EXPECT_EQ(ZX_OK, view_ref_pair_.view_ref.Clone(&clone));
+    return clone;
+  }
+
+ private:
+  scenic::ViewRefPair view_ref_pair_;
+};
+
+TEST_F(VirtualKeyboardControllerTest, CtorDoesNotCrash) {
+  VirtualKeyboardController(view_ref(), fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC);
+}
+
+TEST_F(VirtualKeyboardControllerTest, SetTextTypeDoesNotCrash) {
+  VirtualKeyboardController(view_ref(), fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC)
+      .SetTextType(fuchsia::input::virtualkeyboard::TextType::NUMERIC);
+}
+
+TEST_F(VirtualKeyboardControllerTest, RequestShowDoesNotCrash) {
+  VirtualKeyboardController(view_ref(), fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC)
+      .RequestShow();
+}
+
+TEST_F(VirtualKeyboardControllerTest, RequestHideDoesNotCrash) {
+  VirtualKeyboardController(view_ref(), fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC)
+      .RequestHide();
+}
+
+TEST_F(VirtualKeyboardControllerTest, WatchVisibilityDoesNotCrash) {
+  VirtualKeyboardController(view_ref(), fuchsia::input::virtualkeyboard::TextType::ALPHANUMERIC)
+      .WatchVisibility([](bool updated_visibility) {});
+}
+
+}  // namespace
+}  // namespace virtual_keyboard_controller
+}  // namespace root_presenter
diff --git a/src/ui/bin/root_presenter/virtual_keyboard_controller.cc b/src/ui/bin/root_presenter/virtual_keyboard_controller.cc
new file mode 100644
index 0000000..1405840
--- /dev/null
+++ b/src/ui/bin/root_presenter/virtual_keyboard_controller.cc
@@ -0,0 +1,26 @@
+// Copyright 2021 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 "src/ui/bin/root_presenter/virtual_keyboard_controller.h"
+
+#include <lib/syslog/cpp/macros.h>
+
+namespace root_presenter {
+
+VirtualKeyboardController::VirtualKeyboardController(
+    fuchsia::ui::views::ViewRef view_ref, fuchsia::input::virtualkeyboard::TextType text_type) {}
+
+void VirtualKeyboardController::SetTextType(fuchsia::input::virtualkeyboard::TextType text_type) {
+  FX_LOGS(INFO) << __PRETTY_FUNCTION__;
+}
+
+void VirtualKeyboardController::RequestShow() { FX_LOGS(INFO) << __PRETTY_FUNCTION__; }
+
+void VirtualKeyboardController::RequestHide() { FX_LOGS(INFO) << __PRETTY_FUNCTION__; }
+
+void VirtualKeyboardController::WatchVisibility(WatchVisibilityCallback callback) {
+  FX_LOGS(INFO) << __PRETTY_FUNCTION__;
+}
+
+}  // namespace root_presenter
diff --git a/src/ui/bin/root_presenter/virtual_keyboard_controller.h b/src/ui/bin/root_presenter/virtual_keyboard_controller.h
new file mode 100644
index 0000000..f890fcd
--- /dev/null
+++ b/src/ui/bin/root_presenter/virtual_keyboard_controller.h
@@ -0,0 +1,31 @@
+// Copyright 2021 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 SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_H_
+#define SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_H_
+
+#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
+
+#include "fuchsia/ui/views/cpp/fidl.h"
+
+namespace root_presenter {
+
+// Allows callers to request changes in virtual keyboard configuration, and to
+// watch for changes in virtual keyboard visibility.
+class VirtualKeyboardController : public fuchsia::input::virtualkeyboard::Controller {
+ public:
+  VirtualKeyboardController(fuchsia::ui::views::ViewRef view_ref,
+                            fuchsia::input::virtualkeyboard::TextType text_type);
+
+  // |fuchsia.input.virtualkeyboard.Controller|
+  // Called either via IPC, or from unit tests.
+  void SetTextType(::fuchsia::input::virtualkeyboard::TextType text_type) override;
+  void RequestShow() override;
+  void RequestHide() override;
+  void WatchVisibility(WatchVisibilityCallback callback) override;
+};
+
+}  // namespace root_presenter
+
+#endif  // SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_H_
diff --git a/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.cc b/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.cc
new file mode 100644
index 0000000..2e9e061
--- /dev/null
+++ b/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.cc
@@ -0,0 +1,30 @@
+// Copyright 2021 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 "src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h"
+
+#include <lib/syslog/cpp/macros.h>
+
+#include <memory>
+
+#include "src/ui/bin/root_presenter/virtual_keyboard_controller.h"
+
+namespace root_presenter {
+
+VirtualKeyboardControllerCreator::VirtualKeyboardControllerCreator(
+    sys::ComponentContext* component_context) {
+  FX_DCHECK(component_context);
+  component_context->outgoing()->AddPublicService(creator_bindings_.GetHandler(this));
+}
+
+void VirtualKeyboardControllerCreator::Create(
+    fuchsia::ui::views::ViewRef view_ref, fuchsia::input::virtualkeyboard::TextType text_type,
+    fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Controller> controller_request) {
+  FX_LOGS(INFO) << __PRETTY_FUNCTION__;
+  controller_binding_ = std::make_unique<ControllerBinding>(
+      std::make_unique<VirtualKeyboardController>(std::move(view_ref), text_type),
+      std::move(controller_request));
+}
+
+}  // namespace root_presenter
diff --git a/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h b/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h
new file mode 100644
index 0000000..26b5801
--- /dev/null
+++ b/src/ui/bin/root_presenter/virtual_keyboard_controller_creator.h
@@ -0,0 +1,46 @@
+// Copyright 2021 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 SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_CREATOR_H_
+#define SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_CREATOR_H_
+
+#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
+#include <fuchsia/ui/views/cpp/fidl.h>
+#include <lib/fidl/cpp/binding_set.h>
+#include <lib/fidl/cpp/interface_request.h>
+#include <lib/sys/cpp/component_context.h>
+
+#include <memory>
+
+namespace root_presenter {
+
+// Enables the binding of one or more `fuchsia.input.virtualkeyboard.Controller`s with
+// a virtual keyboard. A `VirtualKeyboardControllerCreator` and its `VirtualKeyboardController`s
+// are associated with a single virtual keyboard.
+class VirtualKeyboardControllerCreator : public fuchsia::input::virtualkeyboard::ControllerCreator {
+ public:
+  // Constructs an object which can serve the `fuchsia.input.virtualkeyboard.ControllerCreator`
+  // FIDL protocol, and publishes the protocol using `component_context`.
+  //
+  // Callers _should_ construct this object before entering the event loop.
+  explicit VirtualKeyboardControllerCreator(sys::ComponentContext* component_context);
+
+ private:
+  using ControllerBinding =
+      fidl::Binding<fuchsia::input::virtualkeyboard::Controller,
+                    std::unique_ptr<fuchsia::input::virtualkeyboard::Controller>>;
+
+  // |fuchsia.input.virtualkeyboard.ControllerCreator|
+  void Create(fuchsia::ui::views::ViewRef view_ref,
+              fuchsia::input::virtualkeyboard::TextType text_type,
+              fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Controller>
+                  controller_request) override;
+
+  fidl::BindingSet<fuchsia::input::virtualkeyboard::ControllerCreator> creator_bindings_;
+  std::unique_ptr<ControllerBinding> controller_binding_;
+};
+
+}  // namespace root_presenter
+
+#endif  // SRC_UI_BIN_ROOT_PRESENTER_VIRTUAL_KEYBOARD_CONTROLLER_CREATOR_H_