Add C interface for virtual touchpad client.

For use by the dvr api.

Changes VrWindowManager::ShellView to exercise this change,
and because it will be used when that code relocates to VrCore.

Bug: 36050790
Test: use in vr_wm.
Change-Id: I0fa67d19f94939ae41ef0ea2338f92f6147a4111
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index ad999b7..c8bc884 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -94,6 +94,7 @@
 
 client_src = [
     "VirtualTouchpadClient.cpp",
+    "DvrVirtualTouchpadClient.cpp",
     "aidl/android/dvr/VirtualTouchpadService.aidl",
 ]
 
diff --git a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
new file mode 100644
index 0000000..eb152ed
--- /dev/null
+++ b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
@@ -0,0 +1,45 @@
+#include "VirtualTouchpadClient.h"
+#include "dvr/virtual_touchpad_client.h"
+
+struct DvrVirtualTouchpad {};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+namespace {
+android::dvr::VirtualTouchpad* FromC(DvrVirtualTouchpad* client) {
+  return reinterpret_cast<android::dvr::VirtualTouchpad*>(client);
+}
+}  // namespace
+
+DvrVirtualTouchpad* dvrVirtualTouchpadCreate() {
+  return reinterpret_cast<DvrVirtualTouchpad*>(
+      android::dvr::VirtualTouchpadClient::Create().release());
+}
+
+void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client) {
+  delete FromC(client);
+}
+
+int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client) {
+  return FromC(client)->Attach();
+}
+
+int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client) {
+  return FromC(client)->Detach();
+}
+
+int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x,
+                            float y, float pressure) {
+  return FromC(client)->Touch(touchpad, x, y, pressure);
+}
+
+int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
+                                  int buttons) {
+  return FromC(client)->ButtonState(touchpad, buttons);
+}
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index 782b19c..c7c8184 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -72,8 +72,8 @@
 
 }  // anonymous namespace
 
-sp<VirtualTouchpad> VirtualTouchpadClient::Create() {
-  return new VirtualTouchpadClientImpl();
+std::unique_ptr<VirtualTouchpad> VirtualTouchpadClient::Create() {
+  return std::unique_ptr<VirtualTouchpad>(new VirtualTouchpadClientImpl());
 }
 
 }  // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index 92193d3..ee09d48 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -30,10 +30,10 @@
 
 }  // anonymous namespace
 
-sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
-  VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
+std::unique_ptr<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
+  std::unique_ptr<VirtualTouchpadEvdev> touchpad(new VirtualTouchpadEvdev());
   touchpad->Reset();
