Merge "split libsensor our of libgui "
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a84b051..fbb30db 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1252,7 +1252,7 @@
             calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                     sharedGid, -1);
         }
-        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+        calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize,
                 multiuser_get_uid(userId, appId), -1);
         ATRACE_END();
     }
@@ -1350,7 +1350,7 @@
         ATRACE_BEGIN("dalvik");
         calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
                 -1, -1, true);
-        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+        calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize,
                 -1, -1, true);
         ATRACE_END();
 
@@ -1400,7 +1400,7 @@
 
         ATRACE_BEGIN("dalvik");
         calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
-        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize);
+        calculate_tree_size(create_data_user_profile_path(userId), &stats.dataSize);
         ATRACE_END();
     }
 
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 6d50f55..2bf0171 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -239,10 +239,6 @@
     return "/data/dalvik-cache";
 }
 
-std::string create_data_misc_foreign_dex_path(userid_t userid) {
-    return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid);
-}
-
 // Keep profile paths in sync with ActivityThread.
 constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
 
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index aa83dc2..d99b445 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -103,7 +103,6 @@
 std::string create_data_ref_profile_package_path(const char* package_name);
 
 std::string create_data_dalvik_cache_path();
-std::string create_data_misc_foreign_dex_path(userid_t userid);
 
 std::string create_primary_profile(const std::string& profile_dir);
 
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 7646feb..9e60461 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -294,7 +294,7 @@
 static const std::string &getArchString(Architecture arch) {
     static const std::string sStr64 = "64";
     static const std::string sStr32 = "32";
-    static const std::string sStrBoth = "64&32";
+    static const std::string sStrBoth = "32+64";
     static const std::string sStrUnknown = "";
     switch (arch) {
         case ARCH64:
@@ -325,12 +325,12 @@
     mServicesTable.description =
             "All binderized services (registered services through hwservicemanager)";
     mPassthroughRefTable.description =
-            "All interfaces that getService() has ever return a passthrough interface;\n"
+            "All interfaces that getService() has ever return as a passthrough interface;\n"
             "PIDs / processes shown below might be inaccurate because the process\n"
-            "might have relinquish the interface or might have died.\n"
+            "might have relinquished the interface or might have died.\n"
             "The Server / Server CMD column can be ignored.\n"
-            "The Clients / Clients CMD column shows all process that have ever dlopen the library\n"
-            "and successfully fetch the passthrough implementation.";
+            "The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
+            "the library and successfully fetched the passthrough implementation.";
     mImplementationsTable.description =
             "All available passthrough implementations (all -impl.so files)";
     forEachTable([this] (const Table &table) {
@@ -393,7 +393,7 @@
         for (const auto &info : infos) {
             std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
                     std::string{info.instanceName.c_str()};
-            entries.emplace(std::string{interfaceName}, TableEntry{
+            entries.emplace(interfaceName, TableEntry{
                 .interfaceName = interfaceName,
                 .transport = "passthrough",
                 .serverPid = NO_PID,
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 9485d5b..9294419 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -17,7 +17,11 @@
 cc_library {
     name: "libinput",
     host_supported: true,
-
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
     srcs: [
         "Input.cpp",
         "InputDevice.cpp",
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 9d761fd..4287abe 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -90,7 +90,7 @@
     String8 path;
 
     // Treblized input device config files will be located /odm/usr or /vendor/usr.
-    char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
+    const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
     for (size_t i = 0; i < size(rootsForPartition); i++) {
         path.setTo(rootsForPartition[i]);
         path.append("/usr/");
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 9a01395..07f2289 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -208,7 +208,6 @@
 }
 
 int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
-    int32_t mask;
     switch (keyCode) {
     case AKEYCODE_ALT_LEFT:
         return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
diff --git a/libs/vr/libposepredictor/predictor.cpp b/libs/vr/libposepredictor/predictor.cpp
index 266e7ef..4d2eafd 100644
--- a/libs/vr/libposepredictor/predictor.cpp
+++ b/libs/vr/libposepredictor/predictor.cpp
@@ -8,7 +8,7 @@
   const auto delta_q = b.inverse() * a;
   // Check that delta_q.w() == 1, Eigen doesn't respect this convention. If
   // delta_q.w() == -1, we'll get the opposite velocity.
-  return 2.0 * (delta_q.w() < 0 ? -delta_q.vec() : delta_q.vec()) / delta_time;
+  return 2.0 * (delta_q.w() < 0 ? static_cast<vec3>(-delta_q.vec()) : delta_q.vec()) / delta_time;
 }
 
 Velocity Predictor::PredictVelocity(int64_t time_ns) const {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 0ac74db..740ead3 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -623,9 +623,9 @@
 #define EGL_ANDROID_get_native_client_buffer 1
 struct AHardwareBuffer;
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const AHardwareBuffer *buffer);
+EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
 #else
-typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const AHardwareBuffer *buffer);
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);
 #endif
 #endif
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 3359c64..e52713f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -126,6 +126,7 @@
         "EGL_EXT_yuv_surface "
         "EGL_EXT_protected_content "
         "EGL_IMG_context_priority "
+        "EGL_KHR_no_config_context "
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 3edd50b..7bd495f 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -13,21 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <sys/types.h>
+#include "SensorDevice.h"
+#include "SensorService.h"
 
 #include <android-base/logging.h>
+#include <sensors/convert.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/Singleton.h>
 
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-#include <sensors/convert.h>
+#include <chrono>
+#include <cinttypes>
+#include <thread>
 
 using android::hardware::hidl_vec;
 
@@ -55,13 +52,38 @@
 }
 
 SensorDevice::SensorDevice() {
-    mSensors = ISensors::getService();
+    // SensorDevice may wait upto 100ms * 10 = 1s for hidl service.
+    constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
+    size_t retry = 10;
 
-    if (mSensors == NULL) {
-        return;
+    while (true) {
+        int initStep = 0;
+        mSensors = ISensors::getService();
+        if (mSensors != nullptr) {
+            ++initStep;
+            // Poke ISensor service. If it has lingering connection from previous generation of
+            // system server, it will kill itself. There is no intention to handle the poll result,
+            // which will be done since the size is 0.
+            if(mSensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
+                // ok to continue
+                break;
+            }
+            // hidl service is restarting, pointer is invalid.
+            mSensors = nullptr;
+        }
+
+        if (--retry <= 0) {
+            ALOGE("Cannot connect to ISensors hidl service!");
+            return;
+        }
+        // Delay 100ms before retry, hidl service is expected to come up in short time after
+        // crash.
+        ALOGI("%s unsuccessful, try again soon (remaining retry %zu).",
+                (initStep == 0) ? "getService()" : "poll() check", retry);
+        std::this_thread::sleep_for(RETRY_DELAY);
     }
 
-    mSensors->getSensorsList(
+    checkReturn(mSensors->getSensorsList(
             [&](const auto &list) {
                 const size_t count = list.size();
 
@@ -74,19 +96,19 @@
 
                     mActivationCount.add(list[i].sensorHandle, model);
 
-                    mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
+                    checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
                 }
-            });
+            }));
 
     mIsDirectReportSupported =
-           (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION);
+           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
 }
 
 void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
     if (connected) {
         Info model;
         mActivationCount.add(handle, model);
-        mSensors->activate(handle, 0 /* enabled */);
+        checkReturn(mSensors->activate(handle, 0 /* enabled */));
     } else {
         mActivationCount.removeItem(handle);
     }
@@ -96,7 +118,7 @@
     if (mSensors == NULL) return "HAL not initialized\n";
 
     String8 result;
-    mSensors->getSensorsList([&](const auto &list) {
+    checkReturn(mSensors->getSensorsList([&](const auto &list) {
             const size_t count = list.size();
 
             result.appendFormat(
@@ -141,7 +163,7 @@
                         "}, selected = %.1f ms\n",
                         info.bestBatchParams.batchTimeout / 1e6f);
             }
-        });
+        }));
 
     return result.string();
 }
@@ -161,7 +183,7 @@
 
     ssize_t err;
 
-    mSensors->poll(
+    checkReturn(mSensors->poll(
             count,
             [&](auto result,
                 const auto &events,
@@ -172,7 +194,7 @@
                 } else {
                     err = StatusFromResult(result);
                 }
-            });
+            }));
 
     return err;
 }
@@ -237,10 +259,10 @@
                          "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
                          info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                          info.bestBatchParams.batchTimeout);
-                mSensors->batch(
+                checkReturn(mSensors->batch(
                         handle,
                         info.bestBatchParams.batchDelay,
-                        info.bestBatchParams.batchTimeout);
+                        info.bestBatchParams.batchTimeout));
             }
         } else {
             // sensor wasn't enabled for this ident
@@ -254,7 +276,7 @@
     if (actuateHardware) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                  enabled);
-        err = StatusFromResult(mSensors->activate(handle, enabled));
+        err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
         ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                  strerror(-err));
 
@@ -311,10 +333,10 @@
                  info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                  info.bestBatchParams.batchTimeout);
         err = StatusFromResult(
-                mSensors->batch(
+                checkReturn(mSensors->batch(
                     handle,
                     info.bestBatchParams.batchDelay,
-                    info.bestBatchParams.batchTimeout));
+                    info.bestBatchParams.batchTimeout)));
         if (err != NO_ERROR) {
             ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
                   mSensors.get(), handle,
@@ -348,7 +370,7 @@
     info.selectBatchParams();
 
     return StatusFromResult(
-            mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
+            checkReturn(mSensors->batch(handle, info.bestBatchParams.batchDelay, 0)));
 }
 
 int SensorDevice::getHalDeviceVersion() const {
@@ -359,7 +381,7 @@
 status_t SensorDevice::flush(void* ident, int handle) {
     if (isClientDisabled(ident)) return INVALID_OPERATION;
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return StatusFromResult(mSensors->flush(handle));
+    return StatusFromResult(checkReturn(mSensors->flush(handle)));
 }
 
 bool SensorDevice::isClientDisabled(void* ident) {
@@ -383,15 +405,15 @@
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                    sensor_handle);
         status_t err = StatusFromResult(
-                mSensors->batch(
+                checkReturn(mSensors->batch(
                     sensor_handle,
                     info.bestBatchParams.batchDelay,
-                    info.bestBatchParams.batchTimeout));
+                    info.bestBatchParams.batchTimeout)));
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
             err = StatusFromResult(
-                    mSensors->activate(sensor_handle, 1 /* enabled */));
+                    checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
     }
@@ -406,7 +428,7 @@
            const int sensor_handle = mActivationCount.keyAt(i);
            ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
                    sensor_handle);
-           mSensors->activate(sensor_handle, 0 /* enabled */);
+           checkReturn(mSensors->activate(sensor_handle, 0 /* enabled */));
 
            // Add all the connections that were registered for this sensor to the disabled
            // clients list.
@@ -431,14 +453,14 @@
     Event ev;
     convertFromSensorEvent(*injected_sensor_event, &ev);
 
-    return StatusFromResult(mSensors->injectSensorData(ev));
+    return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
 
      return StatusFromResult(
-             mSensors->setOperationMode(
-                 static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+             checkReturn(mSensors->setOperationMode(
+                 static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
 }
 
 // ---------------------------------------------------------------------------
@@ -529,20 +551,20 @@
     };
 
     int32_t ret;
-    mSensors->registerDirectChannel(mem,
+    checkReturn(mSensors->registerDirectChannel(mem,
             [&ret](auto result, auto channelHandle) {
                 if (result == Result::OK) {
                     ret = channelHandle;
                 } else {
                     ret = StatusFromResult(result);
                 }
-            });
+            }));
     return ret;
 }
 
 void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
     Mutex::Autolock _l(mLock);