-  return sp<VirtualTouchpad>(touchpad);
+  return touchpad;
 }
 
 void VirtualTouchpadEvdev::Reset() {
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index dbaca9a..2fb8ff3 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -1,8 +1,6 @@
 #ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
 #define ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
 
-#include <memory>
-
 #include "EvdevInjector.h"
 #include "VirtualTouchpad.h"
 
@@ -15,7 +13,8 @@
 //
 class VirtualTouchpadEvdev : public VirtualTouchpad {
  public:
-  static sp<VirtualTouchpad> Create();
+  static std::unique_ptr<VirtualTouchpad> Create();
+  ~VirtualTouchpadEvdev() override {}
 
   // VirtualTouchpad implementation:
   status_t Attach() override;
@@ -28,7 +27,6 @@
   static constexpr int kTouchpads = 2;
 
   VirtualTouchpadEvdev() {}
-  ~VirtualTouchpadEvdev() override {}
   void Reset();
 
   // Must be called only between construction (or Detach()) and Attach().
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 194d787..cf236f9 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,8 +13,8 @@
 //
 class VirtualTouchpadService : public BnVirtualTouchpadService {
  public:
-  VirtualTouchpadService(sp<VirtualTouchpad> touchpad)
-      : touchpad_(touchpad), client_pid_(0) {}
+  VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
+      : touchpad_(std::move(touchpad)), client_pid_(0) {}
   ~VirtualTouchpadService() override;
 
  protected:
@@ -31,7 +31,7 @@
   bool CheckPermissions();
   bool CheckTouchPermission(pid_t* out_pid);
 
-  sp<VirtualTouchpad> touchpad_;
+  std::unique_ptr<VirtualTouchpad> touchpad_;
 
   // Only one client at a time can use the virtual touchpad.
   pid_t client_pid_;
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index b1ee700..da3a0b7 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -1,31 +1,34 @@
 #ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
 #define ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
 
+#include "dvr/virtual_touchpad_client.h"
+
+#include <memory>
 #include <utils/Errors.h>
-#include <utils/RefBase.h>
 #include <utils/String8.h>
-#include <utils/StrongPointer.h>
 
 namespace android {
 namespace dvr {
 
 // Provides a virtual touchpad for injecting events into the input system.
 //
-class VirtualTouchpad : public RefBase {
+class VirtualTouchpad {
  public:
   enum : int {
-    PRIMARY = 0,
-    VIRTUAL = 1,
+    PRIMARY = DVR_VIRTUAL_TOUCHPAD_PRIMARY,
+    VIRTUAL = DVR_VIRTUAL_TOUCHPAD_VIRTUAL,
   };
 
+  virtual ~VirtualTouchpad() {}
+
   // Create a virtual touchpad.
   // Implementations should provide this, and hide their constructors.
   // For the user, switching implementations should be as simple as changing
   // the class whose |Create()| is called.
   // Implementations should be minimial; major resource allocation should
   // be performed in Attach().
-  static sp<VirtualTouchpad> Create() {
-    return sp<VirtualTouchpad>();
+  static std::unique_ptr<VirtualTouchpad> Create() {
+    return nullptr;
   }
 
   // Initialize a virtual touchpad.
@@ -63,7 +66,6 @@
 
  protected:
   VirtualTouchpad() {}
-  ~VirtualTouchpad() override {}
 
  private:
   VirtualTouchpad(const VirtualTouchpad&) = delete;
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 471d9e0..23fb9f8 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -12,7 +12,7 @@
 class VirtualTouchpadClient : public VirtualTouchpad {
  public:
   // VirtualTouchpad implementation:
-  static sp<VirtualTouchpad> Create();
+  static std::unique_ptr<VirtualTouchpad> Create();
   status_t Attach() override;
   status_t Detach() override;
   status_t Touch(int touchpad, float x, float y, float pressure) override;
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
new file mode 100644
index 0000000..08cca1b
--- /dev/null
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -0,0 +1,71 @@
+#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
+#define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
+
+enum {
+  DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
+  DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
+};
+
+// Creates a new virtual touchpad client.
+//
+// @return Pointer to the created virtual touchpad client; nullptr on failure.
+//
+DvrVirtualTouchpad* dvrVirtualTouchpadCreate();
+
+// Destroys a virtual touchpad client.
+//
+// @param client Pointer to the virtual touchpad client to be destroyed.
+//
+void dvrVirtualTouchpadDestroy(DvrVirtualTouchpad* client);
+
+// Initialize the virtual touchpad.
+//
+// In the current server implementation, attachment creates and configures
+// the kernel virtual touchpad device(s). A single client may be attached
+// and detached repeatedly, e.g. on entering and leaving VR mode.
+//
+// @param client Pointer to the virtual touchpad client to be attached.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadAttach(DvrVirtualTouchpad* client);
+
+// Shut down the virtual touchpad.
+//
+// @param client Pointer to the virtual touchpad client to be detached.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadDetach(DvrVirtualTouchpad* client);
+
+// Generate a simulated touch event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param x Horizontal touch position.
+// @param y Vertical touch position.
+// @param pressure Touch pressure; use 0.0 for no touch (lift or hover).
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadTouch(DvrVirtualTouchpad* client, int touchpad, float x,
+                            float y, float pressure);
+
+// Generate a simulated touchpad button state event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param buttons A union of MotionEvent BUTTON_* values.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
+                                  int buttons);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H
diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp
index e73f8b9..68f1d70 100644
--- a/services/vr/virtual_touchpad/main.cpp
+++ b/services/vr/virtual_touchpad/main.cpp
@@ -9,7 +9,7 @@
 int main() {
   ALOGI("Starting");
   android::dvr::VirtualTouchpadService touchpad_service(
-      android::dvr::VirtualTouchpadEvdev::Create());
+      std::move(android::dvr::VirtualTouchpadEvdev::Create()));
 
   signal(SIGPIPE, SIG_IGN);
   android::sp<android::ProcessState> ps(android::ProcessState::self());
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index bc34850..24cfdf8 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -95,7 +95,9 @@
 
 class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
  public:
-  static sp<VirtualTouchpad> Create() { return sp<VirtualTouchpad>(New()); }
+  static std::unique_ptr<VirtualTouchpad> Create() {
+    return std::unique_ptr<VirtualTouchpad>(New());
+  }
   static VirtualTouchpadForTesting* New() {
     VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
     touchpad->Reset();
@@ -124,7 +126,8 @@
 class VirtualTouchpadTest : public testing::Test {};
 
 TEST_F(VirtualTouchpadTest, Goodness) {
-  sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
+  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
+      VirtualTouchpadForTesting::New());
   UInputRecorder expect;
 
   status_t touch_status = touchpad->Attach();
@@ -284,7 +287,8 @@
 }
 
 TEST_F(VirtualTouchpadTest, Badness) {
-  sp<VirtualTouchpadForTesting> touchpad(VirtualTouchpadForTesting::New());
+  std::unique_ptr<VirtualTouchpadForTesting> touchpad(
+      VirtualTouchpadForTesting::New());
   UInputRecorder expect;
   UInputRecorder& record = touchpad->injector[VirtualTouchpad::PRIMARY].record;
 
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 72a2c26..80a3ec2 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -95,7 +95,8 @@
 }
 
 int GetTouchIdForDisplay(uint32_t display) {
-  return display == 1 ? VirtualTouchpad::PRIMARY : VirtualTouchpad::VIRTUAL;
+  return display == 1 ? DVR_VIRTUAL_TOUCHPAD_PRIMARY
+                      : DVR_VIRTUAL_TOUCHPAD_VIRTUAL;
 }
 
 }  // namespace
@@ -109,8 +110,9 @@
   if (ret)
     return ret;
 
-  virtual_touchpad_ = VirtualTouchpadClient::Create();
-  const status_t touchpad_status = virtual_touchpad_->Attach();
+  virtual_touchpad_.reset(dvrVirtualTouchpadCreate());
+  const status_t touchpad_status =
+      dvrVirtualTouchpadAttach(virtual_touchpad_.get());
   if (touchpad_status != OK) {
     ALOGE("Failed to connect to virtual touchpad");
     return touchpad_status;
@@ -164,13 +166,11 @@
 }
 
 void ShellView::EnableDebug(bool debug) {
-  ALOGI("EnableDebug(%d)", (int)debug);  // XXX TODO delete
   QueueTask(debug ? MainThreadTask::EnableDebugMode
                   : MainThreadTask::DisableDebugMode);
 }
 
 void ShellView::VrMode(bool mode) {
-  ALOGI("VrMode(%d)", (int)mode);  // XXX TODO delete
   QueueTask(mode ? MainThreadTask::EnteringVrMode
                  : MainThreadTask::ExitingVrMode);
 }
@@ -419,7 +419,7 @@
 }
 
 void ShellView::Touch() {
-  if (!virtual_touchpad_.get()) {
+  if (!virtual_touchpad_) {
     ALOGE("missing virtual touchpad");
     return;
   }
@@ -431,8 +431,8 @@
 
   // Device is portrait, but in landscape when in VR.
   // Rotate touch input appropriately.
-  const android::status_t status = virtual_touchpad_->Touch(
-      active_display_->touchpad_id(),
+  const android::status_t status = dvrVirtualTouchpadTouch(
+      virtual_touchpad_.get(), active_display_->touchpad_id(),
       1.0f - hit_location.y() / size_.y(), hit_location.x() / size_.x(),
       is_touching_ ? 1.0f : 0.0f);
   if (status != OK) {
@@ -453,7 +453,7 @@
     return true;
   }
   touchpad_buttons_ = buttons;
-  if (!virtual_touchpad_.get()) {
+  if (!virtual_touchpad_) {
     ALOGE("missing virtual touchpad");
     return false;
   }
@@ -461,8 +461,9 @@
   if (!active_display_)
     return true;
 
-  const android::status_t status = virtual_touchpad_->ButtonState(
-      active_display_->touchpad_id(), touchpad_buttons_);
+  const android::status_t status = dvrVirtualTouchpadButtonState(
+      virtual_touchpad_.get(), active_display_->touchpad_id(),
+      touchpad_buttons_);
   if (status != OK) {
     ALOGE("touchpad button failed: %d %d", touchpad_buttons_, status);
   }
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index c10bd27..856c8b8 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -1,12 +1,12 @@
 #ifndef VR_WINDOW_MANAGER_SHELL_VIEW_H_
 #define VR_WINDOW_MANAGER_SHELL_VIEW_H_
 
+#include <dvr/virtual_touchpad_client.h>
 #include <private/dvr/graphics/mesh.h>
 #include <private/dvr/graphics/shader_program.h>
 
 #include <deque>
 
-#include "VirtualTouchpadClient.h"
 #include "application.h"
 #include "display_view.h"
 #include "reticle.h"
@@ -53,7 +53,6 @@
   DisplayView* FindActiveDisplay(const vec3& position, const quat& quaternion,
                                  vec3* hit_location);
 
-
   // HwcCallback::Client:
   base::unique_fd OnFrame(std::unique_ptr<HwcCallback::Frame> frame) override;
   DisplayView* FindOrCreateDisplay(uint32_t id);
@@ -64,7 +63,15 @@
 
   std::unique_ptr<SurfaceFlingerView> surface_flinger_view_;
   std::unique_ptr<Reticle> reticle_;
-  sp<VirtualTouchpad> virtual_touchpad_;
+
+  struct DvrVirtualTouchpadDeleter {
+    void operator()(DvrVirtualTouchpad* p) {
+      dvrVirtualTouchpadDetach(p);
+      dvrVirtualTouchpadDestroy(p);
+    }
+  };
+  std::unique_ptr<DvrVirtualTouchpad, DvrVirtualTouchpadDeleter>
+      virtual_touchpad_;
 
   std::unique_ptr<Mesh<vec3, vec3, vec2>> controller_mesh_;