-    mSensors->unregisterDirectChannel(channelHandle);
+    checkReturn(mSensors->unregisterDirectChannel(channelHandle));
 }
 
 int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
@@ -568,7 +590,7 @@
     }
 
     int32_t ret;
-    mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+    checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
             [&ret, rate] (auto result, auto token) {
                 if (rate == RateLevel::STOP) {
                     ret = StatusFromResult(result);
@@ -579,7 +601,7 @@
                         ret = StatusFromResult(result);
                     }
                 }
-            });
+            }));
 
     return ret;
 }
@@ -635,5 +657,10 @@
     }
 }
 
+void SensorDevice::handleHidlDeath(const std::string & detail) {
+    // restart is the only option at present.
+    LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 818656c..03552f6 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -37,6 +37,7 @@
 
 // ---------------------------------------------------------------------------
 using SensorServiceUtil::Dumpable;
+using hardware::Return;
 
 class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
 public:
@@ -128,6 +129,15 @@
     SortedVector<void *> mDisabledClients;
     SensorDevice();
 
+    static void handleHidlDeath(const std::string &detail);
+    template<typename T>
+    static Return<T> checkReturn(Return<T> &&ret) {
+        if (!ret.isOk()) {
+            handleHidlDeath(ret.description());
+        }
+        return std::move(ret);
+    }
+
     bool isClientDisabled(void* ident);
     bool isClientDisabledLocked(void* ident);
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 92ede08..caa7adc 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -242,7 +242,11 @@
     static status_t orientationToTransfrom(int orientation,
             int w, int h, Transform* tr);
 
+    // The identifier of the active layer stack for this display. Several displays
+    // can use the same layer stack: A z-ordered group of layers (sometimes called
+    // "surfaces"). Any given layer can only be on a single layer stack.
     uint32_t mLayerStack;
+
     int mOrientation;
     static uint32_t sPrimaryDisplayOrientation;
     // user-provided visible area of the layer stack
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f2e5f22..e2b2a3a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -109,7 +109,14 @@
         Geometry active;
         Geometry requested;
         int32_t z;
+
+        // The identifier of the layer stack this layer belongs to. A layer can
+        // only be associated to a single layer stack. A layer stack is a
+        // z-ordered group of layers which can be associated to one or more
+        // displays. Using the same layer stack on different displays is a way
+        // to achieve mirroring.
         uint32_t layerStack;
+
 #ifdef USE_HWC2
         float alpha;
 #else
@@ -697,6 +704,11 @@
         Rect displayFrame;
         FloatRect sourceCrop;
     };
+
+    // A layer can be attached to multiple displays when operating in mirror mode
+    // (a.k.a: when several displays are attached with equal layerStack). In this
+    // case we need to keep track. In non-mirror mode, a layer will have only one.
+    // HWCInfo. This map key is a display layerStack.
     std::unordered_map<int32_t, HWCInfo> mHwcLayers;
 
     // We need one HWComposerBufferCache for each HWC display.  We cannot have
diff --git a/services/vr/virtual_touchpad/Android.mk b/services/vr/virtual_touchpad/Android.mk
index 4224aaa..b78eb99 100644
--- a/services/vr/virtual_touchpad/Android.mk
+++ b/services/vr/virtual_touchpad/Android.mk
@@ -6,13 +6,14 @@
 
 src := \
   EvdevInjector.cpp \
-  VirtualTouchpad.cpp
+  VirtualTouchpadEvdev.cpp
 
 shared_libs := \
   libbase
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(src)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_SHARED_LIBRARIES := $(shared_libs)
 LOCAL_CPPFLAGS += -std=c++11
 LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\"
@@ -29,11 +30,13 @@
 static_libs := \
   libbase \
   libcutils \
+  libutils \
   libvirtualtouchpad
 
 $(foreach file,$(test_src_files), \
     $(eval include $(CLEAR_VARS)) \
     $(eval LOCAL_SRC_FILES := $(file)) \
+    $(eval LOCAL_C_INCLUDES := $(LOCAL_PATH)/include) \
     $(eval LOCAL_STATIC_LIBRARIES := $(static_libs)) \
     $(eval LOCAL_SHARED_LIBRARIES := $(shared_libs)) \
     $(eval LOCAL_CPPFLAGS += -std=c++11) \
@@ -63,6 +66,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(src)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES := $(static_libs)
 LOCAL_SHARED_LIBRARIES := $(shared_libs)
 LOCAL_CPPFLAGS += -std=c++11
@@ -74,3 +78,27 @@
 LOCAL_MULTILIB := 64
 LOCAL_CXX_STL := libc++_static
 include $(BUILD_EXECUTABLE)
+
+
+# Touchpad client library.
+
+src := \
+  VirtualTouchpadClient.cpp \
+  aidl/android/dvr/VirtualTouchpadService.aidl
+
+shared_libs := \
+  libbase \
+  libbinder \
+  libutils
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(src)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := $(shared_libs)
+LOCAL_CPPFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_TAG=\"VirtualTouchpadClient\"
+LOCAL_LDLIBS := -llog
+LOCAL_MODULE := libvirtualtouchpadclient
+LOCAL_MODULE_TAGS := optional
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
diff --git a/services/vr/virtual_touchpad/VirtualTouchpad.h b/services/vr/virtual_touchpad/VirtualTouchpad.h
deleted file mode 100644
index 17aeb35..0000000
--- a/services/vr/virtual_touchpad/VirtualTouchpad.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_H
-#define ANDROID_DVR_VIRTUAL_TOUCHPAD_H
-
-#include <memory>
-
-#include "EvdevInjector.h"
-
-namespace android {
-namespace dvr {
-
-class EvdevInjector;
-
-// Provides a virtual touchpad for injecting events into the input system.
-//
-class VirtualTouchpad {
- public:
-  VirtualTouchpad() {}
-  ~VirtualTouchpad() {}
-
-  // |Intialize()| must be called once on a VirtualTouchpad before
-  // and other public method. Returns zero on success.
-  int Initialize();
-
-  // Generate a simulated touch event.
-  //
-  // @param x Horizontal touch position.
-  // @param y Vertical touch position.
-  //            Values must be in the range [0.0, 1.0).
-  // @param pressure Touch pressure.
-  //            Positive values represent contact; use 1.0f if contact
-  //            is binary. Use 0.0f for no contact.
-  // @returns Zero on success.
-  //
-  int Touch(float x, float y, float pressure);
-
-  // Generate a simulated touchpad button state.
-  //
-  // @param buttons A union of MotionEvent BUTTON_* values.
-  // @returns Zero on success.
-  //
-  // Currently only BUTTON_BACK is supported, as the implementation
-  // restricts itself to operations actually required by VrWindowManager.
-  //
-  int ButtonState(int buttons);
-
- protected:
-  // Must be called only between construction and Initialize().
-  inline void SetEvdevInjectorForTesting(EvdevInjector* injector) {
-    injector_ = injector;
-  }
-
- private:
-  // Except for testing, the |EvdevInjector| used to inject evdev events.
-  std::unique_ptr<EvdevInjector> owned_injector_;
-
-  // Active pointer to |owned_injector_| or to a testing injector.
-  EvdevInjector* injector_ = nullptr;
-
-  // Previous (x, y) position in device space, to suppress redundant events.
-  int32_t last_device_x_ = INT32_MIN;
-  int32_t last_device_y_ = INT32_MIN;
-
-  // Records current touch state (0=up 1=down) in bit 0, and previous state
-  // in bit 1, to track transitions.
-  int touches_ = 0;
-
-  // Previous injected button state, to detect changes.
-  int32_t last_motion_event_buttons_ = 0;
-
-  VirtualTouchpad(const VirtualTouchpad&) = delete;
-  void operator=(const VirtualTouchpad&) = delete;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_VIRTUAL_TOUCHPAD_H
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
new file mode 100644
index 0000000..23a2e31
--- /dev/null
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -0,0 +1,52 @@
+#include "VirtualTouchpadClient.h"
+
+#include <android/dvr/IVirtualTouchpadService.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
+ public:
+  VirtualTouchpadClientImpl(sp<IVirtualTouchpadService> service)
+      : service_(service) {}
+  ~VirtualTouchpadClientImpl() {}
+
+  status_t Touch(float x, float y, float pressure) override {
+    if (service_ == nullptr) {
+      return NO_INIT;
+    }
+    return service_->touch(x, y, pressure).transactionError();
+  }
+  status_t ButtonState(int buttons) override {
+    if (service_ == nullptr) {
+      return NO_INIT;
+    }
+    return service_->buttonState(buttons).transactionError();
+  }
+
+ private:
+  sp<IVirtualTouchpadService> service_;
+};
+
+}  // anonymous namespace
+
+sp<VirtualTouchpad> VirtualTouchpadClient::Create() {
+  sp<IServiceManager> sm = defaultServiceManager();
+  if (sm == nullptr) {
+    ALOGE("no service manager");
+    return sp<VirtualTouchpad>();
+  }
+  sp<IVirtualTouchpadService> service = interface_cast<IVirtualTouchpadService>(
+      sm->getService(IVirtualTouchpadService::SERVICE_NAME()));
+  if (service == nullptr) {
+    ALOGE("failed to get service");
+    return sp<VirtualTouchpad>();
+  }
+  return new VirtualTouchpadClientImpl(service);
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/services/vr/virtual_touchpad/VirtualTouchpad.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
similarity index 87%
rename from services/vr/virtual_touchpad/VirtualTouchpad.cpp
rename to services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index 4793058..ae31156 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpad.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -1,4 +1,4 @@
-#include "VirtualTouchpad.h"
+#include "VirtualTouchpadEvdev.h"
 
 #include <android/input.h>
 #include <inttypes.h>
@@ -30,7 +30,17 @@
 
 }  // anonymous namespace
 
-int VirtualTouchpad::Initialize() {
+sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
+  VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
+  const status_t status = touchpad->Initialize();
+  if (status) {
+    ALOGE("initialization failed: %d", status);
+    return sp<VirtualTouchpad>();
+  }
+  return sp<VirtualTouchpad>(touchpad);
+}
+
+int VirtualTouchpadEvdev::Initialize() {
   if (!injector_) {
     owned_injector_.reset(new EvdevInjector());
     injector_ = owned_injector_.get();
@@ -46,7 +56,7 @@
   return injector_->GetError();
 }
 
-int VirtualTouchpad::Touch(float x, float y, float pressure) {
+int VirtualTouchpadEvdev::Touch(float x, float y, float pressure) {
   if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
     return EINVAL;
   }
@@ -91,7 +101,7 @@
   return injector_->GetError();
 }
 
-int VirtualTouchpad::ButtonState(int buttons) {
+int VirtualTouchpadEvdev::ButtonState(int buttons) {
   const int changes = last_motion_event_buttons_ ^ buttons;
   if (!changes) {
     return 0;
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
new file mode 100644
index 0000000..c763529
--- /dev/null
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -0,0 +1,59 @@
+#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
+#define ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
+
+#include <memory>
+
+#include "VirtualTouchpad.h"
+#include "EvdevInjector.h"
+
+namespace android {
+namespace dvr {
+
+class EvdevInjector;
+
+// VirtualTouchpadEvdev implements a VirtualTouchpad by injecting evdev events.
+//
+class VirtualTouchpadEvdev : public VirtualTouchpad {
+ public:
+  static sp<VirtualTouchpad> Create();
+
+  // VirtualTouchpad implementation:
+  status_t Touch(float x, float y, float pressure) override;
+  status_t ButtonState(int buttons) override;
+
+ protected:
+  VirtualTouchpadEvdev() {}
+  ~VirtualTouchpadEvdev() {}
+  status_t Initialize();
+
+  // Must be called only between construction and Initialize().
+  inline void SetEvdevInjectorForTesting(EvdevInjector* injector) {
+    injector_ = injector;
+  }
+
+ private:
+  // Except for testing, the |EvdevInjector| used to inject evdev events.
+  std::unique_ptr<EvdevInjector> owned_injector_;
+
+  // Active pointer to |owned_injector_| or to a testing injector.
+  EvdevInjector* injector_ = nullptr;
+
+  // Previous (x, y) position in device space, to suppress redundant events.
+  int32_t last_device_x_ = INT32_MIN;
+  int32_t last_device_y_ = INT32_MIN;
+
+  // Records current touch state (0=up 1=down) in bit 0, and previous state
+  // in bit 1, to track transitions.
+  int touches_ = 0;
+
+  // Previous injected button state, to detect changes.
+  int32_t last_motion_event_buttons_ = 0;
+
+  VirtualTouchpadEvdev(const VirtualTouchpadEvdev&) = delete;
+  void operator=(const VirtualTouchpadEvdev&) = delete;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_VIRTUAL_TOUCHPAD_EVDEV_H
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index 25c1a4f..3fcb8fc 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -8,19 +8,15 @@
 namespace android {
 namespace dvr {
 
-int VirtualTouchpadService::Initialize() {
-  return touchpad_.Initialize();
-}
-
 binder::Status VirtualTouchpadService::touch(float x, float y, float pressure) {
-  const int error = touchpad_.Touch(x, y, pressure);
-  return error ? binder::Status::fromServiceSpecificError(error)
+  const status_t error = touchpad_->Touch(x, y, pressure);
+  return error ? binder::Status::fromStatusT(error)
                : binder::Status::ok();
 }
 
 binder::Status VirtualTouchpadService::buttonState(int buttons) {
-  const int error = touchpad_.ButtonState(buttons);
-  return error ? binder::Status::fromServiceSpecificError(error)
+  const status_t error = touchpad_->ButtonState(buttons);
+  return error ? binder::Status::fromStatusT(error)
                : binder::Status::ok();
 }
 
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index e2426e3..b832c8f 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,22 +13,16 @@
 //
 class VirtualTouchpadService : public BnVirtualTouchpadService {
  public:
-  VirtualTouchpadService(VirtualTouchpad& touchpad)
+  VirtualTouchpadService(sp<VirtualTouchpad> touchpad)
       : touchpad_(touchpad) {}
 
-  // Must be called before clients can connect.
-  // Returns 0 if initialization is successful.
-  int Initialize();
-
-  static char const* getServiceName() { return "virtual_touchpad"; }
-
  protected:
   // Implements IVirtualTouchpadService.
-  ::android::binder::Status touch(float x, float y, float pressure) override;
-  ::android::binder::Status buttonState(int buttons) override;
+  binder::Status touch(float x, float y, float pressure) override;
+  binder::Status buttonState(int buttons) override;
 
  private:
-  VirtualTouchpad& touchpad_;
+  sp<VirtualTouchpad> touchpad_;
 
   VirtualTouchpadService(const VirtualTouchpadService&) = delete;
   void operator=(const VirtualTouchpadService&) = delete;
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
index e048837..c2044da 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
@@ -3,6 +3,8 @@
 /** @hide */
 interface VirtualTouchpadService
 {
+  const String SERVICE_NAME = "virtual_touchpad";
+
   /**
    * Generate a simulated touch event.
    *
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
new file mode 100644
index 0000000..bbaf69b
--- /dev/null
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -0,0 +1,57 @@
+#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
+#define ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace dvr {
+
+// Provides a virtual touchpad for injecting events into the input system.
+//
+class VirtualTouchpad : public RefBase {
+ public:
+  // 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.
+  static sp<VirtualTouchpad> Create() {
+    return sp<VirtualTouchpad>();
+  }
+
+  // Generate a simulated touch event.
+  //
+  // @param x Horizontal touch position.
+  // @param y Vertical touch position.
+  //            Values must be in the range [0.0, 1.0).
+  // @param pressure Touch pressure.
+  //            Positive values represent contact; use 1.0f if contact
+  //            is binary. Use 0.0f for no contact.
+  // @returns OK on success.
+  //
+  virtual status_t Touch(float x, float y, float pressure) = 0;
+
+  // Generate a simulated touchpad button state.
+  //
+  // @param buttons A union of MotionEvent BUTTON_* values.
+  // @returns OK on success.
+  //
+  // Currently only BUTTON_BACK is supported, as the implementation
+  // restricts itself to operations actually required by VrWindowManager.
+  //
+  virtual status_t ButtonState(int buttons) = 0;
+
+ protected:
+  VirtualTouchpad() {}
+  virtual ~VirtualTouchpad() {}
+
+ private:
+  VirtualTouchpad(const VirtualTouchpad&) = delete;
+  void operator=(const VirtualTouchpad&) = delete;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_VIRTUAL_TOUCHPAD_INTERFACE_H
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
new file mode 100644
index 0000000..46bec0e
--- /dev/null
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H
+#define ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H
+
+#include "VirtualTouchpad.h"
+
+namespace android {
+namespace dvr {
+
+// VirtualTouchpadClient implements a VirtualTouchpad by connecting to
+// a VirtualTouchpadService over Binder.
+//
+class VirtualTouchpadClient : public VirtualTouchpad {
+ public:
+  // VirtualTouchpad implementation:
+  static sp<VirtualTouchpad> Create();
+  status_t Touch(float x, float y, float pressure) override;
+  status_t ButtonState(int buttons) override;
+
+ protected:
+  VirtualTouchpadClient() {}
+  virtual ~VirtualTouchpadClient() {}
+
+ private:
+  VirtualTouchpadClient(const VirtualTouchpadClient&) = delete;
+  void operator=(const VirtualTouchpadClient&) = delete;
+};
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_VIRTUAL_TOUCHPAD_CLIENT_H
diff --git a/services/vr/virtual_touchpad/main.cpp b/services/vr/virtual_touchpad/main.cpp
index 1debe9f..e73f8b9 100644
--- a/services/vr/virtual_touchpad/main.cpp
+++ b/services/vr/virtual_touchpad/main.cpp
@@ -3,17 +3,13 @@
 #include <binder/ProcessState.h>
 #include <log/log.h>
 
+#include "VirtualTouchpadEvdev.h"
 #include "VirtualTouchpadService.h"
 
 int main() {
   ALOGI("Starting");
-  android::dvr::VirtualTouchpad touchpad;
-  android::dvr::VirtualTouchpadService touchpad_service(touchpad);
-  const int touchpad_status = touchpad_service.Initialize();
-  if (touchpad_status) {
-    ALOGE("virtual touchpad initialization failed: %d", touchpad_status);
-    exit(1);
-  }
+  android::dvr::VirtualTouchpadService touchpad_service(
+      android::dvr::VirtualTouchpadEvdev::Create());
 
   signal(SIGPIPE, SIG_IGN);
   android::sp<android::ProcessState> ps(android::ProcessState::self());
@@ -23,7 +19,7 @@
 
   android::sp<android::IServiceManager> sm(android::defaultServiceManager());
   const android::status_t service_status =
-      sm->addService(android::String16(touchpad_service.getServiceName()),
+      sm->addService(android::String16(touchpad_service.SERVICE_NAME()),
                      &touchpad_service, false /*allowIsolated*/);
   if (service_status != android::OK) {
     ALOGE("virtual touchpad service not added: %d",
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 256c6bc..b448fd1 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -1,12 +1,12 @@
 #include <android/input.h>
+#include <gtest/gtest.h>
+#include <linux/input.h>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <gtest/gtest.h>
-#include <linux/input.h>
 
 #include "EvdevInjector.h"
-#include "VirtualTouchpad.h"
+#include "VirtualTouchpadEvdev.h"
 
 namespace android {
 namespace dvr {
@@ -21,7 +21,7 @@
     event.type = type;
     event.code = code;
     event.value = value;
-    Write(&event, sizeof (event));
+    Write(&event, sizeof(event));
   }
 };
 
@@ -87,16 +87,17 @@
 
 class EvdevInjectorForTesting : public EvdevInjector {
  public:
-  EvdevInjectorForTesting(UInput& uinput) {
-    SetUInputForTesting(&uinput);
-  }
+  EvdevInjectorForTesting(UInput& uinput) { SetUInputForTesting(&uinput); }
   const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); }
 };
 
-class VirtualTouchpadForTesting : public VirtualTouchpad {
+class VirtualTouchpadForTesting : public VirtualTouchpadEvdev {
  public:
-  VirtualTouchpadForTesting(EvdevInjector& injector) {
-    SetEvdevInjectorForTesting(&injector);
+  static sp<VirtualTouchpad> Create(EvdevInjectorForTesting& injector) {
+    VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
+    touchpad->SetEvdevInjectorForTesting(&injector);
+    touchpad->Initialize();
+    return sp<VirtualTouchpad>(touchpad);
   }
 };
 
@@ -113,17 +114,13 @@
 
 }  // anonymous namespace
 
-class VirtualTouchpadTest : public testing::Test {
-};
+class VirtualTouchpadTest : public testing::Test {};
 
 TEST_F(VirtualTouchpadTest, Goodness) {
   UInputRecorder expect;
   UInputRecorder record;
   EvdevInjectorForTesting injector(record);
-  VirtualTouchpadForTesting touchpad(injector);
-
-  const int initialization_status = touchpad.Initialize();
-  EXPECT_EQ(0, initialization_status);
+  sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
 
   // Check some aspects of uinput_user_dev.
   const uinput_user_dev* uidev = injector.GetUiDev();
@@ -154,13 +151,13 @@
   expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
   expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
   // From ConfigureEnd():
-  expect.Write(uidev, sizeof (uinput_user_dev));
+  expect.Write(uidev, sizeof(uinput_user_dev));
   expect.IoctlVoid(UI_DEV_CREATE);
   EXPECT_EQ(expect.GetString(), record.GetString());
 
   expect.Reset();
   record.Reset();
-  int touch_status = touchpad.Touch(0, 0, 0);
+  int touch_status = touchpad->Touch(0, 0, 0);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
@@ -171,7 +168,7 @@
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.Touch(0.25f, 0.75f, 0.5f);
+  touch_status = touchpad->Touch(0.25f, 0.75f, 0.5f);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width);
@@ -182,7 +179,7 @@
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.Touch(1.0f, 1.0f, 1.0f);
+  touch_status = touchpad->Touch(1.0f, 1.0f, 1.0f);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
   expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, width);
@@ -192,7 +189,7 @@
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.Touch(0.25f, 0.75f, -0.01f);
+  touch_status = touchpad->Touch(0.25f, 0.75f, -0.01f);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE);
   expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1);
@@ -201,7 +198,7 @@
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK);
+  touch_status = touchpad->ButtonState(AMOTION_EVENT_BUTTON_BACK);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS);
   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
@@ -209,13 +206,13 @@
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK);
+  touch_status = touchpad->ButtonState(AMOTION_EVENT_BUTTON_BACK);
   EXPECT_EQ(0, touch_status);
   EXPECT_EQ(expect.GetString(), record.GetString());
 
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.ButtonState(0);
+  touch_status = touchpad->ButtonState(0);
   EXPECT_EQ(0, touch_status);
   expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE);
   expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
@@ -229,56 +226,29 @@
   UInputRecorder expect;
   UInputRecorder record;
   EvdevInjectorForTesting injector(record);
-  VirtualTouchpadForTesting touchpad(injector);
-
-  // Touch before initialization should return an error,
-  // and should not result in any system calls.
-  expect.Reset();
-  record.Reset();
-  int touch_status = touchpad.Touch(0.25f, 0.75f, -0.01f);
-  EXPECT_NE(0, touch_status);
-  EXPECT_EQ(expect.GetString(), record.GetString());
-
-  // Button change before initialization should return an error,
-  // and should not result in any system calls.
-  expect.Reset();
-  record.Reset();
-  touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK);
-  EXPECT_NE(0, touch_status);
-  EXPECT_EQ(expect.GetString(), record.GetString());
-
-  expect.Reset();
-  record.Reset();
-  touchpad.Initialize();
-
-  // Repeated initialization should return an error,
-  // and should not result in any system calls.
-  expect.Reset();
-  record.Reset();
-  const int initialization_status = touchpad.Initialize();
-  EXPECT_NE(0, initialization_status);
-  EXPECT_EQ(expect.GetString(), record.GetString());
+  sp<VirtualTouchpad> touchpad(
+      VirtualTouchpadForTesting::Create(injector));
 
   // Touch off-screen should return an error,
   // and should not result in any system calls.
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.Touch(-0.25f, 0.75f, 1.0f);
-  EXPECT_NE(0, touch_status);
-  touch_status = touchpad.Touch(0.25f, -0.75f, 1.0f);
-  EXPECT_NE(0, touch_status);
-  touch_status = touchpad.Touch(1.25f, 0.75f, 1.0f);
-  EXPECT_NE(0, touch_status);
-  touch_status = touchpad.Touch(0.25f, 1.75f, 1.0f);
-  EXPECT_NE(0, touch_status);
+  status_t touch_status = touchpad->Touch(-0.25f, 0.75f, 1.0f);
+  EXPECT_NE(OK, touch_status);
+  touch_status = touchpad->Touch(0.25f, -0.75f, 1.0f);
+  EXPECT_NE(OK, touch_status);
+  touch_status = touchpad->Touch(1.25f, 0.75f, 1.0f);
+  EXPECT_NE(OK, touch_status);
+  touch_status = touchpad->Touch(0.25f, 1.75f, 1.0f);
+  EXPECT_NE(OK, touch_status);
   EXPECT_EQ(expect.GetString(), record.GetString());
 
   // Unsupported button should return an error,
   // and should not result in any system calls.
   expect.Reset();
   record.Reset();
-  touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_FORWARD);
-  EXPECT_NE(0, touch_status);
+  touch_status = touchpad->ButtonState(AMOTION_EVENT_BUTTON_FORWARD);
+  EXPECT_NE(OK, touch_status);
   EXPECT_EQ(expect.GetString(), record.GetString());
 }
 
diff --git a/services/vr/vr_window_manager/Android.mk b/services/vr/vr_window_manager/Android.mk
index 706efe5..ddb58e9 100644
--- a/services/vr/vr_window_manager/Android.mk
+++ b/services/vr/vr_window_manager/Android.mk
@@ -14,29 +14,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-binder_src := \
-  vr_window_manager_binder.cpp \
-  aidl/android/service/vr/IVrWindowManager.aidl
-
-static_libs := \
-  libcutils
-
-shared_libs := \
-  libbase \
-  libbinder \
-  libutils
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(binder_src)
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\"
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := libvrwm_binder
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_STATIC_LIBRARY)
-
 native_src := \
   application.cpp \
   controller_mesh.cpp \
@@ -47,7 +24,8 @@
   surface_flinger_view.cpp \
   texture.cpp \
   vr_window_manager.cpp \
-  ../virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl \
+  vr_window_manager_binder.cpp \
+  aidl/android/service/vr/IVrWindowManager.aidl
 
 static_libs := \
   libdisplay \
@@ -62,6 +40,7 @@
   libpdx_default_transport \
   libcutils \
   libvr_manager \
+  libvirtualtouchpadclient
 
 shared_libs := \
   android.dvr.composer@1.0 \
@@ -85,7 +64,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(native_src)
-LOCAL_STATIC_LIBRARIES := $(static_libs) libvrwm_binder
+LOCAL_STATIC_LIBRARIES := $(static_libs)
 LOCAL_SHARED_LIBRARIES := $(shared_libs)
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
 LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 6cbd88d..7321ed0 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -703,10 +703,7 @@
 }
 
 bool ShellView::InitializeTouch() {
-  virtual_touchpad_ =
-      android::interface_cast<android::dvr::IVirtualTouchpadService>(
-          android::defaultServiceManager()->getService(
-              android::String16("virtual_touchpad")));
+  virtual_touchpad_ = VirtualTouchpadClient::Create();
   if (!virtual_touchpad_.get()) {
     ALOGE("Failed to connect to virtual touchpad");
     return false;
@@ -723,12 +720,12 @@
     }
   }
 
-  const android::binder::Status status = virtual_touchpad_->touch(
+  const android::status_t status = virtual_touchpad_->Touch(
       hit_location_in_window_coord_.x() / size_.x(),
       hit_location_in_window_coord_.y() / size_.y(),
       is_touching_ ? 1.0f : 0.0f);
-  if (!status.isOk()) {
-    ALOGE("touch failed: %s", status.toString8().string());
+  if (status != OK) {
+    ALOGE("touch failed: %d", status);
   }
 }
 
@@ -750,11 +747,10 @@
     return false;
   }
 
-  const android::binder::Status status =
-      virtual_touchpad_->buttonState(touchpad_buttons_);
-  if (!status.isOk()) {
-    ALOGE("touchpad button failed: %d %s", touchpad_buttons_,
-          status.toString8().string());
+  const android::status_t status =
+      virtual_touchpad_->ButtonState(touchpad_buttons_);
+  if (status != OK) {
+    ALOGE("touchpad button failed: %d %d", touchpad_buttons_, status);
   }
   return true;
 }
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index 1e061bb..c477669 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -3,10 +3,10 @@
 
 #include <private/dvr/graphics/mesh.h>
 #include <private/dvr/graphics/shader_program.h>
-#include <android/dvr/IVirtualTouchpadService.h>
 
 #include <deque>
 
+#include "VirtualTouchpadClient.h"
 #include "application.h"
 #include "reticle.h"
 #include "shell_view_binder_interface.h"
@@ -90,7 +90,7 @@
 
   std::unique_ptr<SurfaceFlingerView> surface_flinger_view_;
   std::unique_ptr<Reticle> reticle_;
-  sp<IVirtualTouchpadService> virtual_touchpad_;
+  sp<VirtualTouchpad> virtual_touchpad_;
   std::vector<TextureLayer> textures_;
   TextureLayer ime_texture_;
 
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index f12395f..3c8ee1c 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -3713,7 +3713,7 @@
     VkStructureType                   sType;
     const void*                       pNext;
     VkAndroidSurfaceCreateFlagsKHR    flags;
-    ANativeWindow*                    window;
+    struct ANativeWindow*             window;
 } VkAndroidSurfaceCreateInfoKHR;
 
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 351caeb..b62eec6 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -778,9 +778,6 @@
     loader_extensions.push_back({
         VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
         VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
-    loader_extensions.push_back({
-        VK_EXT_HDR_METADATA_EXTENSION_NAME,
-        VK_EXT_HDR_METADATA_SPEC_VERSION});
 
     // conditionally add shared_presentable_image if supportable
     VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 358645c..a0ae1f3 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -479,7 +479,7 @@
               err);
         surface->~Surface();
         allocator->pfnFree(allocator->pUserData, surface);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
     }
 
     *out_surface = HandleFromSurface(surface);
@@ -527,13 +527,13 @@
     if (err != 0) {
         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
     if (err != 0) {
         ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     int transform_hint;
@@ -541,7 +541,7 @@
     if (err != 0) {
         ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     // TODO(jessehall): Figure out what the min/max values should be.
@@ -764,7 +764,7 @@
     if (err != 0) {
         ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     int swap_interval =
@@ -775,21 +775,21 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     err = native_window_set_shared_buffer_mode(surface.window.get(), false);
     if (err != 0) {
         ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     err = native_window_set_auto_refresh(surface.window.get(), false);
     if (err != 0) {
         ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     // -- Configure the native window --
@@ -803,7 +803,7 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
               native_pixel_format, strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     err = native_window_set_buffers_data_space(surface.window.get(),
                                                native_dataspace);
@@ -812,7 +812,7 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
               native_dataspace, strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     err = native_window_set_buffers_dimensions(
@@ -824,7 +824,7 @@
         ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
               create_info->imageExtent.width, create_info->imageExtent.height,
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     // VkSwapchainCreateInfo::preTransform indicates the transformation the app
@@ -844,7 +844,7 @@
         ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
               InvertTransformToNative(create_info->preTransform),
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     err = native_window_set_scaling_mode(
@@ -854,7 +854,7 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     int query_value;
@@ -866,7 +866,7 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
               query_value);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
     uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
     uint32_t num_images =
@@ -877,7 +877,7 @@
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
               strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     VkSwapchainImageUsageFlagsANDROID swapchain_image_usage = 0;
@@ -888,7 +888,7 @@
         err = native_window_set_shared_buffer_mode(surface.window.get(), true);
         if (err != 0) {
             ALOGE("native_window_set_shared_buffer_mode failed: %s (%d)", strerror(-err), err);
-            return VK_ERROR_INITIALIZATION_FAILED;
+            return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
 
@@ -896,7 +896,7 @@
         err = native_window_set_auto_refresh(surface.window.get(), true);
         if (err != 0) {
             ALOGE("native_window_set_auto_refresh failed: %s (%d)", strerror(-err), err);
-            return VK_ERROR_INITIALIZATION_FAILED;
+            return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
 
@@ -925,7 +925,7 @@
         }
         if (result != VK_SUCCESS) {
             ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
-            return VK_ERROR_INITIALIZATION_FAILED;
+            return VK_ERROR_SURFACE_LOST_KHR;
         }
         // TODO: This is the same translation done by Gralloc1On0Adapter.
         // Remove it once ANativeWindow has been updated to take gralloc1-style
@@ -938,7 +938,7 @@
             &gralloc_usage);
         if (result != VK_SUCCESS) {
             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
-            return VK_ERROR_INITIALIZATION_FAILED;
+            return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
     err = native_window_set_usage(surface.window.get(), gralloc_usage);
@@ -946,7 +946,7 @@
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
         ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     // -- Allocate our Swapchain object --
@@ -1005,7 +1005,7 @@
             // TODO(jessehall): Improve error reporting. Can we enumerate
             // possible errors and translate them to valid Vulkan result codes?
             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
-            result = VK_ERROR_INITIALIZATION_FAILED;
+            result = VK_ERROR_SURFACE_LOST_KHR;
             break;
         }
         img.buffer = buffer;
@@ -1141,7 +1141,7 @@
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
-        return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_ERROR_SURFACE_LOST_KHR;
     }
 
     uint32_t idx;