Merge "Add RGBA 10:10:10:2 format for surfaces"
diff --git a/aidl/gui/android/view/Surface.aidl b/aidl/gui/android/view/Surface.aidl
index 674c163..7e89220 100644
--- a/aidl/gui/android/view/Surface.aidl
+++ b/aidl/gui/android/view/Surface.aidl
@@ -17,4 +17,4 @@
 
 package android.view;
 
-parcelable Surface cpp_header "gui/Surface.h";
+parcelable Surface cpp_header "gui/view/Surface.h";
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index ce0caed..8f2dee1 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -552,17 +552,13 @@
             hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
             Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName);
             if (!interfaceRet.isOk()) {
-                fprintf(stderr, "failed to get service %s: %s\n",
-                        fqInstanceName.c_str(),
-                        interfaceRet.description().c_str());
+                // ignore
                 continue;
             }
             sp<IBase> interface = interfaceRet;
             auto notifyRet = interface->notifySyspropsChanged();
             if (!notifyRet.isOk()) {
-                fprintf(stderr, "failed to notifySyspropsChanged on service %s: %s\n",
-                        fqInstanceName.c_str(),
-                        notifyRet.description().c_str());
+                // ignore
             }
         }
     });
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index efc050b..d1e94ed 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -103,8 +103,7 @@
 
 LOCAL_MODULE := dumpstate
 
-LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) \
-    android.hardware.vibrator@1.0
+LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES)
 
 LOCAL_STATIC_LIBRARIES := $(COMMON_STATIC_LIBRARIES)
 
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 67172b6..e33f099 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -42,7 +42,6 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
-#include <android/hardware/vibrator/1.0/IVibrator.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
 #include <openssl/sha.h>
@@ -54,8 +53,6 @@
 #include "dumpstate.h"
 
 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
-using ::android::hardware::vibrator::V1_0::IVibrator;
-using VibratorStatus = ::android::hardware::vibrator::V1_0::Status;
 
 // TODO: remove once moved to namespace
 using android::os::dumpstate::CommandOptions;
@@ -1347,7 +1344,8 @@
 
     // TODO: explicity setting Shell's component to allow broadcast to launch it.
     // That might break other components that are listening to the bugreport notifications
-    // (android.intent.action.BUGREPORT_STARTED and android.intent.action.BUGREPORT_STOPED), but
+    // (com.android.internal.intent.action.BUGREPORT_STARTED and
+    // com.android.internal.intent.action.BUGREPORT_STOPED), but
     // those should be just handled by Shell anyways.
     // A more generic alternative would be passing the -f 0x01000000 flag (or whatever
     // value is defined by FLAG_RECEIVER_INCLUDE_BACKGROUND), but that would reset the
@@ -1363,6 +1361,16 @@
                    .Build());
 }
 
+static void Vibrate(int duration_ms) {
+    // clang-format off
+    RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
+               CommandOptions::WithTimeout(10)
+                   .Log("Vibrate: '%s'\n")
+                   .Always()
+                   .Build());
+    // clang-format on
+}
+
 int main(int argc, char *argv[]) {
     int do_add_date = 0;
     int do_zip_file = 0;
@@ -1593,7 +1601,7 @@
                      "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
                 };
                 // clang-format on
-                SendShellBroadcast("android.intent.action.BUGREPORT_STARTED", am_args);
+                SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
             }
             if (use_control_socket) {
                 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
@@ -1608,22 +1616,8 @@
         fclose(cmdline);
     }
 
-    ::android::sp<IVibrator> vibrator = nullptr;
     if (do_vibrate) {
-        vibrator = IVibrator::getService();
-
-        if (vibrator != nullptr) {
-            // cancel previous vibration if any
-            ::android::hardware::Return<VibratorStatus> offStatus = vibrator->off();
-            if (!offStatus.isOk() || offStatus != VibratorStatus::OK) {
-                MYLOGE("Vibrator off failed.");
-            } else {
-                ::android::hardware::Return<VibratorStatus> onStatus = vibrator->on(150);
-                if (!onStatus.isOk() || onStatus != VibratorStatus::OK) {
-                    MYLOGE("Vibrator on failed.");
-                }
-            }
-        }
+        Vibrate(150);
     }
 
     if (do_fb && ds.do_early_screenshot_) {
@@ -1803,21 +1797,9 @@
     }
 
     /* vibrate a few but shortly times to let user know it's finished */
-    if (vibrator != nullptr) {
-        // in case dumpstate magically completes before the above vibration
-        ::android::hardware::Return<VibratorStatus> offStatus = vibrator->off();
-        if (!offStatus.isOk() || offStatus != VibratorStatus::OK) {
-            MYLOGE("Vibrator off failed.");
-        } else {
-            for (int i = 0; i < 3; i++) {
-                ::android::hardware::Return<VibratorStatus> onStatus = vibrator->on(75);
-                if (!onStatus.isOk() || onStatus != VibratorStatus::OK) {
-                    MYLOGE("Vibrator on failed.");
-                    break;
-                }
-                usleep((75 + 50) * 1000);
-            }
-        }
+    for (int i = 0; i < 3; i++) {
+        Vibrate(75);
+        usleep((75 + 50) * 1000);
     }
 
     /* tell activity manager we're done */
@@ -1844,9 +1826,10 @@
                 am_args.push_back("--es");
                 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
                 am_args.push_back(SHA256_file_hash(ds.path_));
-                SendShellBroadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
+                SendShellBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
+                                   am_args);
             } else {
-                SendShellBroadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
+                SendShellBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
             }
         } else {
             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index c5ae9d2..3476964 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -15,8 +15,6 @@
         "libutils",
         "liblog",
         "libbinder",
-        "android.hidl.manager@1.0",
-        "libhidlbase"
     ],
 
     clang: true,
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 860b7b4..f0e7200 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -45,7 +45,8 @@
 using android::base::unique_fd;
 using android::base::WriteFully;
 
-static int sort_func(const String16* lhs, const String16* rhs) {
+static int sort_func(const String16* lhs, const String16* rhs)
+{
     return lhs->compare(*rhs);
 }
 
@@ -54,11 +55,10 @@
         "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--help | --hw | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+            "       dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
             "         -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
-            "         --hw: list all hw services running on the device\n"
             "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
             "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
 }
@@ -72,42 +72,16 @@
     return false;
 }
 
-static void ListHardwareServices(android::hidl::manager::V1_0::IServiceManager* hm) {
-    using android::hardware::hidl_vec;
-    using android::hardware::hidl_string;
-    using android::hardware::Return;
-    using android::sp;
-
-    if (hm == nullptr) {
-        ALOGE("Unable to get hardware service manager!");
-        aerr << "Failed to get hardware service manager!";
-        return;
-    }
-
-    Return<void> ret = hm->list([](const hidl_vec<hidl_string> &registered){
-        aout << "Currently running hardware services:" << endl;
-        for (const auto &service : registered) {
-            aout << "  " << service << endl;
-        }
-    });
-
-    if (!ret.isOk()) {
-        aerr << "Failed to list hardware services: " << ret.description();
-    }
-}
-
 int Dumpsys::main(int argc, char* const argv[]) {
     Vector<String16> services;
     Vector<String16> args;
     Vector<String16> skippedServices;
     bool showListOnly = false;
-    bool listHwOnly = false;
     bool skipServices = false;
     int timeoutArg = 10;
     static struct option longOptions[] = {
         {"skip", no_argument, 0,  0 },
         {"help", no_argument, 0,  0 },
-        {"hw",   no_argument, 0,  0 },
         {     0,           0, 0,  0 }
     };
 
@@ -131,8 +105,6 @@
             } else if (!strcmp(longOptions[optionIndex].name, "help")) {
                 usage();
                 return 0;
-            } else if (!strcmp(longOptions[optionIndex].name, "hw")) {
-                listHwOnly = true;
             }
             break;
 
@@ -171,17 +143,11 @@
     }
 
     if ((skipServices && skippedServices.empty()) ||
-            (showListOnly && (!services.empty() || !skippedServices.empty())) ||
-            (listHwOnly && (skipServices || services.size() > 0 || showListOnly))) {
+            (showListOnly && (!services.empty() || !skippedServices.empty()))) {
         usage();
         return -1;
     }
 
-    if (listHwOnly) {
-        ListHardwareServices(hm_);
-        return 0;
-    }
-
     if (services.empty() || showListOnly) {
         // gets all services
         services = sm_->listServices();
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 20d515d..2534dde 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -17,21 +17,18 @@
 #ifndef FRAMEWORK_NATIVE_CMD_DUMPSYS_H_
 #define FRAMEWORK_NATIVE_CMD_DUMPSYS_H_
 
-#include <android/hidl/manager/1.0/IServiceManager.h>
 #include <binder/IServiceManager.h>
 
 namespace android {
 
 class Dumpsys {
   public:
-    Dumpsys(android::IServiceManager* sm,
-            android::hidl::manager::V1_0::IServiceManager* hm) : sm_(sm), hm_(hm) {
+    Dumpsys(android::IServiceManager* sm) : sm_(sm) {
     }
     int main(int argc, char* const argv[]);
 
   private:
     android::IServiceManager* sm_;
-    android::hidl::manager::V1_0::IServiceManager* hm_;
 };
 }
 
diff --git a/cmds/dumpsys/main.cpp b/cmds/dumpsys/main.cpp
index b180c98..8ba0eba 100644
--- a/cmds/dumpsys/main.cpp
+++ b/cmds/dumpsys/main.cpp
@@ -27,7 +27,6 @@
 #include <stdio.h>
 
 using namespace android;
-using HServiceManager = android::hidl::manager::V1_0::IServiceManager;
 
 int main(int argc, char* const argv[]) {
     signal(SIGPIPE, SIG_IGN);
@@ -39,8 +38,6 @@
         return 20;
     }
 
-    sp<HServiceManager> hm = HServiceManager::getService("manager");
-
-    Dumpsys dumpsys(sm.get(), hm.get());
+    Dumpsys dumpsys(sm.get());
     return dumpsys.main(argc, argv);
 }
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index e00444f..7698ed5 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -5,12 +5,8 @@
     srcs: ["dumpsys_test.cpp"],
 
     shared_libs: [
-        "android.hidl.manager@1.0",
         "libbase",
         "libbinder",
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
         "libutils",
     ],
 
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 01a2fa3..a61cb00 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -44,12 +44,6 @@
 using ::testing::internal::GetCapturedStderr;
 using ::testing::internal::GetCapturedStdout;
 
-using android::hardware::hidl_vec;
-using android::hardware::hidl_string;
-using android::hardware::Void;
-using HServiceManager = android::hidl::manager::V1_0::IServiceManager;
-using IServiceNotification = android::hidl::manager::V1_0::IServiceNotification;
-
 class ServiceManagerMock : public IServiceManager {
   public:
     MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&));
@@ -61,27 +55,6 @@
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
 
-class HardwareServiceManagerMock : public HServiceManager {
-  public:
-    template<typename T>
-    using R = android::hardware::Return<T>; // conflicts with ::testing::Return
-
-    MOCK_METHOD2(get, R<sp<IBase>>(const hidl_string&, const hidl_string&));
-    MOCK_METHOD3(add,
-        R<bool>(const hidl_vec<hidl_string>&,
-                const hidl_string&,
-                const sp<IBase>&));
-    MOCK_METHOD1(list, R<void>(list_cb));
-    MOCK_METHOD2(listByInterface,
-        R<void>(const hidl_string&, listByInterface_cb));
-    MOCK_METHOD3(registerForNotifications,
-        R<bool>(const hidl_string&,
-                const hidl_string&,
-                const sp<IServiceNotification>&));
-    MOCK_METHOD1(debugDump, R<void>(debugDump_cb));
-
-};
-
 class BinderMock : public BBinder {
   public:
     BinderMock() {
@@ -111,26 +84,6 @@
     return MakeAction(new WriteOnFdAction(output));
 }
 
-// gmock black magic to provide a WithArg<0>(List(services)) matcher
-typedef void HardwareListFunction(HServiceManager::list_cb);
-
-class HardwareListAction : public ActionInterface<HardwareListFunction> {
-  public:
-    explicit HardwareListAction(const hidl_vec<hidl_string> &services) : services_(services) {
-    }
-    virtual Result Perform(const ArgumentTuple& args) {
-        auto cb = ::std::tr1::get<0>(args);
-        cb(services_);
-    }
-
-  private:
-    hidl_vec<hidl_string> services_;
-};
-
-Action<HardwareListFunction> HardwareList(const  hidl_vec<hidl_string> &services) {
-    return MakeAction(new HardwareListAction(services));
-}
-
 // Matcher for args using Android's Vector<String16> format
 // TODO: move it to some common testing library
 MATCHER_P(AndroidElementsAre, expected, "") {
@@ -168,7 +121,7 @@
 
 class DumpsysTest : public Test {
   public:
-    DumpsysTest() : sm_(), hm_(), dump_(&sm_, &hm_), stdout_(), stderr_() {
+    DumpsysTest() : sm_(), dump_(&sm_), stdout_(), stderr_() {
     }
 
     void ExpectListServices(std::vector<std::string> services) {
@@ -176,22 +129,9 @@
         for (auto& service : services) {
             services16.add(String16(service.c_str()));
         }
-
         EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16));
     }
 
-    void ExpectListHardwareServices(std::vector<std::string> services) {
-        hidl_vec<hidl_string> hidl_services;
-        hidl_services.resize(services.size());
-        for (size_t i = 0; i < services.size(); i++) {
-            hidl_services[i] = services[i];
-        }
-
-        EXPECT_CALL(hm_, list(_)).WillRepeatedly(DoAll(
-                WithArg<0>(HardwareList(hidl_services)),
-                Return(Void())));
-    }
-
     sp<BinderMock> ExpectCheckService(const char* name, bool running = true) {
         sp<BinderMock> binder_mock;
         if (running) {
@@ -235,10 +175,8 @@
         EXPECT_THAT(status, Eq(0));
     }
 
-    void AssertRunningServices(const std::vector<std::string>& services,
-                               const std::string &message = "Currently running services:") {
-        std::string expected(message);
-        expected.append("\n");
+    void AssertRunningServices(const std::vector<std::string>& services) {
+        std::string expected("Currently running services:\n");
         for (const std::string& service : services) {
             expected.append("  ").append(service).append("\n");
         }
@@ -266,21 +204,12 @@
     }
 
     ServiceManagerMock sm_;
-    HardwareServiceManagerMock hm_;
     Dumpsys dump_;
 
   private:
     std::string stdout_, stderr_;
 };
 
-TEST_F(DumpsysTest, ListHwServices) {
-    ExpectListHardwareServices({"Locksmith", "Valet"});
-
-    CallMain({"--hw"});
-
-    AssertRunningServices({"Locksmith", "Valet"}, "Currently running hardware services:");
-}
-
 // Tests 'dumpsys -l' when all services are running
 TEST_F(DumpsysTest, ListAllServices) {
     ExpectListServices({"Locksmith", "Valet"});
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index aa32d6b..0fb207b 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -854,13 +854,16 @@
     return open(file_name, flags, permissions);
 }
 
-static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
+static bool set_permissions_and_ownership(
+        int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
+    // Primary apks are owned by the system. Secondary dex files are owned by the app.
+    int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
     if (fchmod(fd,
                S_IRUSR|S_IWUSR|S_IRGRP |
                (is_public ? S_IROTH : 0)) < 0) {
         ALOGE("installd cannot chmod '%s' during dexopt\n", path);
         return false;
-    } else if (fchown(fd, AID_SYSTEM, uid) < 0) {
+    } else if (fchown(fd, owning_uid, uid) < 0) {
         ALOGE("installd cannot chown '%s' during dexopt\n", path);
         return false;
     }
@@ -1009,10 +1012,11 @@
 
 // (re)Creates the app image if needed.
 Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
-        bool is_public, int uid) {
+        bool is_public, int uid, bool is_secondary_dex) {
     // Use app images only if it is enabled (by a set image format) and we are compiling
     // profile-guided (so the app image doesn't conservatively contain all classes).
-    if (!profile_guided) {
+    // Note that we don't create an image for secondary dex files.
+    if (is_secondary_dex || !profile_guided) {
         return Dex2oatFileWrapper();
     }
 
@@ -1043,7 +1047,7 @@
             }
         }
     } else if (!set_permissions_and_ownership(
-                wrapper_fd.get(), is_public, uid, image_path.c_str())) {
+                wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
         ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
         wrapper_fd.reset(-1);
     }
@@ -1101,7 +1105,7 @@
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
 // out_vdex_wrapper_fd. Returns true for success or false in case of errors.
 bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
-        const char* instruction_set, bool is_public, int uid,
+        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
         Dex2oatFileWrapper* in_vdex_wrapper_fd,
         Dex2oatFileWrapper* out_vdex_wrapper_fd) {
     CHECK(in_vdex_wrapper_fd != nullptr);
@@ -1164,7 +1168,7 @@
         }
     }
     if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
-            out_vdex_path_str.c_str())) {
+            out_vdex_path_str.c_str(), is_secondary_dex)) {
         ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
         return false;
     }
@@ -1187,7 +1191,8 @@
             [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
     if (wrapper_fd.get() < 0) {
         PLOG(ERROR) << "installd cannot open output during dexopt" <<  out_oat_path;
-    } else if (!set_permissions_and_ownership(wrapper_fd.get(), is_public, uid, out_oat_path)) {
+    } else if (!set_permissions_and_ownership(
+                wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
         ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
         wrapper_fd.reset(-1);
     }
@@ -1445,7 +1450,7 @@
     Dex2oatFileWrapper in_vdex_fd;
     Dex2oatFileWrapper out_vdex_fd;
     if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
-            &in_vdex_fd, &out_vdex_fd)) {
+            is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
         return -1;
     }
 
@@ -1454,7 +1459,7 @@
 
     // Create the app image file if needed.
     Dex2oatFileWrapper image_fd =
-            maybe_open_app_image(out_oat_path, profile_guided, is_public, uid);
+            maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
 
     // Open the reference profile if needed.
     Dex2oatFileWrapper reference_profile_fd =
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index c380598..5aab35a 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -22,6 +22,6 @@
         "libhidltransport",
     ],
     srcs: [
-        "lshal.cpp"
+        "Lshal.cpp"
     ],
 }
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
new file mode 100644
index 0000000..ce058c8
--- /dev/null
+++ b/cmds/lshal/Lshal.cpp
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Lshal.h"
+
+#include <getopt.h>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <regex>
+
+#include <android-base/parseint.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+
+#include "Timeout.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hidl::manager::V1_0::IServiceManager;
+
+namespace android {
+namespace lshal {
+
+template <typename A>
+std::string join(const A &components, const std::string &separator) {
+    std::stringstream out;
+    bool first = true;
+    for (const auto &component : components) {
+        if (!first) {
+            out << separator;
+        }
+        out << component;
+
+        first = false;
+    }
+    return out.str();
+}
+
+static std::string toHexString(uint64_t t) {
+    std::ostringstream os;
+    os << std::hex << std::setfill('0') << std::setw(16) << t;
+    return os.str();
+}
+
+static std::pair<hidl_string, hidl_string> split(const hidl_string &s, char c) {
+    const char *pos = strchr(s.c_str(), c);
+    if (pos == nullptr) {
+        return {s, {}};
+    }
+    return {hidl_string(s.c_str(), pos - s.c_str()), hidl_string(pos + 1)};
+}
+
+static std::vector<std::string> split(const std::string &s, char c) {
+    std::vector<std::string> components{};
+    size_t startPos = 0;
+    size_t matchPos;
+    while ((matchPos = s.find(c, startPos)) != std::string::npos) {
+        components.push_back(s.substr(startPos, matchPos - startPos));
+        startPos = matchPos + 1;
+    }
+
+    if (startPos <= s.length()) {
+        components.push_back(s.substr(startPos));
+    }
+    return components;
+}
+
+std::string getCmdline(pid_t pid) {
+    std::ifstream ifs("/proc/" + std::to_string(pid) + "/cmdline");
+    std::string cmdline;
+    if (!ifs.is_open()) {
+        return "";
+    }
+    ifs >> cmdline;
+    return cmdline;
+}
+
+const std::string &Lshal::getCmdline(pid_t pid) {
+    auto pair = mCmdlines.find(pid);
+    if (pair != mCmdlines.end()) {
+        return pair->second;
+    }
+    mCmdlines[pid] = ::android::lshal::getCmdline(pid);
+    return mCmdlines[pid];
+}
+
+void Lshal::removeDeadProcesses(Pids *pids) {
+    static const pid_t myPid = getpid();
+    std::remove_if(pids->begin(), pids->end(), [this](auto pid) {
+        return pid == myPid || this->getCmdline(pid).empty();
+    });
+}
+
+bool Lshal::getReferencedPids(
+        pid_t serverPid, std::map<uint64_t, Pids> *objects) const {
+
+    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
+    if (!ifs.is_open()) {
+        return false;
+    }
+
+    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
+
+    std::string line;
+    std::smatch match;
+    while(getline(ifs, line)) {
+        if (!std::regex_search(line, match, prefix)) {
+            // the line doesn't start with the correct prefix
+            continue;
+        }
+        std::string ptrString = "0x" + match.str(2); // use number after c
+        uint64_t ptr;
+        if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
+            // Should not reach here, but just be tolerant.
+            mErr << "Could not parse number " << ptrString << std::endl;
+            continue;
+        }
+        const std::string proc = " proc ";
+        auto pos = line.rfind(proc);
+        if (pos != std::string::npos) {
+            for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) {
+                int32_t pid;
+                if (!::android::base::ParseInt(pidStr, &pid)) {
+                    mErr << "Could not parse number " << pidStr << std::endl;
+                    continue;
+                }
+                (*objects)[ptr].push_back(pid);
+            }
+        }
+    }
+    return true;
+}
+
+void Lshal::postprocess() {
+    if (mSortColumn) {
+        std::sort(mTable.begin(), mTable.end(), mSortColumn);
+    }
+    for (TableEntry &entry : mTable) {
+        entry.serverCmdline = getCmdline(entry.serverPid);
+        removeDeadProcesses(&entry.clientPids);
+        for (auto pid : entry.clientPids) {
+            entry.clientCmdlines.push_back(this->getCmdline(pid));
+        }
+    }
+}
+
+void Lshal::printLine(
+        const std::string &interfaceName,
+        const std::string &transport, const std::string &server,
+        const std::string &serverCmdline,
+        const std::string &address, const std::string &clients,
+        const std::string &clientCmdlines) const {
+    if (mSelectedColumns & ENABLE_INTERFACE_NAME)
+        mOut << std::setw(80) << interfaceName << "\t";
+    if (mSelectedColumns & ENABLE_TRANSPORT)
+        mOut << std::setw(10) << transport << "\t";
+    if (mSelectedColumns & ENABLE_SERVER_PID) {
+        if (mEnableCmdlines) {
+            mOut << std::setw(15) << serverCmdline << "\t";
+        } else {
+            mOut << std::setw(5)  << server << "\t";
+        }
+    }
+    if (mSelectedColumns & ENABLE_SERVER_ADDR)
+        mOut << std::setw(16) << address << "\t";
+    if (mSelectedColumns & ENABLE_CLIENT_PIDS) {
+        if (mEnableCmdlines) {
+            mOut << std::setw(0)  << clientCmdlines;
+        } else {
+            mOut << std::setw(0)  << clients;
+        }
+    }
+    mOut << std::endl;
+}
+
+void Lshal::dump() const {
+    mOut << "All services:" << std::endl;
+    mOut << std::left;
+    printLine("Interface", "Transport", "Server", "Server CMD", "PTR", "Clients", "Clients CMD");
+    for (const auto &entry : mTable) {
+        printLine(entry.interfaceName,
+                entry.transport,
+                entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid),
+                entry.serverCmdline,
+                entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress),
+                join(entry.clientPids, " "),
+                join(entry.clientCmdlines, ";"));
+    }
+}
+
+void Lshal::putEntry(TableEntry &&entry) {
+    mTable.push_back(std::forward<TableEntry>(entry));
+}
+
+Status Lshal::fetchAllLibraries(const sp<IServiceManager> &manager) {
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &fqInstanceNames) {
+        for (const auto &fqInstanceName : fqInstanceNames) {
+            putEntry({
+                .interfaceName = fqInstanceName,
+                .transport = "passthrough",
+                .serverPid = NO_PID,
+                .serverObjectAddress = NO_PTR,
+                .clientPids = {}
+            });
+        }
+    });
+    if (!ret.isOk()) {
+        mErr << "Error: Failed to call list on getPassthroughServiceManager(): "
+             << ret.description() << std::endl;
+        return DUMP_ALL_LIBS_ERROR;
+    }
+    return OK;
+}
+
+Status Lshal::fetchPassthrough(const sp<IServiceManager> &manager) {
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+        for (const auto &info : infos) {
+            putEntry({
+                .interfaceName =
+                        std::string{info.interfaceName.c_str()} + "/" +
+                        std::string{info.instanceName.c_str()},
+                .transport = "passthrough",
+                .serverPid = info.clientPids.size() == 1 ? info.clientPids[0] : NO_PID,
+                .serverObjectAddress = NO_PTR,
+                .clientPids = info.clientPids
+            });
+        }
+    });
+    if (!ret.isOk()) {
+        mErr << "Error: Failed to call debugDump on defaultServiceManager(): "
+             << ret.description() << std::endl;
+        return DUMP_PASSTHROUGH_ERROR;
+    }
+    return OK;
+}
+
+Status Lshal::fetchBinderized(const sp<IServiceManager> &manager) {
+    using namespace ::std;
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    const std::string mode = "hwbinder";
+    Status status = OK;
+    auto listRet = timeoutIPC(manager, &IServiceManager::list, [&] (const auto &fqInstanceNames) {
+        // server pid, .ptr value of binder object, child pids
+        std::map<std::string, DebugInfo> allDebugInfos;
+        std::map<pid_t, std::map<uint64_t, Pids>> allPids;
+        for (const auto &fqInstanceName : fqInstanceNames) {
+            const auto pair = split(fqInstanceName, '/');
+            const auto &serviceName = pair.first;
+            const auto &instanceName = pair.second;
+            auto getRet = timeoutIPC(manager, &IServiceManager::get, serviceName, instanceName);
+            if (!getRet.isOk()) {
+                mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                     << "cannot be fetched from service manager:"
+                     << getRet.description() << std::endl;
+                status |= DUMP_BINDERIZED_ERROR;
+                continue;
+            }
+            sp<IBase> service = getRet;
+            if (service == nullptr) {
+                mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                     << "cannot be fetched from service manager (null)";
+                status |= DUMP_BINDERIZED_ERROR;
+                continue;
+            }
+            auto debugRet = timeoutIPC(service, &IBase::getDebugInfo, [&] (const auto &debugInfo) {
+                allDebugInfos[fqInstanceName] = debugInfo;
+                if (debugInfo.pid >= 0) {
+                    allPids[static_cast<pid_t>(debugInfo.pid)].clear();
+                }
+            });
+            if (!debugRet.isOk()) {
+                mErr << "Warning: Skipping \"" << fqInstanceName << "\": "
+                     << "debugging information cannot be retrieved:"
+                     << debugRet.description() << std::endl;
+                status |= DUMP_BINDERIZED_ERROR;
+            }
+        }
+        for (auto &pair : allPids) {
+            pid_t serverPid = pair.first;
+            if (!getReferencedPids(serverPid, &allPids[serverPid])) {
+                mErr << "Warning: no information for PID " << serverPid
+                          << ", are you root?" << std::endl;
+                status |= DUMP_BINDERIZED_ERROR;
+            }
+        }
+        for (const auto &fqInstanceName : fqInstanceNames) {
+            auto it = allDebugInfos.find(fqInstanceName);
+            if (it == allDebugInfos.end()) {
+                putEntry({
+                    .interfaceName = fqInstanceName,
+                    .transport = mode,
+                    .serverPid = NO_PID,
+                    .serverObjectAddress = NO_PTR,
+                    .clientPids = {}
+                });
+                continue;
+            }
+            const DebugInfo &info = it->second;
+            putEntry({
+                .interfaceName = fqInstanceName,
+                .transport = mode,
+                .serverPid = info.pid,
+                .serverObjectAddress = info.ptr,
+                .clientPids = info.pid == NO_PID || info.ptr == NO_PTR
+                        ? Pids{} : allPids[info.pid][info.ptr]
+            });
+        }
+
+    });
+    if (!listRet.isOk()) {
+        mErr << "Error: Failed to list services for " << mode << ": "
+             << listRet.description() << std::endl;
+        status |= DUMP_BINDERIZED_ERROR;
+    }
+    return status;
+}
+
+Status Lshal::fetch() {
+    Status status = OK;
+    auto bManager = ::android::hardware::defaultServiceManager();
+    if (bManager == nullptr) {
+        mErr << "Failed to get defaultServiceManager()!" << std::endl;
+        status |= NO_BINDERIZED_MANAGER;
+    } else {
+        status |= fetchBinderized(bManager);
+        // Passthrough PIDs are registered to the binderized manager as well.
+        status |= fetchPassthrough(bManager);
+    }
+
+    auto pManager = ::android::hardware::getPassthroughServiceManager();
+    if (pManager == nullptr) {
+        mErr << "Failed to get getPassthroughServiceManager()!" << std::endl;
+        status |= NO_PASSTHROUGH_MANAGER;
+    } else {
+        status |= fetchAllLibraries(pManager);
+    }
+    return status;
+}
+
+void Lshal::usage() const {
+    mErr
+        << "usage: lshal" << std::endl
+        << "           Dump all hals with default ordering and columns [-itpc]." << std::endl
+        << "       lshal [--interface|-i] [--transport|-t]" << std::endl
+        << "             [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl
+        << "             [--sort={interface|i|pid|p}]" << std::endl
+        << "           -i, --interface: print the interface name column" << std::endl
+        << "           -n, --instance: print the instance name column" << std::endl
+        << "           -t, --transport: print the transport mode column" << std::endl
+        << "           -p, --pid: print the server PID, or server cmdline if -m is set" << std::endl
+        << "           -a, --address: print the server object address column" << std::endl
+        << "           -c, --clients: print the client PIDs, or client cmdlines if -m is set"
+                                                                              << std::endl
+        << "           -m, --cmdline: print cmdline instead of PIDs" << std::endl
+        << "           --sort=i, --sort=interface: sort by interface name" << std::endl
+        << "           --sort=p, --sort=pid: sort by server pid" << std::endl
+        << "       lshal [-h|--help]" << std::endl
+        << "           -h, --help: show this help information." << std::endl;
+}
+
+Status Lshal::parseArgs(int argc, char **argv) {
+    static struct option longOptions[] = {
+        // long options with short alternatives
+        {"help",      no_argument,       0, 'h' },
+        {"interface", no_argument,       0, 'i' },
+        {"transport", no_argument,       0, 't' },
+        {"pid",       no_argument,       0, 'p' },
+        {"address",   no_argument,       0, 'a' },
+        {"clients",   no_argument,       0, 'c' },
+        {"cmdline",   no_argument,       0, 'm' },
+
+        // long options without short alternatives
+        {"sort",      required_argument, 0, 's' },
+        { 0,          0,                 0,  0  }
+    };
+
+    int optionIndex;
+    int c;
+    optind = 1;
+    for (;;) {
+        // using getopt_long in case we want to add other options in the future
+        c = getopt_long(argc, argv, "hitpacm", longOptions, &optionIndex);
+        if (c == -1) {
+            break;
+        }
+        switch (c) {
+        case 's': {
+            if (strcmp(optarg, "interface") == 0 || strcmp(optarg, "i") == 0) {
+                mSortColumn = TableEntry::sortByInterfaceName;
+            } else if (strcmp(optarg, "pid") == 0 || strcmp(optarg, "p") == 0) {
+                mSortColumn = TableEntry::sortByServerPid;
+            } else {
+                mErr << "Unrecognized sorting column: " << optarg << std::endl;
+                usage();
+                return USAGE;
+            }
+            break;
+        }
+        case 'i': {
+            mSelectedColumns |= ENABLE_INTERFACE_NAME;
+            break;
+        }
+        case 't': {
+            mSelectedColumns |= ENABLE_TRANSPORT;
+            break;
+        }
+        case 'p': {
+            mSelectedColumns |= ENABLE_SERVER_PID;
+            break;
+        }
+        case 'a': {
+            mSelectedColumns |= ENABLE_SERVER_ADDR;
+            break;
+        }
+        case 'c': {
+            mSelectedColumns |= ENABLE_CLIENT_PIDS;
+            break;
+        }
+        case 'm': {
+            mEnableCmdlines = true;
+            break;
+        }
+        case 'h': // falls through
+        default: // see unrecognized options
+            usage();
+            return USAGE;
+        }
+    }
+
+    if (mSelectedColumns == 0) {
+        mSelectedColumns = ENABLE_INTERFACE_NAME
+                | ENABLE_TRANSPORT | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS;
+    }
+    return OK;
+}
+
+int Lshal::main(int argc, char **argv) {
+    Status status = parseArgs(argc, argv);
+    if (status != OK) {
+        return status;
+    }
+    status = fetch();
+    postprocess();
+    dump();
+    return status;
+}
+
+}  // namespace lshal
+}  // namespace android
+
+int main(int argc, char **argv) {
+    return ::android::lshal::Lshal{}.main(argc, argv);
+}
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
new file mode 100644
index 0000000..ead99dc
--- /dev/null
+++ b/cmds/lshal/Lshal.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
+
+#include <stdint.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+
+#include "TableEntry.h"
+
+namespace android {
+namespace lshal {
+
+enum : unsigned int {
+    OK                                      = 0,
+    USAGE                                   = 1 << 0,
+    NO_BINDERIZED_MANAGER                   = 1 << 1,
+    NO_PASSTHROUGH_MANAGER                  = 1 << 2,
+    DUMP_BINDERIZED_ERROR                   = 1 << 3,
+    DUMP_PASSTHROUGH_ERROR                  = 1 << 4,
+    DUMP_ALL_LIBS_ERROR                     = 1 << 5,
+};
+using Status = unsigned int;
+
+class Lshal {
+public:
+    int main(int argc, char **argv);
+
+private:
+    Status parseArgs(int argc, char **argv);
+    Status fetch();
+    void postprocess();
+    void dump() const;
+    void usage() const;
+    void putEntry(TableEntry &&entry);
+    Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
+    bool getReferencedPids(
+        pid_t serverPid, std::map<uint64_t, Pids> *objects) const;
+    void printLine(
+            const std::string &interfaceName,
+            const std::string &transport, const std::string &server,
+            const std::string &serverCmdline,
+            const std::string &address, const std::string &clients,
+            const std::string &clientCmdlines) const ;
+    // Return /proc/{pid}/cmdline if it exists, else empty string.
+    const std::string &getCmdline(pid_t pid);
+    // Call getCmdline on all pid in pids. If it returns empty string, the process might
+    // have died, and the pid is removed from pids.
+    void removeDeadProcesses(Pids *pids);
+
+    Table mTable{};
+    std::ostream &mErr = std::cerr;
+    std::ostream &mOut = std::cout;
+    TableEntryCompare mSortColumn = nullptr;
+    TableEntrySelect mSelectedColumns = 0;
+    // If true, cmdlines will be printed instead of pid.
+    bool mEnableCmdlines;
+    // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
+    // If an entry exist but is an empty string, process might have died.
+    // If an entry exist and not empty, it contains the cached content of /proc/{pid}/cmdline.
+    std::map<pid_t, std::string> mCmdlines;
+};
+
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_LSHAL_H_
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
new file mode 100644
index 0000000..4ec3a0c
--- /dev/null
+++ b/cmds/lshal/TableEntry.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+namespace android {
+namespace lshal {
+
+using Pids = std::vector<int32_t>;
+
+struct TableEntry {
+    std::string interfaceName;
+    std::string transport;
+    int32_t serverPid;
+    std::string serverCmdline;
+    uint64_t serverObjectAddress;
+    Pids clientPids;
+    std::vector<std::string> clientCmdlines;
+
+    static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
+        return a.interfaceName < b.interfaceName;
+    };
+    static bool sortByServerPid(const TableEntry &a, const TableEntry &b) {
+        return a.serverPid < b.serverPid;
+    };
+};
+
+using Table = std::vector<TableEntry>;
+using TableEntryCompare = std::function<bool(const TableEntry &, const TableEntry &)>;
+
+enum : unsigned int {
+    ENABLE_INTERFACE_NAME = 1 << 0,
+    ENABLE_TRANSPORT      = 1 << 1,
+    ENABLE_SERVER_PID     = 1 << 2,
+    ENABLE_SERVER_ADDR    = 1 << 3,
+    ENABLE_CLIENT_PIDS    = 1 << 4
+};
+
+using TableEntrySelect = unsigned int;
+
+enum {
+    NO_PID = -1,
+    NO_PTR = 0
+};
+
+}  // namespace lshal
+}  // namespace android
+
+#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_TABLE_ENTRY_H_
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
new file mode 100644
index 0000000..bf883c0
--- /dev/null
+++ b/cmds/lshal/Timeout.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <condition_variable>
+#include <chrono>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+#include <hidl/Status.h>
+
+namespace android {
+namespace lshal {
+
+static constexpr std::chrono::milliseconds IPC_CALL_WAIT{500};
+
+class BackgroundTaskState {
+public:
+    BackgroundTaskState(){}
+    void notify() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mFinished = true;
+        lock.unlock();
+        mCondVar.notify_all();
+    }
+    template<class C, class D>
+    bool wait(std::chrono::time_point<C, D> end) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondVar.wait_until(lock, end, [this](){ return this->mFinished; });
+        return mFinished;
+    }
+private:
+    std::mutex mMutex;
+    std::condition_variable mCondVar;
+    bool mFinished = false;
+};
+
+template<class R, class P>
+bool timeout(std::chrono::duration<R, P> delay, const std::function<void(void)> &func) {
+    auto now = std::chrono::system_clock::now();
+    BackgroundTaskState state{};
+    std::thread t([&state, &func] {
+        func();
+        state.notify();
+    });
+    t.detach();
+    bool success = state.wait(now + delay);
+    return success;
+}
+
+template<class Function, class I, class... Args>
+typename std::result_of<Function(I *, Args...)>::type
+timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+    using ::android::hardware::Status;
+    typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
+    auto boundFunc = std::bind(std::forward<Function>(func),
+            interfaceObject.get(), std::forward<Args>(args)...);
+    bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] {
+        ret = boundFunc();
+    });
+    if (!success) {
+        return Status::fromStatusT(TIMED_OUT);
+    }
+    return ret;
+}
+
+}  // namespace lshal
+}  // namespace android
diff --git a/cmds/lshal/lshal.cpp b/cmds/lshal/lshal.cpp
deleted file mode 100644
index bc5eaf2..0000000
--- a/cmds/lshal/lshal.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <getopt.h>
-
-#include <map>
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <regex>
-
-#include <android-base/parseint.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-
-template <typename A, typename B, typename C, typename D, typename E>
-void printColumn(std::stringstream &stream,
-        const A &a, const B &b, const C &c, const D &d, const E &e) {
-    using namespace ::std;
-    stream << left
-           << setw(70) << a << "\t"
-           << setw(20) << b << "\t"
-           << setw(10) << c << "\t"
-           << setw(5)  << d << "\t"
-           << setw(0)  << e
-           << endl;
-}
-
-std::string toHexString(uint64_t t) {
-    std::ostringstream os;
-    os << std::hex << std::setfill('0') << std::setw(16) << t;
-    return os.str();
-}
-
-::android::status_t getReferencedPids(
-        pid_t serverPid, std::map<uint64_t, std::string> *objects) {
-
-    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
-    if (!ifs.is_open()) {
-        return ::android::PERMISSION_DENIED;
-    }
-
-    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
-
-    std::string line;
-    std::smatch match;
-    while(getline(ifs, line)) {
-        if (!std::regex_search(line, match, prefix)) {
-            // the line doesn't start with the correct prefix
-            continue;
-        }
-        std::string ptrString = "0x" + match.str(2); // use number after c
-        uint64_t ptr;
-        if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) {
-            // Should not reach here, but just be tolerant.
-            std::cerr << "Could not parse number " << ptrString << std::endl;
-            continue;
-        }
-        const std::string proc = " proc ";
-        auto pos = line.rfind(proc);
-        if (pos != std::string::npos) {
-            (*objects)[ptr] += line.substr(pos + proc.size());
-        }
-    }
-    return ::android::OK;
-}
-
-
-int dump() {
-    using namespace ::std;
-    using namespace ::android::hardware;
-    using namespace ::android::hidl::manager::V1_0;
-
-    std::map<std::string, ::android::sp<IServiceManager>> mapping = {
-            {"hwbinder", defaultServiceManager()},
-            {"passthrough", getPassthroughServiceManager()}
-    };
-
-    std::stringstream stream;
-
-    stream << "All services:" << endl;
-    stream << left;
-    printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients");
-
-    for (const auto &pair : mapping) {
-        const std::string &mode = pair.first;
-        const ::android::sp<IServiceManager> &manager = pair.second;
-
-        if (manager == nullptr) {
-            cerr << "Failed to get IServiceManager for " << mode << "!" << endl;
-            continue;
-        }
-
-        auto ret = manager->debugDump([&](const auto &registered) {
-            // server pid, .ptr value of binder object, child pids
-            std::map<pid_t, std::map<uint64_t, std::string>> allPids;
-            for (const auto &info : registered) {
-                if (info.pid < 0) {
-                    continue;
-                }
-                pid_t serverPid = info.pid;
-                allPids[serverPid].clear();
-            }
-            for (auto &pair : allPids) {
-                pid_t serverPid = pair.first;
-                if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) {
-                    std::cerr << "Warning: no information for PID " << serverPid
-                              << ", are you root?" << std::endl;
-                }
-            }
-            for (const auto &info : registered) {
-                printColumn(stream,
-                    info.interfaceName,
-                    info.instanceName.empty() ? "N/A" : info.instanceName,
-                    mode,
-                    info.pid < 0 ? "N/A" : std::to_string(info.pid),
-                    info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]);
-            }
-        });
-        if (!ret.isOk()) {
-            cerr << "Failed to list services for " << mode << ": "
-                 << ret.description() << endl;
-        }
-    }
-    cout << stream.rdbuf();
-    return 0;
-}
-
-int usage() {
-    using namespace ::std;
-    cerr
-        << "usage: lshal" << endl
-        << "           To dump all hals." << endl
-        << "or:" << endl
-        << "       lshal [-h|--help]" << endl
-        << "           -h, --help: show this help information." << endl;
-    return -1;
-}
-
-int main(int argc, char **argv) {
-    static struct option longOptions[] = {
-        {"help", no_argument, 0, 'h' },
-        { 0,               0, 0,  0  }
-    };
-
-    int optionIndex;
-    int c;
-    optind = 1;
-    for (;;) {
-        // using getopt_long in case we want to add other options in the future
-        c = getopt_long(argc, argv, "h", longOptions, &optionIndex);
-        if (c == -1) {
-            break;
-        }
-        switch (c) {
-        case 'h': // falls through
-        default: // see unrecognized options
-            return usage();
-        }
-    }
-    return dump();
-
-}
diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h
index 94afae5..de5c1c7 100644
--- a/include/audiomanager/IPlayer.h
+++ b/include/audiomanager/IPlayer.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <media/VolumeShaper.h>
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
@@ -45,6 +46,9 @@
 
     virtual void setStartDelayMs(int delayMs) = 0;
 
+    virtual void applyVolumeShaper(
+            const sp<VolumeShaper::Configuration>& configuration,
+            const sp<VolumeShaper::Operation>& operation) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 46ca2c2..9e1ae94 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -95,6 +95,11 @@
     std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
 };
 
+struct CompositorTiming {
+    nsecs_t deadline{0};
+    nsecs_t interval{16666667};
+    nsecs_t presentLatency{0};
+};
 
 // A short history of frames that are synchronized between the consumer and
 // producer via deltas.
@@ -111,6 +116,8 @@
 
 protected:
     std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
+
+    CompositorTiming mCompositorTiming;
 };
 
 
@@ -119,6 +126,16 @@
 public:
     ~ProducerFrameEventHistory() override;
 
+    // Public for testing.
+    static nsecs_t snapToNextTick(
+            nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval);
+
+    nsecs_t getNextCompositeDeadline(const nsecs_t now) const;
+    nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; }
+    nsecs_t getCompositeToPresentLatency() const {
+        return mCompositorTiming.presentLatency;
+    }
+
     // virtual for testing.
     virtual void updateAcquireFence(
             uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
@@ -189,12 +206,15 @@
 public:
     ~ConsumerFrameEventHistory() override;
 
+    void initializeCompositorTiming(const CompositorTiming& compositorTiming);
+
     void addQueue(const NewFrameEventsEntry& newEntry);
     void addLatch(uint64_t frameNumber, nsecs_t latchTime);
     void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
     void addPostComposition(uint64_t frameNumber,
             const std::shared_ptr<FenceTime>& gpuCompositionDone,
-            const std::shared_ptr<FenceTime>& displayPresent);
+            const std::shared_ptr<FenceTime>& displayPresent,
+            const CompositorTiming& compositorTiming);
     void addRetire(uint64_t frameNumber,
             const std::shared_ptr<FenceTime>& displayRetire);
     void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime,
@@ -244,7 +264,7 @@
             size_t& count);
 
 private:
-    static size_t minFlattenedSize();
+    static constexpr size_t minFlattenedSize();
 
     size_t mIndex{0};
     uint64_t mFrameNumber{0};
@@ -306,9 +326,10 @@
             size_t& count);
 
 private:
-    static size_t minFlattenedSize();
+    static constexpr size_t minFlattenedSize();
 
     std::vector<FrameEventsDelta> mDeltas;
+    CompositorTiming mCompositorTiming;
 };
 
 
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
index 9e18907..54c9829 100644
--- a/include/gui/GraphicBufferAlloc.h
+++ b/include/gui/GraphicBufferAlloc.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
+#ifndef ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
+#define ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -25,10 +25,16 @@
 #include <utils/Errors.h>
 
 namespace android {
-// ---------------------------------------------------------------------------
 
 class GraphicBuffer;
 
+/*
+ * Concrete implementation of the IGraphicBufferAlloc interface.
+ *
+ * This can create GraphicBuffer instance across processes. This is mainly used
+ * by surfaceflinger.
+ */
+
 class GraphicBufferAlloc : public BnGraphicBufferAlloc {
 public:
     GraphicBufferAlloc();
@@ -40,7 +46,6 @@
 };
 
 
-// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
 
-#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H
+#endif // ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 60203f7..a3c2bfa 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_GUI_SURFACE_H
 #define ANDROID_GUI_SURFACE_H
 
-#include <binder/Parcelable.h>
-
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/BufferQueueDefs.h>
 
@@ -137,12 +135,18 @@
     status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]);
 
+    status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration);
+
     /* Enables or disables frame timestamp tracking. It is disabled by default
      * to avoid overhead during queue and dequeue for applications that don't
      * need the feature. If disabled, calls to getFrameTimestamps will fail.
      */
     void enableFrameTimestamps(bool enable);
 
+    status_t getCompositorTiming(
+            nsecs_t* compositeDeadline, nsecs_t* compositeInterval,
+            nsecs_t* compositeToPresentLatency);
+
     // See IGraphicBufferProducer::getFrameTimestamps
     status_t getFrameTimestamps(uint64_t frameNumber,
             nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
@@ -150,7 +154,6 @@
             nsecs_t* outLastRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
             nsecs_t* outDisplayPresentTime, nsecs_t* outDisplayRetireTime,
             nsecs_t* outDequeueReadyTime, nsecs_t* outReleaseTime);
-    status_t getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration);
 
     status_t getUniqueId(uint64_t* outId) const;
 
@@ -159,6 +162,7 @@
 
     // Virtual for testing.
     virtual sp<ISurfaceComposer> composerService() const;
+    virtual nsecs_t now() const;
 
 private:
     // can't be copied
@@ -206,9 +210,11 @@
     int dispatchSetSurfaceDamage(va_list args);
     int dispatchSetSharedBufferMode(va_list args);
     int dispatchSetAutoRefresh(va_list args);
-    int dispatchEnableFrameTimestamps(va_list args);
-    int dispatchGetFrameTimestamps(va_list args);
     int dispatchGetDisplayRefreshCycleDuration(va_list args);
+    int dispatchGetNextFrameId(va_list args);
+    int dispatchEnableFrameTimestamps(va_list args);
+    int dispatchGetCompositorTiming(va_list args);
+    int dispatchGetFrameTimestamps(va_list args);
 
 protected:
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
@@ -410,43 +416,6 @@
     std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
 };
 
-namespace view {
-
-/**
- * A simple holder for an IGraphicBufferProducer, to match the managed-side
- * android.view.Surface parcelable behavior.
- *
- * This implements android/view/Surface.aidl
- *
- * TODO: Convert IGraphicBufferProducer into AIDL so that it can be directly
- * used in managed Binder calls.
- */
-class Surface : public Parcelable {
-  public:
-
-    String16 name;
-    sp<IGraphicBufferProducer> graphicBufferProducer;
-
-    virtual status_t writeToParcel(Parcel* parcel) const override;
-    virtual status_t readFromParcel(const Parcel* parcel) override;
-
-    // nameAlreadyWritten set to true by Surface.java, because it splits
-    // Parceling itself between managed and native code, so it only wants a part
-    // of the full parceling to happen on its native side.
-    status_t writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const;
-
-    // nameAlreadyRead set to true by Surface.java, because it splits
-    // Parceling itself between managed and native code, so it only wants a part
-    // of the full parceling to happen on its native side.
-    status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead);
-
-  private:
-
-    static String16 readMaybeEmptyString16(const Parcel* parcel);
-};
-
-} // namespace view
-
-}; // namespace android
+} // namespace android
 
 #endif  // ANDROID_GUI_SURFACE_H
diff --git a/include/gui/view/Surface.h b/include/gui/view/Surface.h
new file mode 100644
index 0000000..cc64fd4
--- /dev/null
+++ b/include/gui/view/Surface.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_VIEW_SURFACE_H
+#define ANDROID_GUI_VIEW_SURFACE_H
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/String16.h>
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class IGraphicBufferProducer;
+
+namespace view {
+
+/**
+ * A simple holder for an IGraphicBufferProducer, to match the managed-side
+ * android.view.Surface parcelable behavior.
+ *
+ * This implements android/view/Surface.aidl
+ *
+ * TODO: Convert IGraphicBufferProducer into AIDL so that it can be directly
+ * used in managed Binder calls.
+ */
+class Surface : public Parcelable {
+  public:
+
+    String16 name;
+    sp<IGraphicBufferProducer> graphicBufferProducer;
+
+    virtual status_t writeToParcel(Parcel* parcel) const override;
+    virtual status_t readFromParcel(const Parcel* parcel) override;
+
+    // nameAlreadyWritten set to true by Surface.java, because it splits
+    // Parceling itself between managed and native code, so it only wants a part
+    // of the full parceling to happen on its native side.
+    status_t writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const;
+
+    // nameAlreadyRead set to true by Surface.java, because it splits
+    // Parceling itself between managed and native code, so it only wants a part
+    // of the full parceling to happen on its native side.
+    status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead);
+
+  private:
+
+    static String16 readMaybeEmptyString16(const Parcel* parcel);
+};
+
+} // namespace view
+} // namespace android
+
+#endif  // ANDROID_GUI_VIEW_SURFACE_H
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index 58df24c..37811bc 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -23,8 +23,6 @@
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
 
-#include <experimental/optional>
-
 namespace android {
 
 class String8;
@@ -105,26 +103,29 @@
     // error occurs then SIGNAL_TIME_INVALID is returned.
     nsecs_t getSignalTime() const;
 
-#if __cplusplus > 201103L
-    // hasSignaled returns whether the fence has signaled yet. Prefer this to
+    enum class Status {
+        Invalid,     // Fence is invalid
+        Unsignaled,  // Fence is valid but has not yet signaled
+        Signaled,    // Fence is valid and has signaled
+    };
+
+    // getStatus() returns whether the fence has signaled yet. Prefer this to
     // getSignalTime() or wait() if all you care about is whether the fence has
-    // signaled. Returns an optional bool, which will have a value if there was
-    // no error.
-    inline std::experimental::optional<bool> hasSignaled() {
+    // signaled.
+    inline Status getStatus() {
         // The sync_wait call underlying wait() has been measured to be
         // significantly faster than the sync_fence_info call underlying
         // getSignalTime(), which might otherwise appear to be the more obvious
         // way to check whether a fence has signaled.
         switch (wait(0)) {
             case NO_ERROR:
-                return true;
+                return Status::Signaled;
             case -ETIME:
-                return false;
+                return Status::Unsignaled;
             default:
-                return {};
+                return Status::Invalid;
         }
     }
-#endif
 
     // Flattenable interface
     size_t getFlattenedSize() const;
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 95ca0f3..759c9ec 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -76,11 +76,6 @@
     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
             uint32_t inUsage, std::string requestorName = "<Unknown>");
 
-    // creates w * h buffer with a layer count
-    GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
-            uint32_t inLayerCount, uint32_t inUsage,
-            std::string requestorName = "<Unknown>");
-
     // creates w * h buffer with a layer count using gralloc1
     GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
             uint32_t inLayerCount, uint64_t inProducerUsage,
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index 8e93f72..001769f 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -39,7 +39,9 @@
 public:
     static inline GraphicBufferMapper& get() { return getInstance(); }
 
+    // This may NOT work on devices without a valid Gralloc2::Mapper.
     status_t registerBuffer(buffer_handle_t handle);
+
     status_t registerBuffer(const GraphicBuffer* buffer);
 
     status_t unregisterBuffer(buffer_handle_t handle);
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index cb17da4..ddf1072 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -96,6 +96,7 @@
         "SurfaceControl.cpp",
         "SurfaceComposerClient.cpp",
         "SyncFeatures.cpp",
+        "view/Surface.cpp",
     ],
 
     shared_libs: [
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index be2b1af..c26de66 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -318,16 +318,16 @@
         return OK;
     }
 
-    auto signaled = mSlots[slot].mFence->hasSignaled();
+    auto status = mSlots[slot].mFence->getStatus();
 
-    if (!signaled) {
+    if (status == Fence::Status::Invalid) {
         CB_LOGE("fence has invalid state");
         return BAD_VALUE;
     }
 
-    if (*signaled) {
+    if (status == Fence::Status::Signaled) {
         mSlots[slot].mFence = fence;
-    } else {
+    } else {  // status == Fence::Status::Unsignaled
         char fenceName[32] = {};
         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
         sp<Fence> mergedFence = Fence::merge(
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 73537bf..a6fa38a 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -235,6 +235,23 @@
 
 ProducerFrameEventHistory::~ProducerFrameEventHistory() = default;
 
+nsecs_t ProducerFrameEventHistory::snapToNextTick(
+        nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval) {
+    nsecs_t tickOffset = (tickPhase - timestamp) % tickInterval;
+    // Integer modulo rounds towards 0 and not -inf before taking the remainder,
+    // so adjust the offset if it is negative.
+    if (tickOffset < 0) {
+        tickOffset += tickInterval;
+    }
+    return timestamp + tickOffset;
+}
+
+nsecs_t ProducerFrameEventHistory::getNextCompositeDeadline(
+        const nsecs_t now) const{
+    return snapToNextTick(
+            now, mCompositorTiming.deadline, mCompositorTiming.interval);
+}
+
 void ProducerFrameEventHistory::updateAcquireFence(
         uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) {
     FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset);
@@ -256,6 +273,8 @@
 
 void ProducerFrameEventHistory::applyDelta(
         const FrameEventHistoryDelta& delta) {
+    mCompositorTiming = delta.mCompositorTiming;
+
     for (auto& d : delta.mDeltas) {
         // Avoid out-of-bounds access.
         if (d.mIndex >= mFrames.size()) {
@@ -346,6 +365,11 @@
 
 ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
 
+void ConsumerFrameEventHistory::initializeCompositorTiming(
+        const CompositorTiming& compositorTiming) {
+    mCompositorTiming = compositorTiming;
+}
+
 void ConsumerFrameEventHistory::addQueue(const NewFrameEventsEntry& newEntry) {
     // Overwrite all fields of the frame with default values unless set here.
     FrameEvents newTimestamps;
@@ -393,7 +417,10 @@
 
 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
         const std::shared_ptr<FenceTime>& gpuCompositionDone,
-        const std::shared_ptr<FenceTime>& displayPresent) {
+        const std::shared_ptr<FenceTime>& displayPresent,
+        const CompositorTiming& compositorTiming) {
+    mCompositorTiming = compositorTiming;
+
     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
     if (frame == nullptr) {
         ALOGE_IF(mProducerWantsEvents,
@@ -450,6 +477,8 @@
 
 void ConsumerFrameEventHistory::getAndResetDelta(
         FrameEventHistoryDelta* delta) {
+    delta->mCompositorTiming = mCompositorTiming;
+
     // Write these in order of frame number so that it is easy to
     // add them to a FenceTimeline in the proper order producer side.
     delta->mDeltas.reserve(mFramesDirty.size());
@@ -499,9 +528,8 @@
     }
 }
 
-size_t FrameEventsDelta::minFlattenedSize() {
-    constexpr size_t min =
-            sizeof(FrameEventsDelta::mFrameNumber) +
+constexpr size_t FrameEventsDelta::minFlattenedSize() {
+    return sizeof(FrameEventsDelta::mFrameNumber) +
             sizeof(uint8_t) + // mIndex
             sizeof(uint8_t) + // mAddPostCompositeCalled
             sizeof(uint8_t) + // mAddRetireCalled
@@ -512,7 +540,6 @@
             sizeof(FrameEventsDelta::mFirstRefreshStartTime) +
             sizeof(FrameEventsDelta::mLastRefreshStartTime) +
             sizeof(FrameEventsDelta::mDequeueReadyTime);
-    return min;
 }
 
 // Flattenable implementation
@@ -618,6 +645,8 @@
 
 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
         FrameEventHistoryDelta&& src) {
+    mCompositorTiming = src.mCompositorTiming;
+
     if (CC_UNLIKELY(!mDeltas.empty())) {
         ALOGE("FrameEventHistoryDelta: Clobbering history.");
     }
@@ -626,8 +655,9 @@
     return *this;
 }
 
-size_t FrameEventHistoryDelta::minFlattenedSize() {
-    return sizeof(uint32_t);
+constexpr size_t FrameEventHistoryDelta::minFlattenedSize() {
+    return sizeof(uint32_t) + // mDeltas.size()
+            sizeof(mCompositorTiming);
 }
 
 size_t FrameEventHistoryDelta::getFlattenedSize() const {
@@ -654,6 +684,8 @@
         return NO_MEMORY;
     }
 
+    FlattenableUtils::write(buffer, size, mCompositorTiming);
+
     FlattenableUtils::write(
             buffer, size, static_cast<uint32_t>(mDeltas.size()));
     for (auto& d : mDeltas) {
@@ -671,6 +703,8 @@
         return NO_MEMORY;
     }
 
+    FlattenableUtils::read(buffer, size, mCompositorTiming);
+
     uint32_t deltaCount = 0;
     FlattenableUtils::read(buffer, size, deltaCount);
     if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index f2d3677..cc7d403 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -15,21 +15,15 @@
  ** limitations under the License.
  */
 
-#include <log/log.h>
-
-#include <ui/GraphicBuffer.h>
-
 #include <gui/GraphicBufferAlloc.h>
 
-// ----------------------------------------------------------------------------
+#include <log/log.h>
+
+
 namespace android {
-// ----------------------------------------------------------------------------
 
-GraphicBufferAlloc::GraphicBufferAlloc() {
-}
-
-GraphicBufferAlloc::~GraphicBufferAlloc() {
-}
+GraphicBufferAlloc::GraphicBufferAlloc() = default;
+GraphicBufferAlloc::~GraphicBufferAlloc() = default;
 
 sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
         uint32_t height, PixelFormat format, uint32_t layerCount,
@@ -44,15 +38,12 @@
         if (err == NO_MEMORY) {
             GraphicBuffer::dumpAllocationsToSystemLog();
         }
-        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) "
-             "failed (%s), handle=%p",
+        ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
                 width, height, layerCount, strerror(-err),
                 graphicBuffer->handle);
-        return 0;
+        graphicBuffer.clear();
     }
     return graphicBuffer;
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
+} // namespace android
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 2fd29d5..e2f733a 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -210,6 +210,10 @@
             mFlags |= SENSOR_FLAG_WAKE_UP;
         }
         break;
+    case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT:
+        mStringType = SENSOR_STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT;
+        mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
+        break;
     case SENSOR_TYPE_WRIST_TILT_GESTURE:
         mStringType = SENSOR_STRING_TYPE_WRIST_TILT_GESTURE;
         mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 46eaf28..513b889 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -196,7 +196,8 @@
         if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
             type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
             type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
-            type == SENSOR_TYPE_WRIST_TILT_GESTURE) {
+            type == SENSOR_TYPE_WRIST_TILT_GESTURE ||
+            type == SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT) {
             wakeUpSensor = true;
         }
         // For now we just return the first sensor of that type we find.
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index c663620..d285ef0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -18,9 +18,9 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
-#include <android/native_window.h>
+#include <gui/Surface.h>
 
-#include <binder/Parcel.h>
+#include <android/native_window.h>
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
@@ -32,7 +32,6 @@
 
 #include <gui/BufferItem.h>
 #include <gui/IProducerListener.h>
-#include <gui/Surface.h>
 
 #include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
@@ -101,6 +100,10 @@
     return ComposerService::getComposerService();
 }
 
+nsecs_t Surface::now() const {
+    return systemTime();
+}
+
 sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
     return mGraphicBufferProducer;
 }
@@ -143,11 +146,51 @@
             outTransformMatrix);
 }
 
+status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
+    ATRACE_CALL();
+
+    DisplayStatInfo stats;
+    status_t err = composerService()->getDisplayStats(NULL, &stats);
+
+    *outRefreshDuration = stats.vsyncPeriod;
+
+    return NO_ERROR;
+}
+
 void Surface::enableFrameTimestamps(bool enable) {
     Mutex::Autolock lock(mMutex);
+    // If going from disabled to enabled, get the initial values for
+    // compositor and display timing.
+    if (!mEnableFrameTimestamps && enable) {
+        FrameEventHistoryDelta delta;
+        mGraphicBufferProducer->getFrameTimestamps(&delta);
+        mFrameEventHistory->applyDelta(delta);
+    }
     mEnableFrameTimestamps = enable;
 }
 
+status_t Surface::getCompositorTiming(
+        nsecs_t* compositeDeadline, nsecs_t* compositeInterval,
+        nsecs_t* compositeToPresentLatency) {
+    Mutex::Autolock lock(mMutex);
+    if (!mEnableFrameTimestamps) {
+        return INVALID_OPERATION;
+    }
+
+    if (compositeDeadline != nullptr) {
+        *compositeDeadline =
+                mFrameEventHistory->getNextCompositeDeadline(now());
+    }
+    if (compositeInterval != nullptr) {
+        *compositeInterval = mFrameEventHistory->getCompositeInterval();
+    }
+    if (compositeToPresentLatency != nullptr) {
+        *compositeToPresentLatency =
+                mFrameEventHistory->getCompositeToPresentLatency();
+    }
+    return NO_ERROR;
+}
+
 static bool checkConsumerForUpdates(
         const FrameEvents* e, const uint64_t lastFrameNumber,
         const nsecs_t* outLatchTime,
@@ -261,16 +304,6 @@
 
     return NO_ERROR;
 }
-status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
-    ATRACE_CALL();
-
-    DisplayStatInfo stats;
-    status_t err = composerService()->getDisplayStats(NULL, &stats);
-
-    *outRefreshDuration = stats.vsyncPeriod;
-
-    return NO_ERROR;
-}
 
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
     Surface* c = getSelf(window);
@@ -832,15 +865,21 @@
     case NATIVE_WINDOW_SET_AUTO_REFRESH:
         res = dispatchSetAutoRefresh(args);
         break;
+    case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION:
+        res = dispatchGetDisplayRefreshCycleDuration(args);
+        break;
+    case NATIVE_WINDOW_GET_NEXT_FRAME_ID:
+        res = dispatchGetNextFrameId(args);
+        break;
     case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS:
         res = dispatchEnableFrameTimestamps(args);
         break;
+    case NATIVE_WINDOW_GET_COMPOSITOR_TIMING:
+        res = dispatchGetCompositorTiming(args);
+        break;
     case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS:
         res = dispatchGetFrameTimestamps(args);
         break;
-    case NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION:
-        res = dispatchGetDisplayRefreshCycleDuration(args);
-        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -961,14 +1000,33 @@
     return setAutoRefresh(autoRefresh);
 }
 
+int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) {
+    nsecs_t* outRefreshDuration = va_arg(args, int64_t*);
+    return getDisplayRefreshCycleDuration(outRefreshDuration);
+}
+
+int Surface::dispatchGetNextFrameId(va_list args) {
+    uint64_t* nextFrameId = va_arg(args, uint64_t*);
+    *nextFrameId = getNextFrameNumber();
+    return NO_ERROR;
+}
+
 int Surface::dispatchEnableFrameTimestamps(va_list args) {
     bool enable = va_arg(args, int);
     enableFrameTimestamps(enable);
     return NO_ERROR;
 }
 
+int Surface::dispatchGetCompositorTiming(va_list args) {
+    nsecs_t* compositeDeadline = va_arg(args, int64_t*);
+    nsecs_t* compositeInterval = va_arg(args, int64_t*);
+    nsecs_t* compositeToPresentLatency = va_arg(args, int64_t*);
+    return getCompositorTiming(compositeDeadline, compositeInterval,
+            compositeToPresentLatency);
+}
+
 int Surface::dispatchGetFrameTimestamps(va_list args) {
-    uint32_t framesAgo = va_arg(args, uint32_t);
+    uint64_t frameId = va_arg(args, uint64_t);
     nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*);
     nsecs_t* outAcquireTime = va_arg(args, int64_t*);
     nsecs_t* outLatchTime = va_arg(args, int64_t*);
@@ -979,18 +1037,13 @@
     nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*);
     nsecs_t* outDequeueReadyTime = va_arg(args, int64_t*);
     nsecs_t* outReleaseTime = va_arg(args, int64_t*);
-    return getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo,
+    return getFrameTimestamps(frameId,
             outRequestedPresentTime, outAcquireTime, outLatchTime,
             outFirstRefreshStartTime, outLastRefreshStartTime,
             outGlCompositionDoneTime, outDisplayPresentTime,
             outDisplayRetireTime, outDequeueReadyTime, outReleaseTime);
 }
 
-int Surface::dispatchGetDisplayRefreshCycleDuration(va_list args) {
-    nsecs_t* outRefreshDuration = va_arg(args, int64_t*);
-    return getDisplayRefreshCycleDuration(outRefreshDuration);
-}
-
 int Surface::connect(int api) {
     static sp<IProducerListener> listener = new DummyProducerListener();
     return connect(api, listener);
@@ -1539,74 +1592,4 @@
     return mGraphicBufferProducer->getUniqueId(outId);
 }
 
-namespace view {
-
-status_t Surface::writeToParcel(Parcel* parcel) const {
-    return writeToParcel(parcel, false);
-}
-
-status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const {
-    if (parcel == nullptr) return BAD_VALUE;
-
-    status_t res = OK;
-
-    if (!nameAlreadyWritten) {
-        res = parcel->writeString16(name);
-        if (res != OK) return res;
-
-        /* isSingleBuffered defaults to no */
-        res = parcel->writeInt32(0);
-        if (res != OK) return res;
-    }
-
-    res = parcel->writeStrongBinder(
-            IGraphicBufferProducer::asBinder(graphicBufferProducer));
-
-    return res;
-}
-
-status_t Surface::readFromParcel(const Parcel* parcel) {
-    return readFromParcel(parcel, false);
-}
-
-status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) {
-    if (parcel == nullptr) return BAD_VALUE;
-
-    status_t res = OK;
-    if (!nameAlreadyRead) {
-        name = readMaybeEmptyString16(parcel);
-        // Discard this for now
-        int isSingleBuffered;
-        res = parcel->readInt32(&isSingleBuffered);
-        if (res != OK) {
-            ALOGE("Can't read isSingleBuffered");
-            return res;
-        }
-    }
-
-    sp<IBinder> binder;
-
-    res = parcel->readNullableStrongBinder(&binder);
-    if (res != OK) {
-        ALOGE("%s: Can't read strong binder", __FUNCTION__);
-        return res;
-    }
-
-    graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
-
-    return OK;
-}
-
-String16 Surface::readMaybeEmptyString16(const Parcel* parcel) {
-    size_t len;
-    const char16_t* str = parcel->readString16Inplace(&len);
-    if (str != nullptr) {
-        return String16(str, len);
-    } else {
-        return String16();
-    }
-}
-
-} // namespace view
-
 }; // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 412c0f6..5298027 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -479,8 +479,17 @@
         return mFakeSurfaceComposer;
     }
 
+    nsecs_t now() const override {
+        return mNow;
+    }
+
+    void setNow(nsecs_t now) {
+        mNow = now;
+    }
+
 public:
     sp<FakeSurfaceComposer> mFakeSurfaceComposer;
+    nsecs_t mNow = 0;
 
     // mFrameEventHistory owns the instance of FakeProducerFrameEventHistory,
     // but this raw pointer gives access to test functionality.
@@ -500,10 +509,12 @@
 
     struct RefreshEvents {
         RefreshEvents(FenceToFenceTimeMap& fenceMap, nsecs_t refreshStart)
-            : mFenceMap(fenceMap),
-              kStartTime(refreshStart + 1),
-              kGpuCompositionDoneTime(refreshStart + 2),
-              kPresentTime(refreshStart + 3) {}
+          : mFenceMap(fenceMap),
+            kCompositorTiming(
+                {refreshStart, refreshStart + 1, refreshStart + 2 }),
+            kStartTime(refreshStart + 3),
+            kGpuCompositionDoneTime(refreshStart + 4),
+            kPresentTime(refreshStart + 5) {}
 
         void signalPostCompositeFences() {
             mFenceMap.signalAllForTest(
@@ -516,6 +527,8 @@
         FenceAndFenceTime mGpuCompositionDone { mFenceMap };
         FenceAndFenceTime mPresent { mFenceMap };
 
+        const CompositorTiming kCompositorTiming;
+
         const nsecs_t kStartTime;
         const nsecs_t kGpuCompositionDoneTime;
         const nsecs_t kPresentTime;
@@ -592,14 +605,20 @@
         native_window_set_buffer_count(mWindow.get(), 4);
     }
 
+    void disableFrameTimestamps() {
+        mFakeConsumer->mGetFrameTimestampsEnabled = false;
+        native_window_enable_frame_timestamps(mWindow.get(), 0);
+        mFrameTimestampsEnabled = false;
+    }
+
     void enableFrameTimestamps() {
         mFakeConsumer->mGetFrameTimestampsEnabled = true;
         native_window_enable_frame_timestamps(mWindow.get(), 1);
         mFrameTimestampsEnabled = true;
     }
 
-    int getAllFrameTimestamps(uint32_t framesAgo) {
-        return native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    int getAllFrameTimestamps(uint64_t frameId) {
+        return native_window_get_frame_timestamps(mWindow.get(), frameId,
                 &outRequestedPresentTime, &outAcquireTime, &outLatchTime,
                 &outFirstRefreshStartTime, &outLastRefreshStartTime,
                 &outGpuCompositionDoneTime, &outDisplayPresentTime,
@@ -619,6 +638,13 @@
         outReleaseTime = -1;
     }
 
+    uint64_t getNextFrameId() {
+        uint64_t frameId = -1;
+        int status = native_window_get_next_frame_id(mWindow.get(), &frameId);
+        EXPECT_EQ(status, NO_ERROR);
+        return frameId;
+    }
+
     void dequeueAndQueue(uint64_t frameIndex) {
         int fence = -1;
         ANativeWindowBuffer* buffer = nullptr;
@@ -674,7 +700,8 @@
                     oldFrame->mRefreshes[2].mGpuCompositionDone.mFenceTime :
                     FenceTime::NO_FENCE;
             mCfeh->addPostComposition(nOldFrame, gpuDoneFenceTime,
-                    oldFrame->mRefreshes[2].mPresent.mFenceTime);
+                    oldFrame->mRefreshes[2].mPresent.mFenceTime,
+                    oldFrame->mRefreshes[2].kCompositorTiming);
         }
 
         // Latch the new frame.
@@ -691,7 +718,8 @@
                     std::shared_ptr<FenceTime>(oldFrame->mRelease.mFenceTime));
         }
         mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
-                newFrame->mRefreshes[0].mPresent.mFenceTime);
+                newFrame->mRefreshes[0].mPresent.mFenceTime,
+                newFrame->mRefreshes[0].kCompositorTiming);
 
         // Retire the previous buffer just after compositing the new buffer.
         if (oldFrame != nullptr) {
@@ -703,7 +731,8 @@
                 newFrame->mRefreshes[1].mGpuCompositionDone.mFenceTime :
                 FenceTime::NO_FENCE;
         mCfeh->addPostComposition(nNewFrame, gpuDoneFenceTime,
-                newFrame->mRefreshes[1].mPresent.mFenceTime);
+                newFrame->mRefreshes[1].mPresent.mFenceTime,
+                newFrame->mRefreshes[1].kCompositorTiming);
     }
 
     void QueryPresentRetireSupported(
@@ -733,7 +762,8 @@
     int64_t outDequeueReadyTime = -1;
     int64_t outReleaseTime = -1;
 
-    FrameEvents mFrames[2] { { mFenceMap, 1000 }, { mFenceMap, 2000 } };
+    FrameEvents mFrames[3] {
+        { mFenceMap, 1000 }, { mFenceMap, 2000 }, { mFenceMap, 3000 } };
 };
 
 
@@ -748,6 +778,8 @@
     EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
     EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
 
+    const uint64_t fId = getNextFrameId();
+
     // Verify the producer doesn't get frame timestamps piggybacked on dequeue.
     ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
     EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
@@ -761,27 +793,58 @@
     EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
 
     // Verify attempts to get frame timestamps fail.
-    const uint32_t framesAgo = 0;
-    int result = getAllFrameTimestamps(framesAgo);
+    int result = getAllFrameTimestamps(fId);
     EXPECT_EQ(INVALID_OPERATION, result);
     EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+
+    // Verify compositor timing query fails.
+    nsecs_t compositeDeadline = 0;
+    nsecs_t compositeInterval = 0;
+    nsecs_t compositeToPresentLatency = 0;
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(INVALID_OPERATION, result);
 }
 
 // This test verifies that the frame timestamps are retrieved if explicitly
 // enabled via native_window_enable_frame_timestamps.
 TEST_F(GetFrameTimestampsTest, EnabledSimple) {
+    CompositorTiming initialCompositorTiming {
+        1000000000, // 1s deadline
+        16666667, // 16ms interval
+        50000000, // 50ms present latency
+    };
+    mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
     enableFrameTimestamps();
 
+    // Verify the compositor timing query gets the initial compositor values
+    // after timststamps are enabled; even before the first frame is queued
+    // or dequeued.
+    nsecs_t compositeDeadline = 0;
+    nsecs_t compositeInterval = 0;
+    nsecs_t compositeToPresentLatency = 0;
+    mSurface->setNow(initialCompositorTiming.deadline - 1);
+    int result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+    EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+    EXPECT_EQ(initialCompositorTiming.presentLatency,
+              compositeToPresentLatency);
+
     int fence;
     ANativeWindowBuffer* buffer;
 
     EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
-    EXPECT_EQ(0, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount);
+
+    const uint64_t fId1 = getNextFrameId();
 
     // Verify getFrameTimestamps is piggybacked on dequeue.
     ASSERT_EQ(NO_ERROR, mWindow->dequeueBuffer(mWindow.get(), &buffer, &fence));
     EXPECT_EQ(0, mFakeConsumer->mAddFrameTimestampsCount);
-    EXPECT_EQ(1, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount);
 
     NewFrameEventsEntry f1;
     f1.frameNumber = 1;
@@ -798,14 +861,13 @@
     ASSERT_EQ(NO_ERROR, mWindow->queueBuffer(mWindow.get(), buffer, fence));
     EXPECT_EQ(1, mFakeConsumer->mAddFrameTimestampsCount);
     EXPECT_EQ(1u, mFakeConsumer->mLastAddedFrameNumber);
-    EXPECT_EQ(2, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
 
     // Verify queries for timestamps that the producer doesn't know about
     // triggers a call to see if the consumer has any new timestamps.
-    const uint32_t framesAgo = 0;
-    int result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(NO_ERROR, result);
-    EXPECT_EQ(3, mFakeConsumer->mGetFrameTimestampsCount);
+    EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
 }
 
 void GetFrameTimestampsTest::QueryPresentRetireSupported(
@@ -833,16 +895,245 @@
    QueryPresentRetireSupported(false, true);
 }
 
-// This test verifies that:
-// 1) The timestamps recorded in the consumer's FrameTimestampsHistory are
-//    properly retrieved by the producer for the correct frames.
-// 2) When framesAgo is 0, it is querying for the most recently queued frame.
+TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
+    nsecs_t phase = 4000;
+    nsecs_t interval = 1000;
+
+    // Timestamp in previous interval.
+    nsecs_t timestamp = 3500;
+    EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp in next interval.
+    timestamp = 4500;
+    EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp multiple intervals before.
+    timestamp = 2500;
+    EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp multiple intervals after.
+    timestamp = 6500;
+    EXPECT_EQ(7000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp on previous interval.
+    timestamp = 3000;
+    EXPECT_EQ(3000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp on next interval.
+    timestamp = 5000;
+    EXPECT_EQ(5000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+
+    // Timestamp equal to phase.
+    timestamp = 4000;
+    EXPECT_EQ(4000, ProducerFrameEventHistory::snapToNextTick(
+            timestamp, phase, interval));
+}
+
+// int(big_timestamp / interval) < 0, which can cause a crash or invalid result
+// if the number of intervals elapsed is internally stored in an int.
+TEST_F(GetFrameTimestampsTest, SnapToNextTickOverflow) {
+      nsecs_t phase = 0;
+      nsecs_t interval = 4000;
+      nsecs_t big_timestamp = 8635916564000;
+      int32_t intervals = big_timestamp / interval;
+
+      EXPECT_LT(intervals, 0);
+      EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick(
+            big_timestamp, phase, interval));
+      EXPECT_EQ(8635916564000, ProducerFrameEventHistory::snapToNextTick(
+            big_timestamp, big_timestamp, interval));
+}
+
+// This verifies the compositor timing is updated by refresh events
+// and piggy backed on a queue, dequeue, and enabling of timestamps..
+TEST_F(GetFrameTimestampsTest, CompositorTimingUpdatesBasic) {
+    CompositorTiming initialCompositorTiming {
+        1000000000, // 1s deadline
+        16666667, // 16ms interval
+        50000000, // 50ms present latency
+    };
+    mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
+    enableFrameTimestamps();
+
+    // We get the initial values before any frames are submitted.
+    nsecs_t compositeDeadline = 0;
+    nsecs_t compositeInterval = 0;
+    nsecs_t compositeToPresentLatency = 0;
+    mSurface->setNow(initialCompositorTiming.deadline - 1);
+    int result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+    EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+    EXPECT_EQ(initialCompositorTiming.presentLatency,
+              compositeToPresentLatency);
+
+    const uint64_t fId1 = getNextFrameId();
+    dequeueAndQueue(0);
+    addFrameEvents(true, NO_FRAME_INDEX, 0);
+
+    // Still get the initial values because the frame events for frame 0
+    // didn't get a chance to piggyback on a queue or dequeue yet.
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+    EXPECT_EQ(initialCompositorTiming.interval, compositeInterval);
+    EXPECT_EQ(initialCompositorTiming.presentLatency,
+              compositeToPresentLatency);
+
+    const uint64_t fId2 = getNextFrameId();
+    dequeueAndQueue(1);
+    addFrameEvents(true, 0, 1);
+
+    // Now expect the composite values associated with frame 1.
+    mSurface->setNow(mFrames[0].mRefreshes[1].kCompositorTiming.deadline);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.deadline,
+            compositeDeadline);
+    EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.interval,
+            compositeInterval);
+    EXPECT_EQ(mFrames[0].mRefreshes[1].kCompositorTiming.presentLatency,
+            compositeToPresentLatency);
+
+    dequeueAndQueue(2);
+    addFrameEvents(true, 1, 2);
+
+    // Now expect the composite values associated with frame 2.
+    mSurface->setNow(mFrames[1].mRefreshes[1].kCompositorTiming.deadline);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.deadline,
+            compositeDeadline);
+    EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.interval,
+            compositeInterval);
+    EXPECT_EQ(mFrames[1].mRefreshes[1].kCompositorTiming.presentLatency,
+            compositeToPresentLatency);
+
+    // Re-enabling frame timestamps should get the latest values.
+    disableFrameTimestamps();
+    enableFrameTimestamps();
+
+    // Now expect the composite values associated with frame 3.
+    mSurface->setNow(mFrames[2].mRefreshes[1].kCompositorTiming.deadline);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.deadline,
+            compositeDeadline);
+    EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.interval,
+            compositeInterval);
+    EXPECT_EQ(mFrames[2].mRefreshes[1].kCompositorTiming.presentLatency,
+            compositeToPresentLatency);
+}
+
+// This verifies the compositor deadline properly snaps to the the next
+// deadline based on the current time.
+TEST_F(GetFrameTimestampsTest, CompositorTimingDeadlineSnaps) {
+    CompositorTiming initialCompositorTiming {
+        1000000000, // 1s deadline
+        16666667, // 16ms interval
+        50000000, // 50ms present latency
+    };
+    mCfeh->initializeCompositorTiming(initialCompositorTiming);
+
+    enableFrameTimestamps();
+
+    nsecs_t compositeDeadline = 0;
+    nsecs_t compositeInterval = 0;
+    nsecs_t compositeToPresentLatency = 0;
+
+    // A "now" just before the deadline snaps to the deadline.
+    mSurface->setNow(initialCompositorTiming.deadline - 1);
+    int result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    EXPECT_EQ(initialCompositorTiming.deadline, compositeDeadline);
+    nsecs_t expectedDeadline = initialCompositorTiming.deadline;
+    EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+    const uint64_t fId1 = getNextFrameId();
+    dequeueAndQueue(0);
+    addFrameEvents(true, NO_FRAME_INDEX, 0);
+
+    // A "now" just after the deadline snaps properly.
+    mSurface->setNow(initialCompositorTiming.deadline + 1);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    expectedDeadline =
+            initialCompositorTiming.deadline +initialCompositorTiming.interval;
+    EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+    const uint64_t fId2 = getNextFrameId();
+    dequeueAndQueue(1);
+    addFrameEvents(true, 0, 1);
+
+    // A "now" just after the next interval snaps properly.
+    mSurface->setNow(
+            mFrames[0].mRefreshes[1].kCompositorTiming.deadline +
+            mFrames[0].mRefreshes[1].kCompositorTiming.interval + 1);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    expectedDeadline =
+            mFrames[0].mRefreshes[1].kCompositorTiming.deadline +
+            mFrames[0].mRefreshes[1].kCompositorTiming.interval * 2;
+    EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+    dequeueAndQueue(2);
+    addFrameEvents(true, 1, 2);
+
+    // A "now" over 1 interval before the deadline snaps properly.
+    mSurface->setNow(
+            mFrames[1].mRefreshes[1].kCompositorTiming.deadline -
+            mFrames[1].mRefreshes[1].kCompositorTiming.interval - 1);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    expectedDeadline =
+            mFrames[1].mRefreshes[1].kCompositorTiming.deadline -
+            mFrames[1].mRefreshes[1].kCompositorTiming.interval;
+    EXPECT_EQ(expectedDeadline, compositeDeadline);
+
+    // Re-enabling frame timestamps should get the latest values.
+    disableFrameTimestamps();
+    enableFrameTimestamps();
+
+    // A "now" over 2 intervals before the deadline snaps properly.
+    mSurface->setNow(
+            mFrames[2].mRefreshes[1].kCompositorTiming.deadline -
+            mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2 - 1);
+    result = native_window_get_compositor_timing(mWindow.get(),
+        &compositeDeadline, &compositeInterval, &compositeToPresentLatency);
+    EXPECT_EQ(NO_ERROR, result);
+    expectedDeadline =
+            mFrames[2].mRefreshes[1].kCompositorTiming.deadline -
+            mFrames[2].mRefreshes[1].kCompositorTiming.interval * 2;
+    EXPECT_EQ(expectedDeadline, compositeDeadline);
+}
+
+// This verifies the timestamps recorded in the consumer's
+// FrameTimestampsHistory are properly retrieved by the producer for the
+// correct frames.
 TEST_F(GetFrameTimestampsTest, TimestampsAssociatedWithCorrectFrame) {
     enableFrameTimestamps();
 
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
     mFrames[0].signalQueueFences();
 
+    const uint64_t fId2 = getNextFrameId();
     dequeueAndQueue(1);
     mFrames[1].signalQueueFences();
 
@@ -853,9 +1144,8 @@
     mFrames[1].signalRefreshFences();
 
     // Verify timestamps are correct for frame 1.
-    uint32_t framesAgo = 1;
     resetTimestamps();
-    int result = getAllFrameTimestamps(framesAgo);
+    int result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
     EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
@@ -870,9 +1160,8 @@
     EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
 
     // Verify timestamps are correct for frame 2.
-    framesAgo = 0;
     resetTimestamps();
-    result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId2);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
     EXPECT_EQ(mFrames[1].kProducerAcquireTime, outAcquireTime);
@@ -893,9 +1182,8 @@
     enableFrameTimestamps();
     mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
 
-    const uint32_t framesAgo = 0;
-
     // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
 
     // Verify queue-related timestamps for f1 are available immediately in the
@@ -903,7 +1191,7 @@
     // acquire fence.
     resetTimestamps();
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
             &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
@@ -915,7 +1203,7 @@
     mFrames[0].signalQueueFences();
 
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    result = native_window_get_frame_timestamps(mWindow.get(), fId1,
             &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
@@ -924,6 +1212,7 @@
     EXPECT_EQ(mFrames[0].kProducerAcquireTime, outAcquireTime);
 
     // Dequeue and queue frame 2.
+    const uint64_t fId2 = getNextFrameId();
     dequeueAndQueue(1);
 
     // Verify queue-related timestamps for f2 are available immediately in the
@@ -931,7 +1220,7 @@
     // acquire fence.
     resetTimestamps();
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    result = native_window_get_frame_timestamps(mWindow.get(), fId2,
             &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
@@ -943,7 +1232,7 @@
     mFrames[1].signalQueueFences();
 
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    result = native_window_get_frame_timestamps(mWindow.get(), fId2,
             &outRequestedPresentTime, &outAcquireTime, nullptr, nullptr,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
@@ -961,6 +1250,7 @@
     mFrames[0].signalQueueFences();
 
     // Dequeue and queue frame 2.
+    const uint64_t fId2 = getNextFrameId();
     dequeueAndQueue(1);
     mFrames[1].signalQueueFences();
 
@@ -971,9 +1261,8 @@
     mFrames[1].signalRefreshFences();
 
     // Verify a request for no timestamps doesn't result in a sync call.
-    const uint32_t framesAgo = 0;
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    int result = native_window_get_frame_timestamps(mWindow.get(), fId2,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
             nullptr, nullptr, nullptr);
     EXPECT_EQ(NO_ERROR, result);
@@ -987,6 +1276,7 @@
     mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
 
     // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
     mFrames[0].signalQueueFences();
 
@@ -1001,10 +1291,9 @@
     // fence has been signaled.
     // Note: A sync call is necessary here since the events triggered by
     // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
-    uint32_t framesAgo = 1;
     resetTimestamps();
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = getAllFrameTimestamps(framesAgo);
+    int result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1021,10 +1310,9 @@
     // Verify available timestamps are correct for frame 1 again, before any
     // fence has been signaled.
     // This time a sync call should not be necessary.
-    framesAgo = 1;
     resetTimestamps();
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1043,10 +1331,9 @@
     mFrames[0].signalReleaseFences();
 
     // Verify all timestamps are available without a sync call.
-    framesAgo = 1;
     resetTimestamps();
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1069,9 +1356,8 @@
     enableFrameTimestamps();
     mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
 
-    const uint32_t framesAgo = 1;
-
     // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
     mFrames[0].signalQueueFences();
 
@@ -1088,7 +1374,7 @@
     // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
     resetTimestamps();
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = getAllFrameTimestamps(framesAgo);
+    int result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1110,7 +1396,7 @@
     // sync call.
     resetTimestamps();
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1132,10 +1418,12 @@
     mSurface->mFakeSurfaceComposer->setSupportedTimestamps(true, true);
 
     // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
     mFrames[0].signalQueueFences();
 
     // Dequeue and queue frame 2.
+    const uint64_t fId2 = getNextFrameId();
     dequeueAndQueue(1);
     mFrames[1].signalQueueFences();
 
@@ -1146,10 +1434,9 @@
     // fence has been signaled.
     // Note: A sync call is necessary here since the events triggered by
     // addFrameEvents didn't get to piggyback on the earlier queues/dequeues.
-    uint32_t framesAgo = 1;
     resetTimestamps();
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = getAllFrameTimestamps(framesAgo);
+    int result = getAllFrameTimestamps(fId1);
     EXPECT_EQ(oldCount + 1, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
@@ -1167,15 +1454,14 @@
     mFrames[0].signalReleaseFences();
     mFrames[1].signalRefreshFences();
 
-    // Verify querying for all timestmaps of f2 does not do a sync call.
-    // Even though the lastRefresh, retire, dequeueReady, and release times aren't
+    // Verify querying for all timestmaps of f2 does not do a sync call. Even
+    // though the lastRefresh, retire, dequeueReady, and release times aren't
     // available, a sync call should not occur because it's not possible for f2
     // to encounter the final value for those events until another frame is
     // queued.
-    framesAgo = 0;
     resetTimestamps();
     oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    result = getAllFrameTimestamps(framesAgo);
+    result = getAllFrameTimestamps(fId2);
     EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
     EXPECT_EQ(NO_ERROR, result);
     EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
@@ -1200,14 +1486,14 @@
         displayPresentSupported, displayRetireSupported);
 
     // Dequeue and queue frame 1.
+    const uint64_t fId1 = getNextFrameId();
     dequeueAndQueue(0);
 
     // Verify a query for the Present and Retire times do not trigger
     // a sync call if they are not supported.
-    const uint32_t framesAgo = 0;
     resetTimestamps();
     int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
-    int result = native_window_get_frame_timestamps(mWindow.get(), framesAgo,
+    int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
             displayPresentSupported ? nullptr : &outDisplayPresentTime,
             displayRetireSupported ? nullptr : &outDisplayRetireTime,
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
new file mode 100644
index 0000000..5ed3d3b
--- /dev/null
+++ b/libs/gui/view/Surface.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Surface"
+
+#include <gui/view/Surface.h>
+
+#include <binder/Parcel.h>
+
+#include <utils/Log.h>
+
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+namespace view {
+
+status_t Surface::writeToParcel(Parcel* parcel) const {
+    return writeToParcel(parcel, false);
+}
+
+status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const {
+    if (parcel == nullptr) return BAD_VALUE;
+
+    status_t res = OK;
+
+    if (!nameAlreadyWritten) {
+        res = parcel->writeString16(name);
+        if (res != OK) return res;
+
+        /* isSingleBuffered defaults to no */
+        res = parcel->writeInt32(0);
+        if (res != OK) return res;
+    }
+
+    res = parcel->writeStrongBinder(
+            IGraphicBufferProducer::asBinder(graphicBufferProducer));
+
+    return res;
+}
+
+status_t Surface::readFromParcel(const Parcel* parcel) {
+    return readFromParcel(parcel, false);
+}
+
+status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) {
+    if (parcel == nullptr) return BAD_VALUE;
+
+    status_t res = OK;
+    if (!nameAlreadyRead) {
+        name = readMaybeEmptyString16(parcel);
+        // Discard this for now
+        int isSingleBuffered;
+        res = parcel->readInt32(&isSingleBuffered);
+        if (res != OK) {
+            ALOGE("Can't read isSingleBuffered");
+            return res;
+        }
+    }
+
+    sp<IBinder> binder;
+
+    res = parcel->readNullableStrongBinder(&binder);
+    if (res != OK) {
+        ALOGE("%s: Can't read strong binder", __FUNCTION__);
+        return res;
+    }
+
+    graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
+
+    return OK;
+}
+
+String16 Surface::readMaybeEmptyString16(const Parcel* parcel) {
+    size_t len;
+    const char16_t* str = parcel->readString16Inplace(&len);
+    if (str != nullptr) {
+        return String16(str, len);
+    } else {
+        return String16();
+    }
+}
+
+} // namespace view
+} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 5ef95ec..b544426 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -50,8 +50,8 @@
     height =
     stride =
     format =
-    layerCount =
     usage  = 0;
+    layerCount = 0;
     handle = NULL;
 }
 
@@ -64,8 +64,8 @@
     height =
     stride =
     format =
-    layerCount =
     usage  = 0;
+    layerCount = 0;
     handle = NULL;
     mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
             std::move(requestorName));
@@ -81,8 +81,8 @@
     height =
     stride =
     format =
-    layerCount =
     usage  = 0;
+    layerCount = 0;
     handle = NULL;
     mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount,
             producerUsage, consumerUsage, std::move(requestorName));
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index b0ed2df..a3b6e18 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -63,7 +63,14 @@
     if (mMapper->valid()) {
         error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
     } else {
+        // This always returns GRALLOC1_BAD_HANDLE when handle is from a
+        // remote process and mDevice is backed by Gralloc1On0Adapter.
         error = mDevice->retain(handle);
+        if (error == GRALLOC1_ERROR_BAD_HANDLE &&
+                mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
+            ALOGE("registerBuffer by handle is not supported with "
+                  "Gralloc1On0Adapter");
+        }
     }
 
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
diff --git a/libs/vr/libgvr/.clang-format b/libs/vr/libgvr/.clang-format
deleted file mode 100644
index 3287160..0000000
--- a/libs/vr/libgvr/.clang-format
+++ /dev/null
@@ -1,2 +0,0 @@
-Language: Cpp
-DisableFormat: true
diff --git a/libs/vr/libgvr/Android.mk b/libs/vr/libgvr/Android.mk
deleted file mode 100644
index 0daf2ea..0000000
--- a/libs/vr/libgvr/Android.mk
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-LOCAL_PATH := $(call my-dir)
-
-include_dirs := \
-  $(LOCAL_PATH)/include \
-  $(LOCAL_PATH)/prebuilt/include
-
-# Java platform library for the system implementation of the GVR API.
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.google.vr.gvr.platform
-LOCAL_REQUIRED_MODULES := libgvr_system_loader libgvr_system
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-include $(BUILD_JAVA_LIBRARY)
-
-# Library to perform dlopen on the actual platform library.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgvr_system_loader
-LOCAL_SRC_FILES := library_loader.cpp
-include $(BUILD_SHARED_LIBRARY)
-
-# Shared library implementing the GVR API.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgvr_system
-
-LOCAL_SRC_FILES := \
-    shim_gvr.cpp \
-    shim_gvr_controller.cpp \
-    shim_gvr_private.cpp \
-    deviceparams/CardboardDevice.nolite.proto
-
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-
-LOCAL_C_INCLUDES := $(include_dirs)
-LOCAL_C_INCLUDES += $(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(include_dirs)
-
-gvr_api_linker_script := $(LOCAL_PATH)/exported_apis.lds
-LOCAL_ADDITIONAL_DEPENDENCIES := $(gvr_api_linker_script)
-
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
-LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
-LOCAL_LDFLAGS += -Wl,-version-script,$(gvr_api_linker_script)
-
-LOCAL_SHARED_LIBRARIES := \
-    libandroid_runtime \
-    libbase \
-    libbinder \
-    libcutils \
-    libutils \
-    libgui \
-    libui \
-    libEGL \
-    libGLESv2 \
-    libvulkan \
-    libhardware \
-    liblog \
-    libsync \
-    libprotobuf-cpp-full
-
-LOCAL_STATIC_LIBRARIES := \
-    libdisplay \
-    libbufferhub \
-    libbufferhubqueue \
-    libdvrcommon \
-    libeds \
-    libdvrgraphics \
-    libsensor \
-    libperformance \
-    libpdx_default_transport \
-
-include $(BUILD_SHARED_LIBRARY)
-
-# Prebuilt shared library for libgvr_audio.so
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgvr_audio
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE_SUFFIX := .so
-LOCAL_MULTILIB := both
-LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
-LOCAL_SRC_FILES_arm := prebuilt/lib/android_arm/libgvr_audio.so
-LOCAL_SRC_FILES_arm64 := prebuilt/lib/android_arm64/libgvr_audio.so
-LOCAL_SRC_FILES_x86 := prebuilt/lib/android_x86/libgvr_audio.so
-LOCAL_SRC_FILES_x86_64 := prebuilt/lib/android_x86_64/libgvr_audio.so
-include $(BUILD_PREBUILT)
-
-# Prebuilt shared library for libgvr.so
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgvr
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/prebuilt/include
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE_SUFFIX := .so
-LOCAL_MULTILIB := both
-LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
-LOCAL_SRC_FILES_arm := prebuilt/lib/android_arm/libgvr.so
-LOCAL_SRC_FILES_arm64 := prebuilt/lib/android_arm64/libgvr.so
-LOCAL_SRC_FILES_x86 := prebuilt/lib/android_x86/libgvr.so
-LOCAL_SRC_FILES_x86_64 := prebuilt/lib/android_x86_64/libgvr.so
-include $(BUILD_PREBUILT)
-
-# Prebuilt Java static library for common_library.aar
-include $(CLEAR_VARS)
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-    gvr_common_library_aar:prebuilt/lib/common_library.aar
-include $(BUILD_MULTI_PREBUILT)
-
-# Dummy libgvr_ext to be used along side libgvr.so prebuilt.
-# This shall be replaced with Google3 prebuilts in future.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libgvr_ext
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SRC_FILES := dummy_gvr_ext.cpp
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES += libgvr
-LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
-include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/vr/libgvr/CPPLINT.cfg b/libs/vr/libgvr/CPPLINT.cfg
deleted file mode 100644
index 2da1c50..0000000
--- a/libs/vr/libgvr/CPPLINT.cfg
+++ /dev/null
@@ -1 +0,0 @@
-filter=-build/header_guard,-build/include_alpha
diff --git a/libs/vr/libgvr/README.dreamos b/libs/vr/libgvr/README.dreamos
deleted file mode 100644
index d847210..0000000
--- a/libs/vr/libgvr/README.dreamos
+++ /dev/null
@@ -1 +0,0 @@
-Files under public/vr/gvr were imported from the public Google VR SDK.
diff --git a/libs/vr/libgvr/com.google.vr.gvr.platform.xml b/libs/vr/libgvr/com.google.vr.gvr.platform.xml
deleted file mode 100644
index 9297c7f..0000000
--- a/libs/vr/libgvr/com.google.vr.gvr.platform.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<permissions>
-    <library name="com.google.vr.gvr.platform"
-             file="/system/framework/com.google.vr.gvr.platform.jar" />
-</permissions>
diff --git a/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto b/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto
deleted file mode 100644
index 77b5d72..0000000
--- a/libs/vr/libgvr/deviceparams/CardboardDevice.nolite.proto
+++ /dev/null
@@ -1,299 +0,0 @@
-
-syntax = "proto2";
-
-option java_package = "com.google.vrtoolkit.cardboard.proto";
-option java_outer_classname = "CardboardDevice";
-option optimize_for = SPEED;
-
-package proto;
-
-
-/**
- * Message describing properties of a VR head mount device (HMD) which uses an
- * interchangeable smartphone as a display (e.g. Google Cardboard).
- *
- * While some properties are certain (e.g. inter_lens_distance), others
- * represent nominal values which may be refined depending on context (e.g.
- * viewport_angles).
- *
- * Lengths are in meters unless noted otherwise.  Fields are _required_
- * unless noted otherwise.
- *
- * Some context on why this set of parameters are deemed necessary and
- * sufficient:
- *    * FOV scale can be reasonably approximated from lens-to-screen distance
- *      and display size (i.e. knowing lens focal length isn't crucial).
- *    * Lenses are assumed to be horizontally centered with respect to
- *      display.
- *    * The display is not necessarily vertically centered.  For interchangeable
- *      phones where the device rests against a tray, we can derive
- *      the vertical offset from tray-to-lens height along with phone-specific
- *      bezel and screen sizes (supplied separately).
- */
-message DeviceParams {
-  // String identifying the device's vendor (e.g. "Google, Inc.").
-  // A device's [vendor, model] pair is expected to be globally unique.
-  optional string vendor = 1;
-
-  // String identifying the device's model, including revision info if
-  // needed (e.g. "Cardboard v1").  A device's [vendor, model] pair is
-  // expected to be globally unique.
-  optional string model = 2;
-
-  // Distance from the display screen to the optical center of lenses.
-  // This is a required field for distortion rendering, and must be positive.
-  optional float screen_to_lens_distance = 3;
-
-  // Horizontal distance between optical center of the lenses.
-  // This is a required field for distortion rendering, and must be positive.
-  optional float inter_lens_distance = 4;
-
-  // Four-element tuple (left, right, bottom, top) of left eye's view extent
-  // angles relative to center, assuming the following:
-  //     * eye is aligned with optical center of lens
-  //     * display screen is equal or larger than extents viewable through lens
-  //     * nominal eye-to-lens distance
-  //     * mirrored field of view will be applied to the right eye
-  // These values are essentially used as an optimization to avoid rendering
-  // pixels which can't be seen.
-  // This is a required field for distortion rendering, and angles must be
-  // positive.
-  repeated float left_eye_field_of_view_angles = 5 [packed = true];
-
-  enum VerticalAlignmentType {
-    BOTTOM = 0;  // phone rests against a fixed bottom tray
-    CENTER = 1;  // phone screen assumed to be centered w.r.t. lenses
-    TOP = 2;     // phone rests against a fixed top tray
-  }
-
-  // Set according to vertical alignment strategy-- see enum comments above.
-  // NOTE: If you set this to CENTER, see special instructions for the
-  // tray_to_lens_distance field below.
-  optional VerticalAlignmentType vertical_alignment = 11 [default = BOTTOM];
-
-  // If the phone is aligned vertically within the device by resting against
-  // a fixed top or bottom tray, this is the distance from the tray to
-  // optical center of the lenses.
-  // This is a required field for distortion rendering, and must be positive.
-  // NOTE: Due to a bug in initial versions of the SDK's, this field
-  // must be set explicitly to .035 when vertical_alignment = CENTER.
-  optional float tray_to_lens_distance = 6;
-
-  // Coefficients Ki for pincushion distortion function which maps
-  // from position on real screen to virtual screen (i.e. texture) relative
-  // to optical center:
-  //
-  //    p' = p (1 + K1 r^2 + K2 r^4 + ... + Kn r^(2n))
-  //
-  // where r is the distance in tan-angle units from the optical center,
-  // p the input point, and p' the output point.  Tan-angle units can be
-  // computed as distance on the screen divided by distance from the
-  // virtual eye to the screen.
-  repeated float distortion_coefficients = 7 [packed = true];
-  // Slots 8, 9 reserved for per-color channel distortion.
-
-  // Optionally, whether the head mount uses a magnet in any part of its
-  // design.  Intended as hint as to whether phone's magnetometer is
-  // available for tasks such as orientation tracking.
-  optional bool has_magnet = 10;
-
-  enum ButtonType {
-    // No physical button, and touch screen is not easily accessible.
-    NONE = 0;
-    // HMD has integrated magnet switch similar to original Cardboard.
-    MAGNET = 1;
-    // At least a portion of touch screen is easily accessible to user for taps.
-    TOUCH = 2;
-    // Touch screen is triggered indirectly via integrated button on the HMD.
-    INDIRECT_TOUCH = 3;
-  }
-
-  // Specify primary input mechanism of the HMD.  Intended for advisory
-  // purposes only, to address simple questions such as "can HMD
-  // be used with apps requiring a physical button event?" or "what icon
-  // should be used to represent button action to the user?".
-  optional ButtonType primary_button = 12 [default = MAGNET];
-
-  // Some internal data for Cardboard.  This data is not intended to be
-  // set or used by developers, and any data in this proto is not guaranteed
-  // to be supported with new SDK updates.
-  optional CardboardInternalParams internal = 1729;
-
-  // Optionally, specifies the additional parameters that are necessary for
-  // a Daydream-ready headset. This field is non-null if the headset is
-  // Daydream-ready.
-  // TODO(b/30112366) The inclusion of this message inside a DeviceParams is a
-  // somewhat ugly result of some historical choices in the SDK. We should
-  // consider refactoring our code to allow us to remove this, and the
-  // CardboardInternalParams messages from this proto.
-  optional DaydreamInternalParams daydream_internal = 196883;
-}
-
-// TODO(b/27108179): CardboardInternalParams should be migrated into its own
-// file, and not live in this file.
-
-/**
- * Message describing parameters that are used internally by Cardboard
- * and VRToolkit. These parameters don't necessarily fit into the DeviceParams
- * notion of a VR viewer combined with user's phone (e.g. case of viewer with
- * dedicated display, etc.) and are not intended to be used by developers
- * and may or may not be supported or changed without notice on new releases
- * of the Cardboard SDK or VR Toolkit.
- */
-message CardboardInternalParams {
-  // Used to specify a per-eye post-process transformation -- an optional
-  // rotation and x-axis reflection -- to be applied after distortion
-  // correction.
-  enum OrientationType {
-    CCW_0_DEGREES = 0;
-    CCW_90_DEGREES = 1;
-    CCW_180_DEGREES = 2;
-    CCW_270_DEGREES = 3;
-    CCW_0_DEGREES_MIRRORED = 4;
-    CCW_90_DEGREES_MIRRORED = 5;
-    CCW_180_DEGREES_MIRRORED = 6;
-    CCW_270_DEGREES_MIRRORED = 7;
-  }
-
-  // Specify a post-process transformation that is applied after the distortion
-  // function. This field is optional, if not specified, CCW_0_DEGREES is
-  // assumed. If repeated, the first orientation is for the left eye, the second
-  // is for the right eye.
-  //
-  // For example, if [CCW_90_DEGREES, CCW_270_DEGREES_MIRRORED] is specified,
-  //
-  // this input:
-  //
-  // ***************** *****************
-  // *1             2* *1             2*
-  // *      *        * *      ***      *
-  // *      *        * *      * *      *
-  // *      ****     * *      *  *     *
-  // *4             3* *4             3*
-  // ***************** *****************
-  //
-  // is rendered on the screen like this:
-  //
-  // ***************** *****************
-  // *2       *     3* *3     *       2*
-  // *        *      * *       **      *
-  // *        *      * *        *      *
-  // *      ***      * *      ***      *
-  // *1             4* *4             1*
-  // ***************** *****************
-  repeated OrientationType eye_orientations = 1 [packed = true];
-
-  // Specify a horizontal offset from the middle of the screen to the center of
-  // the lens, in meters. If one is not provided, half of the inter lens
-  // distance is used.
-  //
-  // This is only necessary if the HMD has some sort of periscope effect, where
-  // the position of the lenses, relative to the screen, is different than
-  // their position relative to the user.
-  //
-  // For example, in the HMD below, two mirrors reflect the image from the
-  // screen to the user, creating a larger inter lens distance than the screen
-  // can support.
-  //
-  // [In the diagram below, S = screen, L = lens]
-  //
-  // screen_center_to_lens_distance
-  //             |--|
-  //
-  // -------------------------
-  // |     SSSSSSSSSSSS      |
-  // |        |  |  |        |
-  // |   /----/  |  \----\   |
-  // |   |       |       |   |
-  // |  LLL             LLL  |
-  //
-  //     |---------------|
-  //    inter_lens_distance
-  //
-  optional float screen_center_to_lens_distance = 2;
-
-  // Optional x-dimension physical pixels per inch of the external display,
-  // assuming landscape orientation. If set, this will override OS-reported
-  // values.
-  optional float x_ppi_override = 3;
-
-  // Optional y-dimension physical pixels per inch of the external display,
-  // assuming landscape orientation.  If set, this will override OS-reported
-  // values.
-  optional float y_ppi_override = 4;
-
-  // Optional string identifying the device's accelerometer and gyroscope.
-  // If either field is filled out, the corresponding sensor (gyroscope or
-  // accelerometer) will be used for head tracking.
-  //
-  // Valid strings are usually found in:
-  // vendor/<vendorname>/<devicename>/xxx/sensors.cpp
-  //
-  // For dynamic sensors, this string will be provided in a separate way.
-  //
-  // NB: Vendors and manufacturers should make the name of the sensor as
-  // specific as possible, since if multiple sensors with the same name are
-  // connected, the first will be used.
-  optional string accelerometer = 5;
-  optional string gyroscope = 6;
-}
-
-/**
- * Message describing the additional properties of a Daydream-ready headset that
- * are not used for a normal cardboard viewer. These parameters are not intended
- * to be used, or consumed, by developers and may or may not be supported or
- * changed without notice on new releases of the Cardboard SDK or VR Toolkit.
- */
-message DaydreamInternalParams {
-  // The version of the Daydream-ready specification to which this device
-  // conforms.
-  optional int32 version = 1;
-
-  // Optionally, specifies the collection of screen alignment markers in the
-  // headset.
-  repeated ScreenAlignmentMarker alignment_markers = 2;
-}
-
-/**
- * Message describing a single screen alignment marker.
- *
- * A screen alignment marker is a capacitive touch point affixed to the headset
- * which is capable of making contact with the screen. The location of the touch
- * point is given in meters, measured along a horizontal axis which passes
- * through the center of both lenses, and a vertical axis which is equidistant
- * from the centers of the lenses. A positive vertical value indicates that the
- * point lies above the horizontal axis, and a positive horizontal value
- * indicates that the point lies to the right, as seen by a user of the headset,
- * of the vertical axis. For example, if the following is a representation of a
- * headset, viewed from the point of view of a user, with three points marked by
- * the numbers 1, 2, and 3.
- *
- * *****************************************************************************
- * *                                    ^                                      *
- * *               _____                |                _____                 *
- * *              /     \               1               /     \                *
- * *             /       \              |              /       \               *
- * *            /         \             |             /         \              *
- * *           /           \            |            /           \             *
- * *          /             \           |           /             \            *
- * *---------|-------*-------|----------+------2---|-------*-------|---------->*
- * *          \             /           |           \             /            *
- * *           \           /            |            \           /             *
- * *            \         /         3   |             \         /              *
- * *             \       /              |              \       /               *
- * *              \_____/               |               \_____/                *
- * *                                    |                                      *
- * *                                    |                                      *
- * *****************************************************************************
- *
- * Then the coordinates of point 1 could be horizontal = 0.0, vertical = 0.035;
- * point 2 could be horizontal = 0.02; and point 3 could be horizontal = -0.01
- * vertical = -0.012
- */
-message ScreenAlignmentMarker {
-  // The horizontal coordinate of the touch point.
-  optional float horizontal = 1;
-
-  // The vertical coordinate of the touch point.
-  optional float vertical = 2;
-}
diff --git a/libs/vr/libgvr/dummy_gvr_ext.cpp b/libs/vr/libgvr/dummy_gvr_ext.cpp
deleted file mode 100644
index f73838d..0000000
--- a/libs/vr/libgvr/dummy_gvr_ext.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <log/log.h>
-#include <vr/gvr/capi/include/gvr.h>
-#include <vr/gvr/capi/include/gvr_ext.h>
-#include <vr/gvr/capi/include/gvr_types.h>
-
-gvr_frame_schedule* gvr_frame_schedule_create() { return NULL; }
-
-void gvr_frame_schedule_destroy(gvr_frame_schedule** /* schedule */) {}
-
-uint32_t gvr_frame_schedule_get_vsync_count(
-    gvr_frame_schedule* /* schedule */) {
-  return 0;
-}
-
-gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr,
-                                                uint32_t /* vsync_count */) {
-  LOG_ALWAYS_FATAL("gvr_get_6dof_head_pose_in_start_space is not implemented. "
-                   "Use gvr_get_head_space_from_start_space_pose instead.");
-  return gvr_mat4f({{{1.0f, 0.0f, 0.0f, 0.0f},
-                     {0.0f, 1.0f, 0.0f, 0.0f},
-                     {0.0f, 0.0f, 1.0f, 0.0f},
-                     {0.0f, 0.0f, 0.0f, 1.0f}}});
-}
-
-void gvr_wait_next_frame(gvr_swap_chain* /* swap_chain */,
-                         int64_t /* sched_offset_nanos */,
-                         gvr_frame_schedule* /* out_next_frame_schedule */) {
-  LOG_ALWAYS_FATAL("gvr_wait_next_frame is not implemented.");
-}
diff --git a/libs/vr/libgvr/exported_apis.lds b/libs/vr/libgvr/exported_apis.lds
deleted file mode 100644
index 2d19303..0000000
--- a/libs/vr/libgvr/exported_apis.lds
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  global:
-    # Export GVR APIs, both public and private.
-    gvr_*;
-
-    # Whitelist of DVR APIs required by VrCore for Ambrosia controller support.
-    dvrPoseCreate;
-    dvrPoseDestroy;
-    dvrPoseGet;
-    dvrPoseGetController;
-    dvrPoseGetVsyncCount;
-
-  local:
-    # Hide everything else.
-    *;
-};
diff --git a/libs/vr/libgvr/include/private/dvr/internal_types.h b/libs/vr/libgvr/include/private/dvr/internal_types.h
deleted file mode 100644
index dafdb73..0000000
--- a/libs/vr/libgvr/include/private/dvr/internal_types.h
+++ /dev/null
@@ -1,170 +0,0 @@
-#ifndef ANDROID_DVR_INTERNAL_TYPES_H_
-#define ANDROID_DVR_INTERNAL_TYPES_H_
-
-#include <GLES2/gl2.h>
-#include <atomic>
-#include <memory>
-#include <vector>
-#include <unordered_map>
-
-#include <dvr/graphics.h>
-#include <dvr/pose_client.h>
-#include <gui/Surface.h>
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/display_client.h>
-#include <vr/gvr/capi/include/gvr.h>
-#include <vr/gvr/capi/include/gvr_types.h>
-#include <vr/gvr/capi/src/gvr_types_experimental.h>
-
-typedef struct gvr_user_prefs_ {
-} gvr_user_prefs;
-
-typedef struct gvr_context_ {
-  int32_t last_error_;
-  JNIEnv* jni_env_;
-  DvrPose* pose_client_;
-  std::unique_ptr<android::dvr::DisplayClient> display_client_;
-  android::dvr::SystemDisplayMetrics display_metrics_;
-  gvr_mat4f left_eye_viewport_transform_;
-  gvr_mat4f right_eye_viewport_transform_;
-  gvr_mat4f next_frame_6dof_pose_;
-  gvr_mat4f next_frame_controller_pose_[2];
-  gvr_user_prefs user_prefs_;
-  bool force_6dof_;
-  std::vector<gvr_swap_chain*> swap_chains_;
-
-  gvr_context_() :
-      last_error_(GVR_ERROR_NONE),
-      jni_env_(nullptr),
-      pose_client_(nullptr),
-      force_6dof_(false) {}
-
-  ~gvr_context_();
-} gvr_context;
-
-typedef struct gvr_buffer_spec_ {
-  gvr_sizei size;
-  int32_t msaa_samples;
-  int32_t color_format;
-  int32_t depth_stencil_format;
-  bool blur_behind;
-  bool initially_visible;
-  int z_order;
-
-  // The default values are configured to match SVR defaults
-  gvr_buffer_spec_()
-      : size{0, 0},
-        msaa_samples(0),
-        color_format(GVR_COLOR_FORMAT_RGBA_8888),
-        depth_stencil_format(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16),
-        blur_behind(true),
-        initially_visible(true),
-        z_order(0) {}
-} gvr_buffer_spec;
-
-// This isn't a public gvr type
-struct gvr_buffer {
-  gvr_buffer_spec spec;
-  GLuint frame_buffer;
-  GLuint color_render_buffer;
-  GLuint depth_stencil_render_buffer;
-
-  // requested_size is used for resizing. It will be {-1, -1} when no resize is
-  // requested. Any other value indicates the app changed the size.
-  gvr_sizei requested_size;
-
-  gvr_buffer();
-  // If creation fails frame_buffer will be 0
-  gvr_buffer(gvr_context* gvr, const gvr_buffer_spec& spec,
-             GLuint texture_id, GLenum texture_target);
-  ~gvr_buffer();
-
-  gvr_buffer(gvr_buffer&& other);
-  gvr_buffer& operator=(gvr_buffer&& other);
-  gvr_buffer(const gvr_buffer& other) = delete;
-  gvr_buffer& operator=(const gvr_buffer& other) = delete;
-
-  // Set default values. Doesn't free GL resources first.
-  void SetDefaults();
-
-  // Frees all GL resources associated with the buffer
-  void FreeGl();
-};
-
-typedef struct gvr_swap_chain_ {
-  gvr_context* context;
-  DvrGraphicsContext* graphics_context_;
-  std::vector<gvr_buffer> buffers_;
-  bool frame_acquired_;
-  bool wait_next_frame_called_by_app_;
-  std::atomic<int32_t> next_external_surface_id_;
-  std::unordered_map<int32_t, gvr_external_surface*> external_surfaces_;
-
-  explicit gvr_swap_chain_(gvr_context* context)
-      : context(context),
-        graphics_context_(nullptr),
-        frame_acquired_(false),
-        wait_next_frame_called_by_app_(false),
-        next_external_surface_id_(0) {}
-  ~gvr_swap_chain_();
-} gvr_swap_chain;
-
-typedef struct gvr_buffer_viewport_ {
-  int32_t buffer_index;
-  gvr_rectf uv;
-  gvr_mat4f transform;
-  int32_t eye;
-  int32_t external_surface_id;
-  gvr_reprojection reprojection;
-
-  gvr_buffer_viewport_()
-      : buffer_index(0),
-        uv{0, 0, 0, 0},
-        transform{{{1.f, 0.f, 0.f, 0.f},
-                   {0.f, 1.f, 0.f, 0.f},
-                   {0.f, 0.f, 1.f, 0.f},
-                   {0.f, 0.f, 0.f, 1.f}}},
-        eye(0),
-        external_surface_id(-1),
-        reprojection(GVR_REPROJECTION_FULL) {}
-
-  gvr_buffer_viewport_(int32_t /* buffer_index */, gvr_rectf uv,
-                       const gvr_mat4f& transform, int32_t eye,
-                       int32_t external_surface_id,
-                       gvr_reprojection reprojection)
-      : buffer_index(0),
-        uv(uv),
-        transform(transform),
-        eye(eye),
-        external_surface_id(external_surface_id),
-        reprojection(reprojection) {}
-
-  bool operator==(const gvr_buffer_viewport_& other) const;
-
-  bool operator!=(const gvr_buffer_viewport_& other) const {
-    return !operator==(other);
-  }
-} gvr_buffer_viewport;
-
-typedef struct gvr_buffer_viewport_list_ {
-  std::vector<gvr_buffer_viewport> viewports;
-} gvr_buffer_viewport_list;
-
-typedef struct gvr_frame_schedule_ {
-  uint32_t vsync_count;
-  gvr_clock_time_point scheduled_finish;
-
-  gvr_frame_schedule_() : vsync_count(0) {
-    scheduled_finish.monotonic_system_time_nanos = 0;
-  }
-} gvr_frame_schedule;
-
-typedef struct gvr_display_synchronizer_ {} gvr_display_synchronizer;
-
-typedef struct gvr_external_surface_ {
-  int32_t id;
-  gvr_swap_chain* swap_chain;
-  DvrVideoMeshSurface* video_surface;
-} gvr_external_surface;
-
-#endif  // ANDROID_DVR_INTERNAL_TYPES_H_
diff --git a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h b/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h
deleted file mode 100644
index 8af434f..0000000
--- a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_ext.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright 2016 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_EXT_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_EXT_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/// Constants that represent GVR error codes.
-typedef enum {
-  // TODO(steventhomas): All errors should be switched to something more
-  // meaningful and this should eventually go away.
-  GVR_ERROR_INTERNAL = 9000,
-} gvr_error_ext;
-
-typedef struct gvr_frame_schedule_ gvr_frame_schedule;
-
-gvr_frame_schedule* gvr_frame_schedule_create();
-
-void gvr_frame_schedule_destroy(gvr_frame_schedule** schedule);
-
-uint32_t gvr_frame_schedule_get_vsync_count(gvr_frame_schedule* schedule);
-
-gvr_clock_time_point gvr_frame_schedule_get_scheduled_finish(
-    gvr_frame_schedule* schedule);
-
-/// Sleep until it's time to render the next frame.
-// |start_delay_ns| adjusts how long this function blocks the app from starting
-// its next frame. If |start_delay_ns| is 0, the function waits until the
-// scheduled frame finish time for the current frame, which gives the app one
-// full vsync period to render the next frame. If the app needs less than a full
-// vysnc period to render the frame, pass in a non-zero |start_delay_ns| to
-// delay the start of frame rendering further. For example, if the vsync period
-// is 11.1ms and the app takes 6ms to render a frame, consider setting this to
-// 5ms (note that the value is in nanoseconds, so 5,000,000ns) so that the app
-// finishes the frame closer to the scheduled frame finish time. Delaying the
-// start of rendering allows the app to use a more up-to-date pose for
-// rendering.
-// |start_delay_ns| must be a positive value or 0. If you're unsure what to set
-// for |start_delay_ns|, use 0.
-/// |out_next_frame_schedule| is an output parameter that will contain the
-/// schedule for the next frame. It can be null.
-void gvr_wait_next_frame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos,
-                         gvr_frame_schedule* out_next_frame_schedule);
-
-gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr,
-                                                uint32_t vsync_count);
-
-gvr_mat4f gvr_get_head_space_from_start_space_pose(
-    gvr_context* gvr, const gvr_clock_time_point time);
-
-gvr_mat4f gvr_get_start_space_from_controller_space_pose(
-    gvr_context* gvr, int controller_id, const gvr_clock_time_point time);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-#include <utility>
-
-namespace gvr {
-
-/// Convenience C++ wrapper for gvr_frame_schedule. Frees the underlying
-/// gvr_frame_schedule on destruction.
-class FrameSchedule {
- public:
-  FrameSchedule() { schedule_ = gvr_frame_schedule_create(); }
-
-  ~FrameSchedule() {
-    if (schedule_)
-      gvr_frame_schedule_destroy(&schedule_);
-  }
-
-  FrameSchedule(FrameSchedule&& other) {
-    std::swap(schedule_, other.schedule_);
-  }
-
-  FrameSchedule& operator=(FrameSchedule&& other) {
-    std::swap(schedule_, other.schedule_);
-    return *this;
-  }
-
-  gvr_frame_schedule* cobj() { return schedule_; }
-  const gvr_frame_schedule* cobj() const { return schedule_; }
-
-  uint32_t GetVsyncCount() const {
-    return gvr_frame_schedule_get_vsync_count(schedule_);
-  }
-
-  gvr_clock_time_point GetScheduledFinish() const {
-    return gvr_frame_schedule_get_scheduled_finish(schedule_);
-  }
-
- private:
-  gvr_frame_schedule* schedule_;
-};
-
-}  // namespace gvr
-#endif  // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_EXT_H_
diff --git a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h b/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h
deleted file mode 100644
index 1fae611..0000000
--- a/libs/vr/libgvr/include/vr/gvr/capi/include/gvr_util.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_
-
-#include <private/dvr/eigen.h>
-#include <private/dvr/numeric.h>
-#include <private/dvr/types.h>
-#include <vr/gvr/capi/include/gvr_types.h>
-
-namespace android {
-namespace dvr {
-
-inline gvr_rectf FovRadiansToDegrees(const gvr_rectf& fov) {
-  return gvr_rectf{ToDeg(fov.left), ToDeg(fov.right), ToDeg(fov.bottom),
-                   ToDeg(fov.top)};
-}
-
-inline gvr_rectf FovDegreesToRadians(const gvr_rectf& fov) {
-  return gvr_rectf{ToRad(fov.left), ToRad(fov.right), ToRad(fov.bottom),
-                   ToRad(fov.top)};
-}
-
-inline FieldOfView GvrToDvrFov(const gvr_rectf& fov) {
-  gvr_rectf fov_rad = FovDegreesToRadians(fov);
-  return FieldOfView(fov_rad.left, fov_rad.right, fov_rad.bottom, fov_rad.top);
-}
-
-inline gvr_rectf DvrToGvrFov(const FieldOfView& fov) {
-  return FovRadiansToDegrees(
-      gvr_rectf{fov.GetLeft(), fov.GetRight(), fov.GetBottom(), fov.GetTop()});
-}
-
-inline gvr_mat4f GvrIdentityMatrix() {
-  gvr_mat4f identity;
-  memset(&identity.m, 0, sizeof(identity.m));
-  for (int i = 0; i < 4; i++)
-    identity.m[i][i] = 1;
-  return identity;
-}
-
-inline gvr_mat4f GvrTranslationMatrix(float x, float y, float z) {
-  gvr_mat4f trans = GvrIdentityMatrix();
-  trans.m[0][3] = x;
-  trans.m[1][3] = y;
-  trans.m[2][3] = z;
-  return trans;
-}
-
-inline gvr_mat4f EigenToGvrMatrix(const mat4& m) {
-  gvr_mat4f ret;
-  for (int i = 0; i < 4; ++i)
-    for (int j = 0; j < 4; ++j)
-      ret.m[i][j] = m(i, j);
-  return ret;
-}
-
-inline mat4 GvrToEigenMatrix(const gvr::Mat4f& m) {
-  mat4 ret;
-  for (int i = 0; i < 4; ++i)
-    for (int j = 0; j < 4; ++j)
-      ret(i, j) = m.m[i][j];
-  return ret;
-}
-
-inline quat GvrToEigenRotation(const gvr_mat4f& m) {
-  mat3 ret;
-  for (int r = 0; r < 3; ++r)
-    for (int c = 0; c < 3; ++c)
-      ret(r, c) = m.m[r][c];
-  return quat(ret.matrix());
-}
-
-inline vec3 GvrToEigenTranslation(const gvr_mat4f& m) {
-  return vec3(m.m[0][3], m.m[1][3], m.m[2][3]);
-}
-
-// Converts a DVR pose to 6DOF head transform as a GVR matrix.
-inline gvr_mat4f PosefToGvrMatrix(const Posef& pose) {
-  return EigenToGvrMatrix(pose.GetObjectFromReferenceMatrix());
-}
-
-// Converts a DVR pose to 3DOF head transform as a GVR matrix by stripping out
-// position translation.
-inline gvr_mat4f PosefTo3DofGvrMatrix(const Posef& pose) {
-  gvr_mat4f ret = PosefToGvrMatrix(pose);
-  ret.m[0][3] = 0;
-  ret.m[1][3] = 0;
-  ret.m[2][3] = 0;
-  return ret;
-}
-
-// Converts a GVR matrix to a DVR pose.
-inline Posef GvrMatrixToPosef(const gvr_mat4f& m) {
-  return Posef(GvrToEigenRotation(m), GvrToEigenTranslation(m)).Inverse();
-}
-
-// Calculates an transform with only the yaw and position components of |pose|.
-// The inverse of this matrix cancels yaw and position without affecting roll or
-// pitch.
-inline mat4 CalculateRecenterTransform(const mat4& pose) {
-  const vec4 z_axis = pose * vec4::UnitZ();
-  const float yaw = std::atan2(z_axis[0], z_axis[2]);
-  const vec3 position = pose.translation();
-  return mat4(Eigen::AngleAxis<float>(yaw, vec3::UnitY())).translate(position);
-}
-
-// Calculates a transform that negates the position component of |pose| and
-// offsets the pose by |position|. The inverse of this matrix cancels the
-// position component of pose and translates by |position| without affecting
-// orientation.
-inline mat4 CalculateOffsetTransform(const mat4& pose, const vec3& position) {
-  // Transform the origin by the pose matrix to produce the offset that cancels
-  // only the position of the pose.
-  //          -1          T
-  // [ R | t ]  [ 0 ] = -R * t
-  // [ 0   1 ]  [ 1 ]
-  const vec3 position_offset = (pose.inverse() * vec4(0, 0, 0, 1)).head<3>();
-  return mat4(mat4::Identity()).translate(position - position_offset);
-}
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_UTIL_H_
diff --git a/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java b/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java
deleted file mode 100644
index 381175c..0000000
--- a/libs/vr/libgvr/java/com/google/vr/gvr/platform/Loader.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.google.vr.gvr.platform;
-
-import android.os.SystemProperties;
-
-/**
- * Auxiliary class to load the system implementation of the GVR API.
- * @hide
- */
-public class Loader {
-
-    private static final String VR_MODE_BOOT = "ro.boot.vr";
-
-    /**
-     * Opens a shared library containing the system implementation for the GVR API and returns the
-     * handle to it.
-     *
-     * @return A Long object describing the handle returned by dlopen.
-     */
-    public static Long loadLibrary() {
-        // Note: caller verifications cannot be safely done here. Any app can find and use this API.
-        // Any sensitive functions must have appropriate checks on the service side.
-
-        // Load a thin JNI library that runs dlopen on request.
-        System.loadLibrary("gvr_system_loader");
-
-        // Performs dlopen on the library and returns the handle.
-        return nativeLoadLibrary("libgvr_system.so");
-    }
-
-    /**
-     * Returns true if this device boots directly in VR mode.
-     */
-    public static boolean getVrBoot() {
-        return SystemProperties.getBoolean(VR_MODE_BOOT, false);
-    }
-
-    private static native long nativeLoadLibrary(String library);
-}
diff --git a/libs/vr/libgvr/library_loader.cpp b/libs/vr/libgvr/library_loader.cpp
deleted file mode 100644
index 3cdc7d6..0000000
--- a/libs/vr/libgvr/library_loader.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <dlfcn.h>
-#include <jni.h>
-
-#include <string>
-
-extern "C" {
-
-JNIEXPORT jlong JNICALL
-Java_com_google_vr_gvr_platform_Loader_nativeLoadLibrary(
-    JNIEnv* env, jclass, jstring java_library) {
-  if (!java_library)
-    return 0;
-
-  // Convert the Java String object to a C++ null-terminated string.
-  const char* data = env->GetStringUTFChars(java_library, NULL);
-  size_t size = env->GetStringUTFLength(java_library);
-  std::string library(data, size);
-  env->ReleaseStringUTFChars(java_library, data);
-
-  // Return the handle to the requested library.
-  return reinterpret_cast<jlong>(
-      dlopen(library.c_str(), RTLD_NOW | RTLD_LOCAL));
-}
-
-}  // extern "C"
diff --git a/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh b/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh
deleted file mode 100755
index 8e6ca2d..0000000
--- a/libs/vr/libgvr/prebuilt/build_gvr_prebuilts.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/bash
-# Build and copy libgvr from Google3. Make sure that your local Google3 client
-# is up-to-date by running `p4 sync` before executing this script.
-#
-# Usage:
-# build_gvr_prebuilts.sh --google3_dir=<path_google3_client_root>
-
-source gbash.sh || exit
-
-DEFINE_string --required "google3_dir" "" \
-  "Path to the root directory of Google3 client"
-
-BLAZE_COMMON_OPTS=(
-  --compilation_mode=opt
-  --copt=-fdata-sections
-  --copt=-ffunction-sections
-  --define='prod=1'
-  --define='enable_experimental_sdk=1'
-  --linkopt=-Wl,--gc-sections
-)
-
-function copy_file() {
-  cp -v "${1}" ${CURRENT_DIR}/"${2}"
-}
-
-function copy_gvr_headers() {
-  echo "Copy GVR headers ..."
-
-  GVR_HEADER_DIR="include/vr/gvr/capi/include"
-  GVR_SOURCE_DIR="include/vr/gvr/capi/src"
-
-  # GVR public headers
-  copy_file "vr/gvr/capi/include/gvr.h" ${GVR_HEADER_DIR}
-  copy_file "vr/gvr/capi/include/gvr_audio.h" ${GVR_HEADER_DIR}
-  copy_file "vr/gvr/capi/include/gvr_controller.h" ${GVR_HEADER_DIR}
-  copy_file "vr/gvr/capi/include/gvr_types.h" ${GVR_HEADER_DIR}
-
-  # GVR private and experimental headers
-  copy_file "vr/gvr/capi/src/gvr_experimental.h" ${GVR_SOURCE_DIR}
-  copy_file "vr/gvr/capi/src/gvr_private.h" ${GVR_SOURCE_DIR}
-  copy_file "vr/gvr/capi/src/gvr_types_experimental.h" ${GVR_SOURCE_DIR}
-}
-
-function build_gvr_libs() {
-  echo "Build GVR libraries ..."
-
-  blaze build \
-    //java/com/google/vr/sdk/release:common_library.aar \
-    //vr/gvr/platform:libgvr.so \
-    //vr/gvr/platform:libgvr_audio.so \
-    ${BLAZE_COMMON_OPTS[@]} --config=android_arm --symlink_prefix blaze-arm-
-
-  blaze build \
-    //vr/gvr/platform:libgvr.so \
-    //vr/gvr/platform:libgvr_audio.so \
-    ${BLAZE_COMMON_OPTS[@]} --config=android_arm64 --symlink_prefix blaze-arm64-
-
-    blaze build \
-    //java/com/google/vr/sdk/release:common_library.aar \
-    //vr/gvr/platform:libgvr.so \
-    //vr/gvr/platform:libgvr_audio.so \
-    ${BLAZE_COMMON_OPTS[@]} --config=android_x86 --symlink_prefix blaze-x86-
-
-  blaze build \
-    //vr/gvr/platform:libgvr.so \
-    //vr/gvr/platform:libgvr_audio.so \
-    ${BLAZE_COMMON_OPTS[@]} --config=android_x86_64 --symlink_prefix blaze-x86_64-
-
-  copy_file "blaze-arm-genfiles/java/com/google/vr/sdk/release/common_library.aar" \
-    "lib/common_library.aar"
-  copy_file "blaze-arm-genfiles/vr/gvr/platform/libgvr.so" "lib/android_arm"
-  copy_file "blaze-arm-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_arm"
-  copy_file "blaze-arm64-genfiles/vr/gvr/platform/libgvr.so" "lib/android_arm64"
-  copy_file "blaze-arm64-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_arm64"
-  copy_file "blaze-x86-genfiles/vr/gvr/platform/libgvr.so" "lib/android_x86"
-  copy_file "blaze-x86-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_x86"
-  copy_file "blaze-x86_64-genfiles/vr/gvr/platform/libgvr.so" "lib/android_x86_64"
-  copy_file "blaze-x86_64-genfiles/vr/gvr/platform/libgvr_audio.so" "lib/android_x86_64"
-}
-
-function main() {
-  set -ex
-
-  CURRENT_DIR=$(pwd)
-  GOOGLE3_DIR=${FLAGS_google3_dir}
-
-  cd ${GOOGLE3_DIR}
-  copy_gvr_headers
-  build_gvr_libs
-}
-
-gbash::init_google "$@"
-main "$@"
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h
deleted file mode 100644
index c459eca..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr.h
+++ /dev/null
@@ -1,1751 +0,0 @@
-/* Copyright 2016 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_H_
-
-#ifdef __ANDROID__
-#include <jni.h>
-#endif
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-#include <array>
-#include <memory>
-#include <vector>
-#endif
-
-#include "vr/gvr/capi/include/gvr_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/// @defgroup base Google VR Base C API
-/// @brief This is the Google VR C API. It supports clients writing VR
-/// experiences for head mounted displays that consist of a mobile phone and a
-/// VR viewer.
-///
-/// Example API usage:
-///
-///     #ifdef __ANDROID__
-///     // On Android, the gvr_context should almost always be obtained from
-///     // the Java GvrLayout object via
-///     // GvrLayout.getGvrApi().getNativeGvrContext().
-///     gvr_context* gvr = ...;
-///     #else
-///     gvr_context* gvr = gvr_create();
-///     #endif
-///
-///     gvr_initialize_gl(gvr);
-///
-///     gvr_buffer_viewport_list* viewport_list =
-///         gvr_buffer_viewport_list_create(gvr);
-///     gvr_get_recommended_buffer_viewports(gvr, viewport_list);
-///     gvr_buffer_viewport* left_eye_vp = gvr_buffer_viewport_create(gvr);
-///     gvr_buffer_viewport* right_eye_vp = gvr_buffer_viewport_create(gvr);
-///     gvr_buffer_viewport_list_get_item(viewport_list, 0, left_eye_vp);
-///     gvr_buffer_viewport_list_get_item(viewport_list, 1, right_eye_vp);
-///
-///     while (client_app_should_render) {
-///       // A client app should be ready for the render target size to change
-///       // whenever a new QR code is scanned, or a new viewer is paired.
-///       gvr_sizei render_target_size =
-///           gvr_get_maximum_effective_render_target_size(gvr);
-///       // The maximum effective render target size can be very large, most
-///       // applications need to scale down to compensate.
-///       render_target_size.width /= 2;
-///       render_target_size.height /= 2;
-///       gvr_swap_chain_resize_buffer(swap_chain, 0, render_target_size);
-///
-///       // This function will depend on your render loop's implementation.
-///       gvr_clock_time_point next_vsync = AppGetNextVsyncTime();
-///
-///       const gvr_mat4f head_view =
-///           gvr_get_head_space_from_start_space_rotation(gvr, next_vsync);
-///       const gvr_mat4f left_eye_view = MatrixMultiply(
-///           gvr_get_eye_from_head_matrix(gvr, GVR_LEFT_EYE), head_view);
-///       const gvr::Mat4f right_eye_view = MatrixMultiply(
-///           gvr_get_eye_from_head_matrix(gvr, GVR_RIGHT_EYE), head_view);
-///
-///       // Insert client rendering code here.
-///
-///       AppSetRenderTarget(offscreen_texture_id);
-///
-///       AppDoSomeRenderingForEye(
-///           gvr_buffer_viewport_get_source_uv(left_eye_view),
-///           left_eye_matrix);
-///       AppDoSomeRenderingForEye(
-///           gvr_buffer_viewport_get_source_uv(right_eye_view),
-///           right_eye_matrix);
-///       AppSetRenderTarget(primary_display);
-///
-///       gvr_frame_submit(&frame, viewport_list, head_matrix);
-///     }
-///
-///     // Cleanup memory.
-///     gvr_buffer_viewport_list_destroy(&viewport_list);
-///     gvr_buffer_viewport_destroy(&left_eye_vp);
-///     gvr_buffer_viewport_destroy(&right_eye_vp);
-///
-///     #ifdef __ANDROID__
-///     // On Android, The Java GvrLayout owns the gvr_context.
-///     #else
-///     gvr_destroy(gvr);
-///     #endif
-///
-/// Head tracking is enabled by default, and will begin as soon as the
-/// gvr_context is created. The client should call gvr_pause_tracking() and
-/// gvr_resume_tracking() when the app is paused and resumed, respectively.
-///
-/// Note: Unless otherwise noted, the functions in this API may not be
-/// thread-safe with respect to the gvr_context, and it is up the caller to use
-/// the API in a thread-safe manner.
-///
-/// @{
-
-/// Creates a new gvr instance.
-///
-/// The instance must remain valid as long as any GVR object is in use. When
-/// the application no longer needs to use the GVR SDK, call gvr_destroy().
-///
-///
-/// On Android, the gvr_context should *almost always* be obtained from the Java
-/// GvrLayout object, rather than explicitly created here. The GvrLayout should
-/// live in the app's View hierarchy, and its use is required to ensure
-/// consistent behavior across all varieties of GVR-compatible viewers. See
-/// the Java GvrLayout and GvrApi documentation for more details.
-///
-#ifdef __ANDROID__
-/// @param env The JNIEnv associated with the current thread.
-/// @param app_context The Android application context. This must be the
-///     application context, NOT an Activity context (Note: from any Android
-///     Activity in your app, you can call getApplicationContext() to
-///     retrieve the application context).
-/// @param class_loader The class loader to use when loading Java classes.
-///     This must be your app's main class loader (usually accessible through
-///     activity.getClassLoader() on any of your Activities).
-///
-/// @return Pointer to the created gvr instance, NULL on failure.
-gvr_context* gvr_create(JNIEnv* env, jobject app_context, jobject class_loader);
-#else
-/// @return Pointer to the created gvr instance, NULL on failure.
-gvr_context* gvr_create();
-#endif  // #ifdef __ANDROID__
-
-/// Gets the current GVR runtime version.
-///
-/// Note: This runtime version may differ from the version against which the
-/// client app is compiled, as defined by the semantic version components in
-/// gvr_version.h.
-///
-/// @return The version as a gvr_version.
-gvr_version gvr_get_version();
-
-/// Gets a string representation of the current GVR runtime version. This is of
-/// the form "MAJOR.MINOR.PATCH".
-///
-/// Note: This runtime version may differ from the version against which the
-/// client app is compiled, as defined in gvr_version.h by
-/// GVR_SDK_VERSION_STRING.
-///
-/// @return The version as a static char pointer.
-const char* gvr_get_version_string();
-
-/// Gets the current GVR error code, or GVR_ERROR_NONE if there is no error.
-/// This function doesn't clear the error code; see gvr_clear_error().
-///
-/// @param gvr Pointer to the gvr instance.
-/// @return The current gvr_error code, or GVR_ERROR_NONE if no error has
-///    occurred.
-int32_t gvr_get_error(gvr_context* gvr);
-
-/// Clears the current GVR error code, and returns the error code that was
-/// cleared.
-///
-/// @param gvr Pointer to the gvr instance.
-/// @return The gvr_error code that was cleared by this function, or
-/// GVR_ERROR_NONE if no error has occurred.
-int32_t gvr_clear_error(gvr_context* gvr);
-
-/// Gets a human-readable string representing the given error code.
-///
-/// @param error_code The gvr_error code.
-/// @return A human-readable string representing the error code.
-const char* gvr_get_error_string(int32_t error_code);
-
-/// Returns an opaque struct containing information about user preferences.
-///
-/// The returned struct will remain valid as long as the context is valid.
-/// The returned struct may be updated when the user changes their preferences,
-/// so this function only needs to be called once, and calling it multiple
-/// times will return the same object each time.
-///
-/// @param gvr Pointer to the gvr instance.
-/// @return An opaque struct containing information about user preferences.
-const gvr_user_prefs* gvr_get_user_prefs(gvr_context* gvr);
-
-/// Returns the controller handedness of the given gvr_user_prefs struct.
-///
-/// @param user_prefs Pointer to the gvr_user_prefs object returned by
-///     gvr_get_user_prefs.
-/// @return Either GVR_CONTROLLER_RIGHT_HANDED or GVR_CONTROLLER_LEFT_HANDED
-///     depending on which hand the user holds the controller in.
-int32_t gvr_user_prefs_get_controller_handedness(
-    const gvr_user_prefs* user_prefs);
-
-/// Destroys a gvr_context instance.  The parameter will be nulled by this
-/// operation.  Once this function is called, the behavior of any subsequent
-/// call to a GVR SDK function that references objects created from this
-/// context is undefined.
-///
-/// @param gvr Pointer to a pointer to the gvr instance to be destroyed and
-///     nulled.
-void gvr_destroy(gvr_context** gvr);
-
-/// Initializes necessary GL-related objects and uses the current thread and
-/// GL context for rendering. Please make sure that a valid GL context is
-/// available when this function is called.  This should never be called more
-/// than once on the same GL context (doing so would cause resource leaks).
-///
-/// @param gvr Pointer to the gvr instance to be initialized.
-void gvr_initialize_gl(gvr_context* gvr);
-
-/// Gets whether asynchronous reprojection is currently enabled.
-///
-/// If enabled, frames will be collected by the rendering system and
-/// asynchronously re-projected in sync with the scanout of the display. This
-/// feature may not be available on every platform, and requires a
-/// high-priority render thread with special extensions to function properly.
-///
-/// Note: On Android, this feature can be enabled solely via the GvrLayout Java
-/// instance which (indirectly) owns this gvr_context. The corresponding
-/// method call is GvrLayout.setAsyncReprojectionEnabled().
-///
-/// Note: Because of the above requirements, asynchronous reprojection is only
-/// currently available on Daydream-ready Android devices.  This function will
-/// always return false on other devices.
-///
-/// @param gvr Pointer to the gvr instance.
-/// @return Whether async reprojection is enabled. Defaults to false.
-bool gvr_get_async_reprojection_enabled(const gvr_context* gvr);
-
-/// Gets the recommended buffer viewport configuration, populating a previously
-/// allocated gvr_buffer_viewport_list object. The updated values include the
-/// per-eye recommended viewport and field of view for the target.
-///
-/// When the recommended viewports are used for distortion rendering, this
-/// method should always be called after calling refresh_viewer_profile(). That
-/// will ensure that the populated viewports reflect the currently paired
-/// viewer.
-///
-/// @param gvr Pointer to the gvr instance from which to get the viewports.
-/// @param viewport_list Pointer to a previously allocated viewport list. This
-///     will be populated with the recommended buffer viewports and resized if
-///     necessary.
-void gvr_get_recommended_buffer_viewports(
-    const gvr_context* gvr, gvr_buffer_viewport_list* viewport_list);
-
-/// Gets the screen (non-distorted) buffer viewport configuration, populating a
-/// previously allocated gvr_buffer_viewport_list object. The updated values
-/// include the per-eye recommended viewport and field of view for the target.
-///
-/// @param gvr Pointer to the gvr instance from which to get the viewports.
-/// @param viewport_list Pointer to a previously allocated viewport list. This
-///     will be populated with the screen buffer viewports and resized if
-///     necessary.
-void gvr_get_screen_buffer_viewports(const gvr_context* gvr,
-                                     gvr_buffer_viewport_list* viewport_list);
-
-/// Returns the maximum effective size for the client's render target, given the
-/// parameters of the head mounted device selected. At this resolution, we have
-/// a 1:1 ratio between source pixels and screen pixels in the most magnified
-/// region of the screen. Applications should rarely, if ever, need to render
-/// to a larger target, as it will simply result in sampling artifacts.
-///
-/// Note that this is probably too large for most applications to use as a
-/// render target size. Applications should scale this value to be appropriate
-/// to their graphical load.
-///
-/// @param gvr Pointer to the gvr instance from which to get the size.
-///
-/// @return Maximum effective size for the target render target.
-gvr_sizei gvr_get_maximum_effective_render_target_size(const gvr_context* gvr);
-
-/// Returns a non-distorted size for the screen, given the parameters
-/// of the phone and/or the head mounted device selected.
-///
-/// @param gvr Pointer to the gvr instance from which to get the size.
-///
-/// @return Screen (non-distorted) size for the render target.
-gvr_sizei gvr_get_screen_target_size(const gvr_context* gvr);
-
-// Sets the size of the underlying render surface.
-//
-// By default, it is assumed that the display size matches the surface
-// size. If that is the case for the client app, this method need never be
-// called. However, in certain cases (e.g., hardware scaling), this will not
-// always hold, in which case the distortion pass must be informed of the
-// custom surface size.
-//
-// Note that the caller is responsible for resizing any BufferSpec objects
-// created before this function is called. Otherwise there will be rendering
-// artifacts, such as edges appearing pixelated. This function will change the
-// result of get_maximum_effective_render_target_size(), so that function can be
-// used to compute the appropriate size for buffers.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param surface_size_pixels The size in pixels of the display surface. If
-//     non-empty, this will be used in conjunction with the current display to
-//     perform properly scaled distortion. If empty, it is assumed that the
-//     rendering surface dimensions match that of the active display.
-void gvr_set_surface_size(gvr_context* gvr, gvr_sizei surface_size_pixels);
-
-/// Performs postprocessing, including lens distortion, on the contents of the
-/// passed texture and shows the result on the screen. Lens distortion is
-/// determined by the parameters of the viewer encoded in its QR code. The
-/// passed texture is not modified.
-///
-/// If the application does not call gvr_initialize_gl() before calling this
-/// function, the results are undefined.
-///
-/// @deprecated This function exists only to support legacy rendering pathways
-///     for Cardboard devices. It is incompatible with the low-latency
-///     experiences supported by async reprojection. Use the swap chain API
-///     instead.
-///
-/// @param gvr Pointer to the gvr instance which will do the distortion.
-/// @param texture_id The OpenGL ID of the texture that contains the next frame
-///     to be displayed.
-/// @param viewport_list Rendering parameters.
-/// @param head_space_from_start_space This parameter is ignored.
-/// @param target_presentation_time This parameter is ignored.
-void gvr_distort_to_screen(gvr_context* gvr, int32_t texture_id,
-                           const gvr_buffer_viewport_list* viewport_list,
-                           gvr_mat4f head_space_from_start_space,
-                           gvr_clock_time_point target_presentation_time);
-
-/// Queries whether a particular GVR feature is supported by the underlying
-/// platform.
-///
-/// @param gvr The context to query against.
-/// @param feature The gvr_feature type being queried.
-/// @return true if feature is supported, false otherwise.
-bool gvr_is_feature_supported(const gvr_context* gvr, int32_t feature);
-
-/// @}
-
-/////////////////////////////////////////////////////////////////////////////
-// Viewports and viewport lists
-/////////////////////////////////////////////////////////////////////////////
-/// @defgroup viewport Viewports and viewport lists
-/// @brief Objects to define the mapping between the application's rendering
-///     output and the user's field of view.
-/// @{
-
-/// Creates a gvr_buffer_viewport instance.
-gvr_buffer_viewport* gvr_buffer_viewport_create(gvr_context* gvr);
-
-/// Frees a gvr_buffer_viewport instance and clears the pointer.
-void gvr_buffer_viewport_destroy(gvr_buffer_viewport** viewport);
-
-/// Gets the UV coordinates specifying where the output buffer is sampled.
-///
-/// @param viewport The buffer viewport.
-/// @return UV coordinates as a rectangle.
-gvr_rectf gvr_buffer_viewport_get_source_uv(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the UV coordinates specifying where the output buffer should be
-/// sampled when compositing the final distorted image.
-///
-/// @param viewport The buffer viewport.
-/// @param uv The new UV coordinates for sampling. The coordinates must be
-///     valid, that is, left <= right and bottom <= top. Otherwise an empty
-///     source region is set, which will result in no output for this viewport.
-void gvr_buffer_viewport_set_source_uv(gvr_buffer_viewport* viewport,
-                                       gvr_rectf uv);
-
-/// Retrieves the field of view for the referenced buffer region.
-///
-/// This is a helper that converts the stored projection matrix to a field of
-/// view. Note that if the previously set projection matrix cannot be expressed
-/// as a view frustum aligned with the eye's optical axis, the result will be
-/// incorrect.
-///
-/// @param viewport The buffer viewport.
-/// @return The field of view of the rendered image, in degrees.
-gvr_rectf gvr_buffer_viewport_get_source_fov(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the field of view for the viewport contents.
-///
-/// This is a helper that sets the projection matrix in such a way that the
-/// viewport's contents fill the specified FOV around the eye's optical axis.
-///
-/// @param viewport The buffer viewport.
-/// @param fov The field of view to use when compositing the rendered image,
-///     in degrees.
-void gvr_buffer_viewport_set_source_fov(gvr_buffer_viewport* viewport,
-                                        gvr_rectf fov);
-
-/// Gets the matrix that positions the viewport in eye space.
-///
-/// @param viewport The buffer viewport.
-/// @return Matrix that transforms a quad with vertices (-1, -1, 0), (1, -1, 0),
-///     (-1, 1, 0), (1, 1, 0) representing the viewport contents to its desired
-///     eye space position for the target eye.
-gvr_mat4f gvr_buffer_viewport_get_transform(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the matrix that positions the viewport in eye space.
-///
-/// @param viewport The buffer viewport.
-/// @param transform Matrix that transforms a quad with vertices (-1, -1, 0),
-///     (1, -1, 0), (-1, 1, 0), (1, 1, 0) representing the viewport contents to
-///     its desired eye space position for the target eye.
-void gvr_buffer_viewport_set_transform(gvr_buffer_viewport* viewport,
-                                       gvr_mat4f transform);
-
-/// Gets the target logical eye for the specified viewport.
-///
-/// @param viewport The buffer viewport.
-/// @return Index of the target logical eye for this viewport.
-int32_t gvr_buffer_viewport_get_target_eye(const gvr_buffer_viewport* viewport);
-
-/// Sets the target logical eye for the specified viewport.
-///
-/// @param viewport The buffer viewport.
-/// @param index Index of the target logical eye.
-void gvr_buffer_viewport_set_target_eye(gvr_buffer_viewport* viewport,
-                                        int32_t index);
-
-/// Gets the index of the source buffer from which the viewport reads its
-/// undistorted pixels.
-///
-/// @param viewport The buffer viewport.
-/// @return Index of the source buffer. This corresponds to the index in the
-///     list of buffer specs that was passed to gvr_swap_chain_create().
-int32_t gvr_buffer_viewport_get_source_buffer_index(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the buffer from which the viewport reads its undistorted pixels.
-///
-/// To use the contents of the external surface as buffer contents, associate an
-/// external surface with the viewport by calling
-/// gvr_buffer_viewport_set_external_surface_id(), then call this function and
-/// pass GVR_BUFFER_INDEX_EXTERNAL_SURFACE.
-///
-/// @param viewport The buffer viewport.
-/// @param buffer_index The index of the source buffer. This is either an index
-///     in the list of buffer specs that was passed to
-///     gvr_swap_chain_create(), or GVR_BUFFER_INDEX_EXTERNAL_SURFACE.
-void gvr_buffer_viewport_set_source_buffer_index(
-    gvr_buffer_viewport* viewport, int32_t buffer_index);
-
-/// Gets the ID of the externally-managed Surface texture from which this
-/// viewport reads undistored pixels.
-///
-/// @param viewport The buffer viewport.
-/// @return ID of the externally-managed Surface of undistorted pixels.
-int32_t gvr_buffer_viewport_get_external_surface_id(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the ID of the externally-managed Surface texture from which this
-/// viewport reads. The ID is issued by GvrLayout.
-///
-/// @param viewport The buffer viewport.
-/// @param external_surface_id The ID of the surface to read from.
-void gvr_buffer_viewport_set_external_surface_id(
-    gvr_buffer_viewport* viewport, int32_t external_surface_id);
-
-/// Gets the type of reprojection to perform on the specified viewport.
-///
-/// @param viewport The buffer viewport.
-/// @return Type of reprojection that is applied to the viewport.
-int32_t gvr_buffer_viewport_get_reprojection(
-    const gvr_buffer_viewport* viewport);
-
-/// Sets the type of reprojection to perform on the specified viewport.
-/// Viewports that display world content should use full reprojection.
-/// Viewports that display head-locked UI should disable reprojection to avoid
-/// excessive judder. The default is to perform full reprojection.
-///
-/// @param viewport The buffer viewport.
-/// @param reprojection Type of reprojection that will be applied to the passed
-///     viewport.
-void gvr_buffer_viewport_set_reprojection(gvr_buffer_viewport* viewport,
-                                          int32_t reprojection);
-
-/// Compares two gvr_buffer_viewport instances and returns true if they specify
-/// the same view mapping.
-///
-/// @param a Instance of a buffer viewport.
-/// @param b Another instance of a buffer viewport.
-/// @return True if the passed viewports are the same.
-bool gvr_buffer_viewport_equal(const gvr_buffer_viewport* a,
-                               const gvr_buffer_viewport* b);
-
-/// Creates a new, empty list of viewports. The viewport list defines how the
-/// application's rendering output should be transformed into the stabilized,
-/// lens-distorted image that is sent to the screen.
-///
-/// The caller should populate the returned viewport using one of:
-///   - gvr_get_recommended_buffer_viewports()
-///   - gvr_get_screen_buffer_viewports()
-///   - gvr_buffer_viewport_list_set_item()
-///
-/// @param gvr Pointer the gvr instance from which to allocate the viewport
-/// list.
-/// @return Pointer to an allocated gvr_buffer_viewport_list object. The caller
-//      is responsible for calling gvr_buffer_viewport_list_destroy() on the
-///     returned object when it is no longer needed.
-gvr_buffer_viewport_list* gvr_buffer_viewport_list_create(
-    const gvr_context* gvr);
-
-/// Destroys a gvr_buffer_viewport_list instance. The parameter will be nulled
-/// by this operation.
-///
-/// @param viewport_list Pointer to a pointer to the viewport list instance to
-///     be destroyed and nulled.
-void gvr_buffer_viewport_list_destroy(gvr_buffer_viewport_list** viewport_list);
-
-/// Returns the size of the given viewport list.
-///
-/// @param viewport_list Pointer to a viewport list.
-/// @return The number of entries in the viewport list.
-size_t gvr_buffer_viewport_list_get_size(
-    const gvr_buffer_viewport_list* viewport_list);
-
-/// Retrieve a buffer viewport entry from a list.
-///
-/// @param viewport_list Pointer to the previously allocated viewport list.
-/// @param index Zero-based index of the viewport entry to query. Must be
-///    smaller than the list size.
-/// @param viewport The buffer viewport structure that will be populated with
-///    retrieved data.
-void gvr_buffer_viewport_list_get_item(
-    const gvr_buffer_viewport_list* viewport_list, size_t index,
-    gvr_buffer_viewport* viewport);
-
-/// Update an element of the viewport list or append a new one at the end.
-///
-/// @param viewport_list Pointer to a previously allocated viewport list.
-/// @param index Index of the buffer viewport entry to update. If the
-///     `viewport_list` size is equal to the index, a new viewport entry will be
-///     added. The `viewport_list` size must *not* be less than the index value.
-/// @param viewport A pointer to the buffer viewport object.
-void gvr_buffer_viewport_list_set_item(gvr_buffer_viewport_list* viewport_list,
-                                       size_t index,
-                                       const gvr_buffer_viewport* viewport);
-
-/// @}
-
-/////////////////////////////////////////////////////////////////////////////
-// Swapchains and frames
-/////////////////////////////////////////////////////////////////////////////
-/// @defgroup swap_chain Swap chains and frames
-/// @brief Functions to create a swap chain, manipulate it and submit frames
-///     for lens distortion and presentation on the screen.
-/// @{
-
-/// Creates a default buffer specification.
-gvr_buffer_spec* gvr_buffer_spec_create(gvr_context* gvr);
-
-/// Destroy the buffer specification and null the pointer.
-void gvr_buffer_spec_destroy(gvr_buffer_spec** spec);
-
-/// Gets the size of the buffer to be created.
-///
-/// @param spec Buffer specification.
-/// @return Size of the pixel buffer. The default is equal to the recommended
-///     render target size at the time when the specification was created.
-gvr_sizei gvr_buffer_spec_get_size(const gvr_buffer_spec* spec);
-
-/// Sets the size of the buffer to be created.
-///
-/// @param spec Buffer specification.
-/// @param size The size. Width and height must both be greater than zero.
-///     Otherwise, the application is aborted.
-void gvr_buffer_spec_set_size(gvr_buffer_spec* spec, gvr_sizei size);
-
-/// Gets the number of samples per pixel in the buffer to be created.
-///
-/// @param spec Buffer specification.
-/// @return Value >= 1 giving the number of samples. 1 means multisampling is
-///     disabled. Negative values and 0 are never returned.
-int32_t gvr_buffer_spec_get_samples(const gvr_buffer_spec* spec);
-
-/// Sets the number of samples per pixel in the buffer to be created.
-///
-/// @param spec Buffer specification.
-/// @param num_samples The number of samples. Negative values are an error.
-///     The values 0 and 1 are treated identically and indicate that
-//      multisampling should be disabled.
-void gvr_buffer_spec_set_samples(gvr_buffer_spec* spec, int32_t num_samples);
-
-/// Sets the color format for the buffer to be created. Default format is
-/// GVR_COLOR_FORMAT_RGBA_8888.
-///
-/// @param spec Buffer specification.
-/// @param color_format The color format for the buffer. Valid formats are in
-///     the gvr_color_format_type enum.
-void gvr_buffer_spec_set_color_format(gvr_buffer_spec* spec,
-                                      int32_t color_format);
-
-/// Sets the depth and stencil format for the buffer to be created. Currently,
-/// only packed stencil formats are supported. Default format is
-/// GVR_DEPTH_STENCIL_FORMAT_DEPTH_16.
-///
-/// @param spec Buffer specification.
-/// @param depth_stencil_format The depth and stencil format for the buffer.
-///     Valid formats are in the gvr_depth_stencil_format_type enum.
-void gvr_buffer_spec_set_depth_stencil_format(gvr_buffer_spec* spec,
-                                              int32_t depth_stencil_format);
-
-/// Creates a swap chain from the given buffer specifications.
-/// This is a potentially time-consuming operation. All frames within the
-/// swapchain will be allocated. Once rendering is stopped, call
-/// gvr_swap_chain_destroy() to free GPU resources. The passed gvr_context must
-/// not be destroyed until then.
-///
-/// Swap chains can have no buffers. This is useful when only displaying
-/// external surfaces. When `count` is zero, `buffers` must be null.
-///
-/// @param gvr GVR instance for which a swap chain will be created.
-/// @param buffers Array of pixel buffer specifications. Each frame in the
-///     swap chain will be composed of these buffers.
-/// @param count Number of buffer specifications in the array.
-/// @return Opaque handle to the newly created swap chain.
-gvr_swap_chain* gvr_swap_chain_create(gvr_context* gvr,
-                                      const gvr_buffer_spec** buffers,
-                                      int32_t count);
-
-/// Destroys the swap chain and nulls the pointer.
-void gvr_swap_chain_destroy(gvr_swap_chain** swap_chain);
-
-/// Gets the number of buffers in each frame of the swap chain.
-int32_t gvr_swap_chain_get_buffer_count(const gvr_swap_chain* swap_chain);
-
-/// Retrieves the size of the specified pixel buffer. Note that if the buffer
-/// was resized while the current frame was acquired, the return value will be
-/// different than the value obtained from the equivalent function for the
-/// current frame.
-///
-/// @param swap_chain The swap chain.
-/// @param index Index of the pixel buffer.
-/// @return Size of the specified pixel buffer in frames that will be returned
-///     from gvr_swap_chain_acquire_frame().
-gvr_sizei gvr_swap_chain_get_buffer_size(gvr_swap_chain* swap_chain,
-                                         int32_t index);
-
-/// Resizes the specified pixel buffer to the given size. The frames are resized
-/// when they are unused, so the currently acquired frame will not be resized
-/// immediately.
-///
-/// @param swap_chain The swap chain.
-/// @param index Index of the pixel buffer to resize.
-/// @param size New size for the specified pixel buffer.
-void gvr_swap_chain_resize_buffer(gvr_swap_chain* swap_chain, int32_t index,
-                                  gvr_sizei size);
-
-/// Acquires a frame from the swap chain for rendering. Buffers that are part of
-/// the frame can then be bound with gvr_frame_bind_buffer(). Once the frame
-/// is finished and all its constituent buffers are ready, call
-/// gvr_frame_submit() to display it while applying lens distortion.
-///
-/// @param swap_chain The swap chain.
-/// @return Handle to the acquired frame. NULL if the swap chain is invalid,
-///     or if acquire has already been called on this swap chain.
-gvr_frame* gvr_swap_chain_acquire_frame(gvr_swap_chain* swap_chain);
-
-/// Binds a pixel buffer that is part of the frame to the OpenGL framebuffer.
-///
-/// @param frame Frame handle acquired from the swap chain.
-/// @param index Index of the pixel buffer to bind. This corresponds to the
-///     index in the buffer spec list that was passed to
-///     gvr_swap_chain_create().
-void gvr_frame_bind_buffer(gvr_frame* frame, int32_t index);
-
-/// Unbinds any buffers bound from this frame and binds the default OpenGL
-/// framebuffer.
-void gvr_frame_unbind(gvr_frame* frame);
-
-/// Returns the dimensions of the pixel buffer with the specified index. Note
-/// that a frame that was acquired before resizing a swap chain buffer will not
-/// be resized until it is submitted to the swap chain.
-///
-/// @param frame Frame handle.
-/// @param index Index of the pixel buffer to inspect.
-/// @return Dimensions of the specified pixel buffer.
-gvr_sizei gvr_frame_get_buffer_size(const gvr_frame* frame, int32_t index);
-
-/// Gets the name (ID) of the framebuffer object associated with the specified
-/// buffer. The OpenGL state is not modified.
-///
-/// @param frame Frame handle.
-/// @param index Index of a pixel buffer.
-/// @return OpenGL object name (ID) of a framebuffer object which can be used
-///     to render into the buffer. The ID is valid only until the frame is
-///     submitted.
-int32_t gvr_frame_get_framebuffer_object(const gvr_frame* frame, int32_t index);
-
-/// Submits the frame for distortion and display on the screen. The passed
-/// pointer is nulled to prevent reuse.
-///
-/// @param frame The frame to submit.
-/// @param list Buffer view configuration to be used for this frame.
-/// @param head_space_from_start_space Transform from start space (space with
-///     head at the origin at last tracking reset) to head space (space with
-///     head at the origin and axes aligned to the view vector).
-void gvr_frame_submit(gvr_frame** frame, const gvr_buffer_viewport_list* list,
-                      gvr_mat4f head_space_from_start_space);
-
-/// Resets the OpenGL framebuffer binding to what it was at the time the
-/// passed gvr_context was created.
-void gvr_bind_default_framebuffer(gvr_context* gvr);
-
-/// @}
-
-/////////////////////////////////////////////////////////////////////////////
-// Head tracking
-/////////////////////////////////////////////////////////////////////////////
-/// @defgroup Headtracking Head tracking
-/// @brief Functions for managing head tracking.
-/// @{
-
-/// Gets the current monotonic system time.
-///
-/// @return The current monotonic system time.
-gvr_clock_time_point gvr_get_time_point_now();
-
-/// Gets the rotation from start space to head space.  The head space is a
-/// space where the head is at the origin and faces the -Z direction.
-///
-/// @param gvr Pointer to the gvr instance from which to get the pose.
-/// @param time The time at which to get the head pose. The time should be in
-///     the future. If the time is not in the future, it will be clamped to now.
-/// @return A matrix representation of the rotation from start space (the space
-///     where the head was last reset) to head space (the space with the head
-///     at the origin, and the axes aligned to the view vector).
-gvr_mat4f gvr_get_head_space_from_start_space_rotation(
-    const gvr_context* gvr, const gvr_clock_time_point time);
-
-/// Applies a simple neck model translation based on the rotation of the
-/// provided head pose.
-///
-/// Note: Neck model application may not be appropriate for all tracking
-/// scenarios, e.g., when tracking is non-biological.
-///
-/// @param gvr Pointer to the context instance from which the pose was obtained.
-/// @param head_space_from_start_space_rotation The head rotation as returned by
-///     gvr_get_head_space_from_start_space_rotation().
-/// @param factor A scaling factor for the neck model offset, clamped from 0 to
-///     1. This should be 1 for most scenarios, while 0 will effectively disable
-///     neck model application. This value can be animated to smoothly
-///     interpolate between alternative (client-defined) neck models.
-/// @return The new head pose with the neck model applied.
-gvr_mat4f gvr_apply_neck_model(const gvr_context* gvr,
-                               gvr_mat4f head_space_from_start_space_rotation,
-                               float factor);
-
-/// Pauses head tracking, disables all sensors (to save power).
-///
-/// @param gvr Pointer to the gvr instance for which tracking will be paused and
-///     sensors disabled.
-void gvr_pause_tracking(gvr_context* gvr);
-
-/// Resumes head tracking, re-enables all sensors.
-///
-/// @param gvr Pointer to the gvr instance for which tracking will be resumed.
-void gvr_resume_tracking(gvr_context* gvr);
-
-/// Resets head tracking.
-///
-/// This API call is deprecated. Use gvr_recenter_tracking instead, which
-/// accomplishes the same effects but avoids the undesirable side-effects of
-/// a full reset (temporary loss of tracking quality).
-///
-/// Only to be used by Cardboard apps. Daydream apps must not call this. On the
-/// Daydream platform, recentering is handled automatically and should never
-/// be triggered programatically by applications. Hybrid apps that support both
-/// Cardboard and Daydream must only call this function when in Cardboard mode
-/// (that is, when the phone is paired with a Cardboard viewer), never in
-/// Daydream mode.
-///
-/// @param gvr Pointer to the gvr instance for which tracking will be reseted.
-/// @deprecated Calls to this method can be safely replaced by calls to
-//    gvr_recenter_tracking.
-void gvr_reset_tracking(gvr_context* gvr);
-
-/// Recenters the head orientation (resets the yaw to zero, leaving pitch and
-/// roll unmodified).
-///
-/// Only to be used by Cardboard apps. Daydream apps must not call this. On the
-/// Daydream platform, recentering is handled automatically and should never
-/// be triggered programatically by applications. Hybrid apps that support both
-/// Cardboard and Daydream must only call this function when in Cardboard mode
-/// (that is, when the phone is paired with a Cardboard viewer), never in
-/// Daydream mode.
-///
-/// @param gvr Pointer to the gvr instance for which tracking will be
-///     recentered.
-void gvr_recenter_tracking(gvr_context* gvr);
-
-/// @}
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Head mounted display.
-/////////////////////////////////////////////////////////////////////////////
-/// @defgroup HMD Head Mounted Display
-/// @brief Functions for managing viewer information.
-/// @{
-
-/// Sets the default viewer profile specified by viewer_profile_uri.
-/// The viewer_profile_uri that is passed in will be ignored if a valid
-/// viewer profile has already been stored on the device that the app
-/// is running on.
-///
-/// Note: This function has the potential of blocking for up to 30 seconds for
-/// each redirect if a shortened URI is passed in as argument. It will try to
-/// unroll the shortened URI for a maximum number of 5 times if the redirect
-/// continues. In that case, it is recommended to create a separate thread to
-/// call this function so that other tasks like rendering will not be blocked
-/// on this. The blocking can be avoided if a standard URI is passed in.
-///
-/// @param gvr Pointer to the gvr instance which to set the profile on.
-/// @param viewer_profile_uri A string that contains either the shortened URI or
-///     the standard URI representing the viewer profile that the app should be
-///     using. If the valid viewer profile can be found on the device, the URI
-///     that is passed in will be ignored and nothing will happen. Otherwise,
-///     gvr will look for the viewer profile specified by viewer_profile_uri,
-///     and it will be stored if found. Also, the values will be applied to gvr.
-///     A valid standard URI can be generated from this page:
-///     https://www.google.com/get/cardboard/viewerprofilegenerator/
-/// @return True if the viewer profile specified by viewer_profile_uri was
-///     successfully stored and applied, false otherwise.
-bool gvr_set_default_viewer_profile(gvr_context* gvr,
-                                    const char* viewer_profile_uri);
-
-/// Refreshes gvr_context with the viewer profile that is stored on the device.
-/// If it can not find the viewer profile, nothing will happen.
-///
-/// @param gvr Pointer to the gvr instance to refresh the profile on.
-void gvr_refresh_viewer_profile(gvr_context* gvr);
-
-/// Gets the name of the viewer vendor.
-///
-/// @param gvr Pointer to the gvr instance from which to get the vendor.
-/// @return A pointer to the vendor name. May be NULL if no viewer is paired.
-///     WARNING: This method guarantees the validity of the returned pointer
-///     only until the next use of the `gvr` context. The string should be
-///     copied immediately if persistence is required.
-const char* gvr_get_viewer_vendor(const gvr_context* gvr);
-
-/// Gets the name of the viewer model.
-///
-/// @param gvr Pointer to the gvr instance from which to get the name.
-/// @return A pointer to the model name. May be NULL if no viewer is paired.
-///     WARNING: This method guarantees the validity of the returned pointer
-///     only until the next use of the `gvr` context. The string should be
-///     copied immediately if persistence is required.
-const char* gvr_get_viewer_model(const gvr_context* gvr);
-
-/// Gets the type of the viewer, as defined by gvr_viewer_type.
-///
-/// @param gvr Pointer to the gvr instance from which to get the viewer type.
-/// @return The gvr_viewer_type of the currently paired viewer.
-int32_t gvr_get_viewer_type(const gvr_context* gvr);
-
-/// Gets the transformation matrix to convert from Head Space to Eye Space for
-/// the given eye.
-///
-/// @param gvr Pointer to the gvr instance from which to get the matrix.
-/// @param eye Selected gvr_eye type.
-/// @return Transformation matrix from Head Space to selected Eye Space.
-gvr_mat4f gvr_get_eye_from_head_matrix(const gvr_context* gvr,
-                                       const int32_t eye);
-
-/// Gets the window bounds.
-///
-/// @param gvr Pointer to the gvr instance from which to get the bounds.
-///
-/// @return Window bounds in physical pixels.
-gvr_recti gvr_get_window_bounds(const gvr_context* gvr);
-
-/// Computes the distorted point for a given point in a given eye.  The
-/// distortion inverts the optical distortion caused by the lens for the eye.
-/// Due to chromatic aberration, the distortion is different for each
-/// color channel.
-///
-/// @param gvr Pointer to the gvr instance which will do the computing.
-/// @param eye The gvr_eye type (left or right).
-/// @param uv_in A point in screen eye Viewport Space in [0,1]^2 with (0, 0)
-///     in the lower left corner of the eye's viewport and (1, 1) in the
-///     upper right corner of the eye's viewport.
-/// @param uv_out A pointer to an array of (at least) 3 elements, with each
-///     element being a Point2f representing a point in render texture eye
-///     Viewport Space in [0,1]^2 with (0, 0) in the lower left corner of the
-///     eye's viewport and (1, 1) in the upper right corner of the eye's
-///     viewport.
-///     `uv_out[0]` is the corrected position of `uv_in` for the red channel
-///     `uv_out[1]` is the corrected position of `uv_in` for the green channel
-///     `uv_out[2]` is the corrected position of `uv_in` for the blue channel
-void gvr_compute_distorted_point(const gvr_context* gvr, const int32_t eye,
-                                 const gvr_vec2f uv_in, gvr_vec2f uv_out[3]);
-
-/// @}
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-namespace gvr {
-
-/// Convenience C++ wrapper for gvr_user_prefs.
-class UserPrefs {
- public:
-  /// Creates a C++ wrapper for a gvr_user_prefs object. Note that unlike most
-  /// of the C++ wrappers in the API, this does not take ownership, as the
-  /// gvr_user_prefs will remain valid for the lifetime of the GVR context.
-  explicit UserPrefs(const gvr_user_prefs* user_prefs)
-      : user_prefs_(user_prefs) {}
-
-  UserPrefs(UserPrefs&& other) : user_prefs_(nullptr) {
-    std::swap(user_prefs_, other.user_prefs_);
-  }
-
-  UserPrefs& operator=(UserPrefs&& other) {
-    std::swap(user_prefs_, other.user_prefs_);
-    return *this;
-  }
-
-  /// For more information, see gvr_user_prefs_get_controller_handedness().
-  ControllerHandedness GetControllerHandedness() const {
-    return static_cast<ControllerHandedness>(
-        gvr_user_prefs_get_controller_handedness(user_prefs_));
-  }
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  const gvr_user_prefs* cobj() const { return user_prefs_; }
-
- private:
-  const gvr_user_prefs* user_prefs_;
-
-  // Disallow copy and assign.
-  UserPrefs(const UserPrefs&);
-  void operator=(const UserPrefs&);
-};
-
-/// Convenience C++ wrapper for the opaque gvr_buffer_viewport type.
-/// The constructor allocates memory, so when used in tight loops, instances
-/// should be reused.
-class BufferViewport {
- public:
-  BufferViewport(BufferViewport&& other)
-      : viewport_(nullptr) {
-    std::swap(viewport_, other.viewport_);
-  }
-
-  BufferViewport& operator=(BufferViewport&& other) {
-    std::swap(viewport_, other.viewport_);
-    return *this;
-  }
-
-  ~BufferViewport() {
-    if (viewport_) gvr_buffer_viewport_destroy(&viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_source_fov().
-  Rectf GetSourceFov() const {
-    return gvr_buffer_viewport_get_source_fov(viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_source_fov().
-  void SetSourceFov(const Rectf& fov) {
-    gvr_buffer_viewport_set_source_fov(viewport_, fov);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_transform().
-  Mat4f GetTransform() const {
-    return gvr_buffer_viewport_get_transform(viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_transform().
-  void SetTransform(const Mat4f& transform) {
-    gvr_buffer_viewport_set_transform(viewport_, transform);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_source_uv().
-  Rectf GetSourceUv() const {
-    return gvr_buffer_viewport_get_source_uv(viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_source_uv().
-  void SetSourceUv(const Rectf& uv) {
-    gvr_buffer_viewport_set_source_uv(viewport_, uv);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_target_eye().
-  Eye GetTargetEye() const {
-    return static_cast<Eye>(gvr_buffer_viewport_get_target_eye(viewport_));
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_target_eye().
-  void SetTargetEye(Eye eye) {
-    gvr_buffer_viewport_set_target_eye(viewport_, eye);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_source_buffer_index().
-  int32_t GetSourceBufferIndex() const {
-    return gvr_buffer_viewport_get_source_buffer_index(viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_source_buffer_index().
-  void SetSourceBufferIndex(int32_t buffer_index) {
-    gvr_buffer_viewport_set_source_buffer_index(viewport_, buffer_index);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_external_surface_id().
-  int32_t GetExternalSurfaceId() const {
-    return gvr_buffer_viewport_get_external_surface_id(viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_set_external_surface_id().
-  void SetExternalSurfaceId(const int32_t external_surface_id) {
-    gvr_buffer_viewport_set_external_surface_id(viewport_, external_surface_id);
-  }
-
-  /// For more information, see gvr_buffer_viewport_get_reprojection().
-  gvr_reprojection GetReprojection() const {
-    return static_cast<gvr_reprojection>(
-        gvr_buffer_viewport_get_reprojection(viewport_));
-  }
-  /// For more information, see gvr_buffer_viewport_set_reprojection().
-  void SetReprojection(gvr_reprojection reprojection) {
-    gvr_buffer_viewport_set_reprojection(viewport_, reprojection);
-  }
-
-  /// For more information, see gvr_buffer_viewport_equal().
-  bool operator==(const BufferViewport& other) const {
-    return gvr_buffer_viewport_equal(viewport_, other.viewport_) ? true : false;
-  }
-  bool operator!=(const BufferViewport& other) const {
-    return !(*this == other);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit BufferViewport(gvr_buffer_viewport* viewport)
-      : viewport_(viewport) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_buffer_viewport* cobj() { return viewport_; }
-  const gvr_buffer_viewport* cobj() const { return viewport_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_buffer_viewport* release() {
-    auto result = viewport_;
-    viewport_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  friend class GvrApi;
-  friend class BufferViewportList;
-
-  explicit BufferViewport(gvr_context* gvr)
-      : viewport_(gvr_buffer_viewport_create(gvr)) {}
-
-  gvr_buffer_viewport* viewport_;
-};
-
-/// Convenience C++ wrapper for the opaque gvr_buffer_viewport_list type. This
-/// class will automatically release the wrapped gvr_buffer_viewport_list upon
-/// destruction. It can only be created via a `GvrApi` instance, and its
-/// validity is tied to the lifetime of that instance.
-class BufferViewportList {
- public:
-  BufferViewportList(BufferViewportList&& other)
-      : context_(nullptr), viewport_list_(nullptr) {
-    std::swap(context_, other.context_);
-    std::swap(viewport_list_, other.viewport_list_);
-  }
-
-  BufferViewportList& operator=(BufferViewportList&& other) {
-    std::swap(context_, other.context_);
-    std::swap(viewport_list_, other.viewport_list_);
-    return *this;
-  }
-
-  ~BufferViewportList() {
-    if (viewport_list_) {
-      gvr_buffer_viewport_list_destroy(&viewport_list_);
-    }
-  }
-
-  /// For more information, see gvr_get_recommended_buffer_viewports().
-  void SetToRecommendedBufferViewports() {
-    gvr_get_recommended_buffer_viewports(context_, viewport_list_);
-  }
-
-  /// For more information, see gvr_get_screen_buffer_viewports().
-  void SetToScreenBufferViewports() {
-    gvr_get_screen_buffer_viewports(context_, viewport_list_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_list_set_item().
-  void SetBufferViewport(size_t index, const BufferViewport& viewport) {
-    gvr_buffer_viewport_list_set_item(viewport_list_, index,
-                                      viewport.viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_list_get_item().
-  void GetBufferViewport(size_t index, BufferViewport* viewport) const {
-    gvr_buffer_viewport_list_get_item(viewport_list_, index,
-                                      viewport->viewport_);
-  }
-
-  /// For more information, see gvr_buffer_viewport_list_get_size().
-  size_t GetSize() const {
-    return gvr_buffer_viewport_list_get_size(viewport_list_);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  BufferViewportList(gvr_buffer_viewport_list* viewport_list,
-                     gvr_context* context)
-      : context_(context),
-        viewport_list_(viewport_list) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_buffer_viewport_list* cobj() { return viewport_list_; }
-  const gvr_buffer_viewport_list* cobj() const { return viewport_list_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_buffer_viewport_list* release() {
-    auto result = viewport_list_;
-    viewport_list_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  friend class Frame;
-  friend class GvrApi;
-  friend class SwapChain;
-
-  explicit BufferViewportList(gvr_context* context)
-      : context_(context),
-        viewport_list_(gvr_buffer_viewport_list_create(context)) {}
-
-  const gvr_context* context_;
-  gvr_buffer_viewport_list* viewport_list_;
-
-  // Disallow copy and assign.
-  BufferViewportList(const BufferViewportList&) = delete;
-  void operator=(const BufferViewportList&) = delete;
-};
-
-/// Convenience C++ wrapper for gvr_buffer_spec, an opaque pixel buffer
-/// specification. Frees the underlying gvr_buffer_spec on destruction.
-class BufferSpec {
- public:
-  BufferSpec(BufferSpec&& other)
-      : spec_(nullptr) {
-    std::swap(spec_, other.spec_);
-  }
-
-  BufferSpec& operator=(BufferSpec&& other) {
-    std::swap(spec_, other.spec_);
-    return *this;
-  }
-
-  ~BufferSpec() {
-    if (spec_) gvr_buffer_spec_destroy(&spec_);
-  }
-
-  /// Gets the buffer's size. The default value is the recommended render
-  /// target size. For more information, see gvr_buffer_spec_get_size().
-  Sizei GetSize() const {
-    return gvr_buffer_spec_get_size(spec_);
-  }
-
-  /// Sets the buffer's size. For more information, see
-  /// gvr_buffer_spec_set_size().
-  void SetSize(const Sizei& size) {
-    gvr_buffer_spec_set_size(spec_, size);
-  }
-
-  /// Sets the buffer's size to the passed width and height. For more
-  /// information, see gvr_buffer_spec_set_size().
-  ///
-  /// @param width The width in pixels. Must be greater than 0.
-  /// @param height The height in pixels. Must be greater than 0.
-  void SetSize(int32_t width, int32_t height) {
-    gvr_sizei size{width, height};
-    gvr_buffer_spec_set_size(spec_, size);
-  }
-
-  /// Gets the number of samples per pixel in the buffer. For more
-  /// information, see gvr_buffer_spec_get_samples().
-  int32_t GetSamples() const { return gvr_buffer_spec_get_samples(spec_); }
-
-  /// Sets the number of samples per pixel. For more information, see
-  /// gvr_buffer_spec_set_samples().
-  void SetSamples(int32_t num_samples) {
-    gvr_buffer_spec_set_samples(spec_, num_samples);
-  }
-
-  /// Sets the color format for this buffer. For more information, see
-  /// gvr_buffer_spec_set_color_format().
-  void SetColorFormat(ColorFormat color_format) {
-    gvr_buffer_spec_set_color_format(spec_, color_format);
-  }
-
-  /// Sets the depth and stencil format for this buffer. For more
-  /// information, see gvr_buffer_spec_set_depth_stencil_format().
-  void SetDepthStencilFormat(DepthStencilFormat depth_stencil_format) {
-    gvr_buffer_spec_set_depth_stencil_format(spec_, depth_stencil_format);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit BufferSpec(gvr_buffer_spec* spec) : spec_(spec) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_buffer_spec* cobj() { return spec_; }
-  const gvr_buffer_spec* cobj() const { return spec_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_buffer_spec* release() {
-    auto result = spec_;
-    spec_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  friend class GvrApi;
-  friend class SwapChain;
-
-  explicit BufferSpec(gvr_context* gvr) {
-    spec_ = gvr_buffer_spec_create(gvr);
-  }
-
-  gvr_buffer_spec* spec_;
-};
-
-/// Convenience C++ wrapper for gvr_frame, which represents a single frame
-/// acquired for rendering from the swap chain.
-class Frame {
- public:
-  Frame(Frame&& other) : frame_(nullptr) {
-    std::swap(frame_, other.frame_);
-  }
-
-  Frame& operator=(Frame&& other) {
-    std::swap(frame_, other.frame_);
-    return *this;
-  }
-
-  ~Frame() {
-    // The swap chain owns the frame, so no clean-up is required.
-  }
-
-  /// For more information, see gvr_frame_get_buffer_size().
-  Sizei GetBufferSize(int32_t index) const {
-    return gvr_frame_get_buffer_size(frame_, index);
-  }
-
-  /// For more information, see gvr_frame_bind_buffer().
-  void BindBuffer(int32_t index) {
-    gvr_frame_bind_buffer(frame_, index);
-  }
-
-  /// For more information, see gvr_frame_unbind().
-  void Unbind() {
-    gvr_frame_unbind(frame_);
-  }
-
-  /// For more information, see gvr_frame_get_framebuffer_object().
-  int32_t GetFramebufferObject(int32_t index) {
-    return gvr_frame_get_framebuffer_object(frame_, index);
-  }
-
-  /// For more information, see gvr_frame_submit().
-  void Submit(const BufferViewportList& viewport_list,
-              const Mat4f& head_space_from_start_space) {
-    gvr_frame_submit(&frame_, viewport_list.viewport_list_,
-                     head_space_from_start_space);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit Frame(gvr_frame* frame) : frame_(frame) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_frame* cobj() { return frame_; }
-  const gvr_frame* cobj() const { return frame_; }
-
-  /// Returns whether the wrapped gvr_frame reference is valid.
-  bool is_valid() const { return frame_ != nullptr; }
-  explicit operator bool const() { return is_valid(); }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_frame* release() {
-    auto result = frame_;
-    frame_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  friend class SwapChain;
-
-  gvr_frame* frame_;
-};
-
-/// Convenience C++ wrapper for gvr_swap_chain, which represents a queue of
-/// frames. The GvrApi object must outlive any SwapChain objects created from
-/// it.
-class SwapChain {
- public:
-  SwapChain(SwapChain&& other)
-      : swap_chain_(nullptr) {
-    std::swap(swap_chain_, other.swap_chain_);
-  }
-
-  SwapChain& operator=(SwapChain&& other) {
-    std::swap(swap_chain_, other.swap_chain_);
-    return *this;
-  }
-
-  ~SwapChain() {
-    if (swap_chain_) gvr_swap_chain_destroy(&swap_chain_);
-  }
-
-  /// For more information, see gvr_swap_chain_get_buffer_count().
-  int32_t GetBufferCount() const {
-    return gvr_swap_chain_get_buffer_count(swap_chain_);
-  }
-
-  /// For more information, see gvr_swap_chain_get_buffer_size().
-  Sizei GetBufferSize(int32_t index) const {
-    return gvr_swap_chain_get_buffer_size(swap_chain_, index);
-  }
-
-  /// For more information, see gvr_swap_chain_resize_buffer().
-  void ResizeBuffer(int32_t index, Sizei size) {
-    gvr_swap_chain_resize_buffer(swap_chain_, index, size);
-  }
-
-  /// For more information, see gvr_swap_chain_acquire_frame().
-  /// Note that if Frame acquisition fails, the returned Frame may not be valid.
-  /// The caller should inspect the returned Frame's validity before using,
-  /// and reschedule frame acquisition upon failure.
-  Frame AcquireFrame() {
-    Frame result(gvr_swap_chain_acquire_frame(swap_chain_));
-    return result;
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit SwapChain(gvr_swap_chain* swap_chain) : swap_chain_(swap_chain) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_swap_chain* cobj() { return swap_chain_; }
-  const gvr_swap_chain* cobj() const { return swap_chain_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_swap_chain* release() {
-    auto result = swap_chain_;
-    swap_chain_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  friend class GvrApi;
-
-  SwapChain(gvr_context* gvr, const std::vector<BufferSpec>& specs) {
-    std::vector<const gvr_buffer_spec*> c_specs;
-    for (const auto& spec : specs)
-      c_specs.push_back(spec.spec_);
-    swap_chain_ = gvr_swap_chain_create(gvr, c_specs.data(),
-                                        static_cast<int32_t>(c_specs.size()));
-  }
-
-  gvr_swap_chain* swap_chain_;
-
-  // Disallow copy and assign.
-  SwapChain(const SwapChain&);
-  void operator=(const SwapChain&);
-};
-
-/// This is a convenience C++ wrapper for the Google VR C API.
-///
-/// This wrapper strategy prevents ABI compatibility issues between compilers
-/// by ensuring that the interface between client code and the implementation
-/// code in libgvr.so is a pure C interface. The translation from C++ calls
-/// to C calls provided by this wrapper runs entirely in the client's binary
-/// and is compiled by the client's compiler.
-///
-/// Methods in this class are only documented insofar as the C++ wrapping logic
-/// is concerned; for information about the method itself, please refer to the
-/// corresponding function in the C API.
-///
-/// Example API usage:
-///
-///     // Functionality supplied by the application in the example below has
-///     // the "app-" prefix.
-///     #ifdef __ANDROID__
-///     // On Android, the gvr_context should almost always be obtained from the
-///     // Java GvrLayout object via
-///     // GvrLayout.getGvrApi().getNativeGvrContext().
-///     std::unique_ptr<GvrApi> gvr = GvrApi::WrapNonOwned(gvr_context);
-///     #else
-///     std::unique_ptr<GvrApi> gvr = GvrApi::Create();
-///     #endif
-///
-///     gvr->InitializeGl();
-///
-///     gvr::BufferViewportList viewport_list =
-///         gvr->CreateEmptyBufferViewportList();
-///     gvr->GetRecommendedBufferViewports(&viewport_list);
-///     gvr::BufferViewport left_eye_viewport = gvr->CreateBufferViewport();
-///     gvr::BufferViewport right_eye_viewport = gvr->CreateBufferViewport();
-///     viewport_list.Get(0, &left_eye_view);
-///     viewport_list.Get(1, &right_eye_view);
-///
-///     std::vector<gvr::BufferSpec> specs;
-///     specs.push_back(gvr->CreateBufferSpec());
-///     specs[0].SetSamples(app_samples);
-///     gvr::SwapChain swap_chain = gvr->CreateSwapChain(specs);
-///
-///     while (client_app_should_render) {
-///       // A client app should be ready for the render target size to change
-///       // whenever a new QR code is scanned, or a new viewer is paired.
-///       gvr::Sizei render_target_size =
-///           gvr->GetRecommendedRenderTargetSize();
-///       swap_chain.ResizeBuffer(0, render_target_size);
-///       gvr::Frame frame = swap_chain.AcquireFrame();
-///       while (!frame) {
-///         std::this_thread::sleep_for(2ms);
-///         frame = swap_chain.AcquireFrame();
-///       }
-///
-///       // This function will depend on your render loop's implementation.
-///       gvr::ClockTimePoint next_vsync = AppGetNextVsyncTime();
-///
-///       const gvr::Mat4f head_view =
-///           gvr->GetHeadSpaceFromStartSpaceRotation(next_vsync);
-///       const gvr::Mat4f left_eye_view = MatrixMultiply(
-///           gvr->GetEyeFromHeadMatrix(kLeftEye), head_view);
-///       const gvr::Mat4f right_eye_view = MatrixMultiply(
-///           gvr->GetEyeFromHeadMatrix(kRightEye), head_view);
-///
-///       frame.BindBuffer(0);
-///       // App does its rendering to the current framebuffer here.
-///       AppDoSomeRenderingForEye(
-///           left_eye_viewport.GetSourceUv(), left_eye_view);
-///       AppDoSomeRenderingForEye(
-///           right_eye_viewport.GetSourceUv(), right_eye_view);
-///       frame.Unbind();
-///       frame.Submit(viewport_list, head_matrix);
-///     }
-///
-class GvrApi {
- public:
-#ifdef __ANDROID__
-  /// Instantiates and returns a GvrApi instance that owns a gvr_context.
-  ///
-  /// @param env The JNIEnv associated with the current thread.
-  /// @param app_context The Android application context. This must be the
-  ///     application context, NOT an Activity context (Note: from any Android
-  ///     Activity in your app, you can call getApplicationContext() to
-  ///     retrieve the application context).
-  /// @param class_loader The class loader to use when loading Java classes.
-  ///     This must be your app's main class loader (usually accessible through
-  ///     activity.getClassLoader() on any of your Activities).
-  /// @return unique_ptr to the created GvrApi instance, nullptr on failure.
-  static std::unique_ptr<GvrApi> Create(JNIEnv* env, jobject app_context,
-                                        jobject class_loader) {
-    gvr_context* context = gvr_create(env, app_context, class_loader);
-    if (!context) {
-      return nullptr;
-    }
-    return std::unique_ptr<GvrApi>(new GvrApi(context, true /* owned */));
-  }
-#else
-  /// Instantiates and returns a GvrApi instance that owns a gvr_context.
-  ///
-  /// @return unique_ptr to the created GvrApi instance, nullptr on failure.
-  static std::unique_ptr<GvrApi> Create() {
-    gvr_context* context = gvr_create();
-    if (!context) {
-      return nullptr;
-    }
-    return std::unique_ptr<GvrApi>(new GvrApi(context, true /* owned */));
-  }
-#endif  // #ifdef __ANDROID__
-
-  ~GvrApi() {
-    if (context_ && owned_) {
-      gvr_destroy(&context_);
-    }
-  }
-
-  /// @name Error handling
-  /// @{
-
-  /// For more information, see gvr_get_error().
-  Error GetError() { return static_cast<Error>(gvr_get_error(context_)); }
-
-  /// For more information, see gvr_clear_error().
-  Error ClearError() { return static_cast<Error>(gvr_clear_error(context_)); }
-
-  /// For more information, see gvr_get_error_string().
-  static const char* GetErrorString(Error error_code) {
-    return gvr_get_error_string(error_code);
-  }
-
-  /// For more information, see gvr_get_user_prefs().
-  UserPrefs GetUserPrefs() { return UserPrefs(gvr_get_user_prefs(context_)); }
-
-  /// @}
-
-  /// @name Rendering
-  /// @{
-
-  /// For more information, see gvr_initialize_gl().
-  void InitializeGl() { gvr_initialize_gl(context_); }
-
-  /// For more information, see gvr_get_async_reprojection_enabled().
-  bool GetAsyncReprojectionEnabled() const {
-    return gvr_get_async_reprojection_enabled(context_);
-  }
-
-  /// Constructs a C++ wrapper for a gvr_buffer_viewport object.  For more
-  /// information, see gvr_buffer_viewport_create().
-  ///
-  /// @return A new BufferViewport instance with memory allocated for an
-  ///     underlying gvr_buffer_viewport.
-  BufferViewport CreateBufferViewport() const {
-    return BufferViewport(context_);
-  }
-
-  /// Constructs a C++ wrapper for a gvr_buffer_viewport_list object.
-  /// For more information, see gvr_buffer_viewport_list_create().
-  ///
-  /// @return A new, empty BufferViewportList instance.
-  ///     Note: The validity of the returned object is closely tied to the
-  ///     lifetime of the member gvr_context. The caller is responsible for
-  ///     ensuring correct usage accordingly.
-  BufferViewportList CreateEmptyBufferViewportList() const {
-    return BufferViewportList(context_);
-  }
-
-  /// For more information, see gvr_get_maximum_effective_render_target_size().
-  Sizei GetMaximumEffectiveRenderTargetSize() const {
-    return gvr_get_maximum_effective_render_target_size(context_);
-  }
-
-  /// For more information, see gvr_get_screen_target_size().
-  Sizei GetScreenTargetSize() const {
-    return gvr_get_screen_target_size(context_);
-  }
-
-  /// For more information, see gvr_set_surface_size().
-  void SetSurfaceSize(Sizei surface_size_pixels) {
-    gvr_set_surface_size(context_, surface_size_pixels);
-  }
-
-  /// For more information, see gvr_distort_to_screen().
-  void DistortToScreen(int32_t texture_id,
-                       const BufferViewportList& viewport_list,
-                       const Mat4f& rendered_head_pose_in_start_space_matrix,
-                       const ClockTimePoint& texture_presentation_time) {
-    gvr_distort_to_screen(context_, texture_id, viewport_list.viewport_list_,
-                          rendered_head_pose_in_start_space_matrix,
-                          texture_presentation_time);
-  }
-
-  /// For more information, see gvr_is_feature_supported().
-  bool IsFeatureSupported(int32_t feature) {
-    return gvr_is_feature_supported(context_, feature);
-  }
-
-  /// For more information, see gvr_buffer_spec_create().
-  BufferSpec CreateBufferSpec() {
-    return BufferSpec(context_);
-  }
-
-  /// For more information, see gvr_swap_chain_create().
-  SwapChain CreateSwapChain(const std::vector<BufferSpec>& specs) {
-    return SwapChain(context_, specs);
-  }
-
-  /// For more information, see gvr_bind_default_framebuffer().
-  void BindDefaultFramebuffer() {
-    gvr_bind_default_framebuffer(context_);
-  }
-  /// @}
-
-  /// @name Head tracking
-  /// @{
-
-  /// For more information see gvr_get_head_space_from_start_space_rotation.
-  ///
-  /// @param time_point The time at which to calculate the head pose in start
-  ///     space.
-  /// @return The matrix representation of the rotation from start space
-  ///     (the space with the head pose at the last tracking reset at origin) to
-  ///     head space (the space with the head at origin and axes aligned to the
-  ///     view vector).
-  Mat4f GetHeadSpaceFromStartSpaceRotation(const ClockTimePoint& time_point) {
-    return gvr_get_head_space_from_start_space_rotation(context_, time_point);
-  }
-
-  /// For more information, see gvr_apply_neck_model().
-  Mat4f ApplyNeckModel(const Mat4f& head_pose_in_start_space, float factor) {
-    return gvr_apply_neck_model(context_, head_pose_in_start_space, factor);
-  }
-
-  /// For more information, see gvr_pause_tracking().
-  void PauseTracking() { gvr_pause_tracking(context_); }
-
-  /// For more information, see gvr_resume_tracking().
-  void ResumeTracking() { gvr_resume_tracking(context_); }
-
-  /// For more information, see gvr_reset_tracking().
-  void ResetTracking() { gvr_reset_tracking(context_); }
-
-  // For more information, see gvr_recenter_tracking().
-  void RecenterTracking() { gvr_recenter_tracking(context_); }
-
-  /// For more information, see gvr_get_time_point_now().
-  static ClockTimePoint GetTimePointNow() { return gvr_get_time_point_now(); }
-  /// @}
-
-  /// @name Viewer parameters
-  /// @{
-
-  /// For more information, see gvr_set_default_viewer_profile().
-  bool SetDefaultViewerProfile(const char* viewer_profile_uri) {
-    return gvr_set_default_viewer_profile(context_, viewer_profile_uri);
-  }
-
-  /// For more information, see gvr_refresh_viewer_profile().
-  void RefreshViewerProfile() { gvr_refresh_viewer_profile(context_); }
-
-  /// For more information, see gvr_get_viewer_vendor().
-  const char* GetViewerVendor() const {
-    return gvr_get_viewer_vendor(context_);
-  }
-
-  /// For more information, see gvr_get_viewer_model().
-  const char* GetViewerModel() const { return gvr_get_viewer_model(context_); }
-
-  /// For more information, see gvr_get_viewer_type().
-  ViewerType GetViewerType() const {
-    return static_cast<ViewerType>(gvr_get_viewer_type(context_));
-  }
-
-  /// For more information, see gvr_get_eye_from_head_matrix().
-  Mat4f GetEyeFromHeadMatrix(Eye eye) const {
-    return gvr_get_eye_from_head_matrix(context_, eye);
-  }
-
-  /// For more information, see gvr_get_window_bounds().
-  Recti GetWindowBounds() const { return gvr_get_window_bounds(context_); }
-
-  /// For more information, see gvr_compute_distorted_point().
-  std::array<Vec2f, 3> ComputeDistortedPoint(Eye eye, const Vec2f& uv_in) {
-    std::array<Vec2f, 3> uv_out = {{{}}};
-    gvr_compute_distorted_point(context_, eye, uv_in, uv_out.data());
-    return uv_out;
-  }
-  /// @}
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and optionally takes ownership.
-  ///
-  /// @param context C object to wrap.
-  /// @param owned Whether the wrapper will own the underlying C object.
-  explicit GvrApi(gvr_context* context, bool owned = true)
-      : context_(context), owned_(owned) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_context* cobj() { return context_; }
-  const gvr_context* cobj() const { return context_; }
-
-  /// @deprecated Use cobj() instead.
-  gvr_context* GetContext() { return context_; }
-  /// @deprecated Use cobj() instead.
-  const gvr_context* GetContext() const { return context_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_context* release() {
-    auto result = context_;
-    context_ = nullptr;
-    return result;
-  }
-
-  /// Instantiates a GvrApi instance that wraps a *non-owned* gvr_context.
-  ///
-  /// Ownership of the provided `context` remains with the caller, and they
-  /// are responsible for ensuring proper disposal of the context.
-  ///
-  /// @param context Pointer to a non-null, non-owned gvr_context instance.
-  /// @return unique_ptr to the created GvrApi instance. Never null.
-  static std::unique_ptr<GvrApi> WrapNonOwned(gvr_context* context) {
-    return std::unique_ptr<GvrApi>(new GvrApi(context, false /* owned */));
-  }
-  /// @}
-
- private:
-  gvr_context* context_;
-
-  // Whether context_ is owned by the GvrApi instance. If owned, the context
-  // will be released upon destruction.
-  const bool owned_;
-
-  // Disallow copy and assign.
-  GvrApi(const GvrApi&);
-  void operator=(const GvrApi&);
-};
-
-}  // namespace gvr
-#endif  // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h
deleted file mode 100644
index d34c84d..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_audio.h
+++ /dev/null
@@ -1,852 +0,0 @@
-/* Copyright 2016 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_
-
-#if __ANDROID__
-#include <jni.h>
-#endif  // __ANDROID__
-
-#include <stdint.h>
-
-#include "vr/gvr/capi/include/gvr.h"
-#include "vr/gvr/capi/include/gvr_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif  // __cplusplus
-
-/// @defgroup Audio Spatial Audio API
-/// @brief This is the GVR Audio C API, a spatial audio rendering engine,
-/// optimized for mobile VR.
-///
-/// It allows the user to spatialize sound sources in 3D space, including
-/// distance and elevation cues. Specifically, the API is capable of playing
-/// back spatial sound in three ways:
-///
-/// - **Sound object rendering**: This allows the user to create a virtual sound
-///   source in 3D space. These sources, while spatialized, are fed with mono
-///   audio data.
-///
-/// - **Ambisonic soundfields**: Ambisonic recordings are multi-channel audio
-///   files which are spatialized all around the listener in 360 degrees. These
-///   can be thought of as recorded or pre-baked soundfields. They can be of
-///   great use for background effects which sound perfectly spatial.  Examples
-///   include rain noise, crowd noise or even the sound of the ocean off to one
-///   side.
-///
-/// - **Stereo Sounds**: This allows the user to directly play back
-///   non-spatialized mono or stereo audio files. This is useful for music and
-///   other such audio.
-///
-/// **Initialization**
-///
-///     gvr_audio_context* gvr_audio_create(int32_t rendering_mode);
-///
-/// The rendering_mode argument corresponds to a `gvr_audio_rendering_mode` enum
-/// value, which specifies a rendering configuration setting:
-///
-/// - `GVR_AUDIO_RENDERING_STEREO_PANNING`:
-///   Stereo panning of all sound objects. This disables HRTF-based rendering.
-/// - `GVR_AUDIO_RENDERING_BINAURAL_LOW_QUALITY`:
-///   This renders sound objects over a virtual array of 8 loudspeakers arranged
-///   in a cube configuration around the listener’s head. HRTF-based rendering
-///   is enabled.
-/// - `GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY`:
-///   This renders sound objects over a virtual array of 16 loudspeakers
-///   arranged in an approximate equidistribution about the listener’s
-///   head. HRTF-based rendering is enabled.
-///
-/// For most modern phones, the high quality mode offers a good balance between
-/// performance and audio quality. To optimize the rendering performance for
-/// headphones *and* speaker playback, the stereo speaker mode can be enabled
-/// which automatically switches to stereo panning when no headphone is plugin.
-/// Note that this can lead to varying CPU usage based on headphone and speaker
-/// playback.
-///
-/// **Sound engine control**
-///
-/// Audio playback on the default audio device can be started and stopped by
-/// calling the following two methods:
-///
-///     void gvr_audio_pause(gvr_audio_context* api);
-///     void gvr_audio_resume(gvr_audio_context* api);
-///
-/// Note that:
-///
-///     void gvr_audio_update(gvr_audio_context* api);
-///
-/// must be called from the main thread at a regular rate. It is used to execute
-/// background operations outside of the audio thread.
-///
-/// **Listener position and rotation**
-///
-/// To ensure that the audio in your application reacts to listener head
-/// movement, it is important to update the listener's head orientation in the
-/// graphics callback using the head orientation matrix.
-///
-/// The following methods can be used to control the listener’s head position
-/// and orientation with the audio engine:
-///
-///     void gvr_audio_set_head_position(gvr_audio_context* api, float x,
-///                                      float y, float z);
-/// or
-///
-///     void gvr_audio_set_head_position_gvr(gvr_audio_context* api,
-///                                          const gvr_vec3f& position);
-///
-/// and
-///
-///     void gvr_audio_set_head_rotation(gvr_audio_context* api,
-///                                      float x, float y, float z, float w);
-/// or
-///
-///     void gvr_audio_set_head_rotation_gvr(gvr_audio_context* api,
-///                                          const gvr_quatf& rotation);
-///
-/// **Preloading Sounds**
-///
-/// Both mono sound files for use with Sound Objects and multi-channel Ambisonic
-/// soundfield files can be preloaded into memory before playback or
-/// alternatively streamed during playback. Preloading can be useful to reduce
-/// CPU usage especially if the same audio clip is likely to be played back many
-/// times. In this case playback latency is also reduced.
-///
-/// Sound files can be preloaded into memory by calling:
-///
-///     bool gvr_audio_preload_soundfile(gvr_audio_context* api,
-///                                      const char* filename);
-///
-/// Unused sound files can be unloaded with a call to:
-///
-///     void gvr_audio_unload_soundfile(gvr_audio_context* api,
-///                                     const char* filename);
-///
-/// NOTE: If a sound object, soundfield or stereo sound is created with a file
-/// that has not been preloaded, that audio will be streamed.
-///
-/// **Spatializtion of sound objects**
-///
-/// The GVR Audio System allows the user to create virtual sound objects which
-/// can be placed anywhere in space around the listener.
-///
-/// To create a new sound object, call:
-///
-///     gvr_audio_source_id
-///     gvr_audio_create_sound_object(gvr_audio_context* api,
-///                                   const char* filename);
-///
-/// This returns a handle that can be used to set properties such as the
-/// position and the volume of the sound object via calls to the following two
-/// functions:
-///
-///     void
-///     gvr_audio_set_sound_object_position(gvr_audio_context* api,
-///                                         gvr_audio_source_id sound_object_id,
-///                                         float x, float y, float z);
-///
-///     void
-///     gvr_audio_set_sound_volume(gvr_audio_context* api,
-///                                gvr_audio_source_id source_id, float volume);
-///
-/// The behavior of Sound Objects with respect to their distance from the
-/// listener can be controlled via calls to the following method:
-///
-///     void gvr_audio_set_sound_object_distance_rolloff_model(
-///         gvr_audio_context* api, gvr_audio_source_id sound_object_id,
-///         int32_t rolloff_model, float min_distance, float max_distance);
-///
-/// This enables a user to choose between logarithmic and linear distance
-/// rolloff methods, or to completely disable distance rolloff effects.
-///
-///
-/// The spatialized playback of a sound object can be triggered with a call to:
-///
-///     void gvr_audio_play_sound(gvr_audio_context* api,
-///                               gvr_audio_source_id source_id,
-///                               bool looping_enabled);
-///
-/// and stopped with a call to:
-///
-///     void gvr_audio_stop_sound(gvr_audio_context* api,
-///                               gvr_audio_source_id source_id);
-///
-/// Note that the sound object handle destroys itself at the moment the sound
-/// playback has stopped. This way, no clean up of sound object handles is
-/// needed. On subsequent calls to this function the corresponding
-/// gvr_audio_source_id no longer refers to a valid sound object.
-///
-/// The following function can be used to check if a sound object is currently
-/// active:
-///
-///     bool gvr_audio_is_sound_playing(const gvr_audio_context* api,
-///                                     gvr_audio_source_id source_id);
-///
-/// **Rendering of ambisonic soundfields**
-///
-/// The GVR Audio System also provides the user with the ability to play back
-/// ambisonic soundfields. Ambisonic soundfields are captured or pre-rendered
-/// 360 degree recordings. It is best to think of them as equivalent to 360
-/// degree video. While they envelop and surround the listener, they only react
-/// to the listener's rotational movement. That is, one cannot walk towards
-/// features in the soundfield. Soundfields are ideal for accompanying 360
-/// degree video playback, for introducing background and environmental effects
-/// such as rain or crowd noise, or even for pre baking 3D audio to reduce
-/// rendering costs.  The GVR Audio System supports full 3D First Order
-/// Ambisonic recordings using ACN channel ordering and SN3D normalization. For
-/// more information please see our Spatial Audio specification at:
-/// https://github.com/google/spatial-media/blob/master/docs/spatial-audio-rfc.md#semantics
-///
-/// Note that Soundfield playback is directly streamed from the sound file and
-/// no sound file preloading is needed.
-///
-/// To obtain a soundfield handler, call:
-///
-///     gvr_audio_source_id gvr_audio_create_soundfield(gvr_audio_context* api,
-///                                                    const char* filename);
-///
-/// This returns a gvr_audio_source_id handle that allows the user to begin
-/// playback of the soundfield, to alter the soundfield’s volume or to stop
-/// soundfield playback and as such destroy the object. These actions can be
-/// achieved with calls to the following functions:
-///
-///     void gvr_audio_play_sound(gvr_audio_context* api,
-///                               gvr_audio_source_id source_id,
-///                               bool looping_enabled);
-///
-///     void gvr_audio_set_sound_volume(gvr_audio_context* api,
-///                                     gvr_audio_source_id source_id,
-///                                     float volume);
-///
-///     void gvr_audio_stop_sound(gvr_audio_context* api,
-///                               gvr_audio_source_id source_id);
-///
-/// Ambisonic soundfields can also be rotated about the listener's head in order
-/// to align the components of the soundfield with the visuals of the game/app.
-///
-/// void gvr_audio_set_soundfield_rotation(gvr_audio_context* api,
-///                                        gvr_audio_source_id soundfield_id,
-///                                        const gvr_quatf&
-///                                        soundfield_rotation);
-///
-/// **Direct Playback of Stereo or Mono Sounds**
-///
-/// The GVR Audio System allows the direct non-spatialized playback of both
-/// stereo and mono audio. Such audio is often used for music or sound effects
-/// that should not be spatialized.
-///
-/// A stereo sound can be created with a call to:
-///
-/// gvr_audio_source_id gvr_audio_create_stereo_sound(gvr_audio_context* api,
-///                                                  const char* filename);
-///
-/// **Paused Sounds and Stopped Sounds**
-///
-/// When using sound sources of any of the above types, the user can ensure that
-/// the given source is currently playing before calling.
-///
-/// bool gvr_audio_is_sound_playing(gvr_audio_source_id source_id);
-///
-/// This method will return false if the source has been either paused or
-/// stopped, and true if the source is currently playing.
-///
-/// Once one is finished with a Sound Object and wish to remove it, a call can
-/// be placed to:
-///
-/// void gvr_audio_stop_sound(gvr_audio_source_id source_id);
-///
-/// Once a source has been stopped it is destroyed and the corresponding
-/// gvr_audio_source_id will be invalid. Sources which have been played with the
-/// |looping_enabled| parameter disabled will also be destroyed once playback
-/// of the full audio clip has completed.
-///
-/// To check whether a given gvr_audio_source_id corresponds to a valid source
-/// which exists and is in a playable state, a call can be made to:
-///
-/// bool gvr_audio_is_source_id_valid(gvr_audio_source_id source_id);
-///
-/// By using this pair of methods a user can differentiate between sources which
-/// have been paused and those which have ceased.
-///
-/// **Room effects**
-///
-/// The GVR Audio System provides a powerful reverb engine which can be used to
-/// create customized room effects by specifying the size of a room and a
-/// material for each surface of the room from the gvr_audio_material_name enum.
-/// Each of these surface materials has unique absorption properties which
-/// differ with frequency. The room created will be centered around the
-/// listener. Note that the Google VR Audio System uses meters as the unit of
-/// distance throughout.
-///
-/// The following methods are used to control room effects:
-///
-///     void gvr_audio_enable_room(gvr_audio_context* api, bool enable);
-///
-/// enables or disables room effects with smooth transitions.
-///
-/// and
-///
-///     void
-///     gvr_audio_set_room_properties(gvr_audio_context* api, float size_x,
-///                                   float size_y, float size_z,
-///                                   gvr_audio_material_name wall_material,
-///                                   gvr_audio_material_name ceiling_material,
-///                                   gvr_audio_material_name floor_material);
-///
-/// allows the user to describe the room based on its dimensions and its surface
-/// properties. For example, one can expect very large rooms to be more
-/// reverberant than smaller rooms, and a room with with hard surface materials
-/// such as brick to be more reverberant than one with soft absorbent materials
-/// such as heavy curtains on every surface.
-///
-/// Note that when a sound source is located outside of the listener's room,
-/// it will sound different from sources located within the room due to
-/// attenuation of both the direct sound and the reverb on that source. Sources
-/// located far outside of the listener's room will not be audible to the
-/// listener.
-///
-/// The following method can be used to subtly adjust the reverb in a room by
-/// changing the gain/attenuation on the reverb, setting a multiplier on the
-/// reverberation time to control the reverb's length, or adjusting the balance
-/// between the low and high frequency components of the reverb.
-///
-/// void gvr_audio_set_room_reverb_adjustments(gvr_audio_context* api,
-///                                            float gain,
-///                                            float time_adjust,
-///                                            float brightness_adjust);
-///
-/// If you are writing C++ code, you might prefer to use the C++ wrapper
-/// rather than implement this C API directly.
-///
-/// **Example usage (C++ API)**
-///
-/// Construction:
-///
-///     std::unique_ptr<gvr::AudioApi> gvr_audio_api(new gvr::AudioApi);
-///     gvr_audio_api->Init(GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY);
-///
-/// Update head rotation in DrawFrame():
-///
-///     head_pose_ = gvr_api_->GetHeadSpaceFromStartSpaceRotation(target_time);
-///     gvr_audio_api_->SetHeadPose(head_pose_);
-///     gvr_audio_api_->Update();
-///
-/// Preload sound file, create sound handle and start playback:
-///
-///     gvr_audio_api->PreloadSoundfile(kSoundFile);
-///     AudioSourceId source_id =
-///                   gvr_audio_api_->CreateSoundObject("sound.wav");
-///     gvr_audio_api->SetSoundObjectPosition(source_id,
-///                                           position_x,
-///                                           position_y,
-///                                           position_z);
-///     gvr_audio_api->PlaySound(source_id, true /* looped playback */);
-///
-
-/// @{
-
-typedef struct gvr_audio_context_ gvr_audio_context;
-
-/// Creates and initializes a gvr_audio_context. This call also initializes
-/// the audio interface and starts the audio engine. Note that the returned
-/// instance must be deleted with gvr_audio_destroy.
-///
-#ifdef __ANDROID__
-/// @param env The JNI Env associated with the current thread.
-/// @param android_context The Android application context. This must be the
-///     application context, NOT an Activity context (Note: from any Android
-///     Activity in your app, you can call getApplicationContext() to
-///     retrieve the application context).
-/// @param class_loader The class loader to use when loading Java
-///     classes. This must be your app's main class loader (usually
-///     accessible through activity.getClassLoader() on any of your Activities).
-/// @param rendering_mode The gvr_audio_rendering_mode value which determines
-///     the rendering configuration preset. This is passed as an int32_t to
-///     ensure API compatibility.
-/// @return gvr_audio_context instance.
-gvr_audio_context* gvr_audio_create(JNIEnv* env, jobject android_context,
-                                    jobject class_loader,
-                                    int32_t rendering_mode);
-#else
-/// @param rendering_mode The gvr_audio_rendering_mode value which determines
-///     the rendering configuration preset. This is passed as an int32_t to
-///     ensure API compatibility.
-/// @return gvr_audio_context instance.
-gvr_audio_context* gvr_audio_create(int32_t rendering_mode);
-#endif  // #ifdef __ANDROID__
-
-/// Destroys a gvr_audio_context that was previously created with
-/// gvr_audio_create or gvr_audio_create_android.
-///
-/// @param api Pointer to a pointer to a gvr_audio_context. The pointer
-///     will be set to NULL after destruction.
-void gvr_audio_destroy(gvr_audio_context** api);
-
-/// Resumes the VR Audio system.
-/// Call this when your app/game loses focus.
-/// Calling this when not paused is a no-op.
-/// Thread-safe (call from any thread).
-///
-/// @param api Pointer to a gvr_audio_context.
-void gvr_audio_resume(gvr_audio_context* api);
-
-/// Pauses the VR Audio system.
-/// Calling this when already paused is a no-op.
-/// Thread-safe (call from any thread).
-///
-/// @param api Pointer to a gvr_audio_context.
-void gvr_audio_pause(gvr_audio_context* api);
-
-/// This method must be called from the main thread at a regular rate. It is
-/// used to execute background operations outside of the audio thread.
-///
-/// @param api Pointer to a gvr_audio_context.
-void gvr_audio_update(gvr_audio_context* api);
-
-/// Preloads a local sound file. Note that the local file access method
-/// depends on the target platform.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param filename Name of the file, used as identifier.
-/// @return True on success or if file has already been preloaded.
-bool gvr_audio_preload_soundfile(gvr_audio_context* api, const char* filename);
-
-/// Unloads a previously preloaded sample from memory. Note that if the sample
-/// is currently used, the memory is freed at the moment playback stops.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param filename Name of the file, used as identifier.
-void gvr_audio_unload_soundfile(gvr_audio_context* api, const char* filename);
-
-/// Returns a new sound object. Note that the sample should only contain a
-/// single audio channel (stereo sources are automatically downmixed to mono).
-/// The handle automatically destroys itself at the moment the sound playback
-/// has stopped.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param filename The path/name of the file to be played.
-/// @return Id of new sound object. Returns kInvalidId if the sound file has not
-///     been preloaded or if the number of input channels is > 1.
-gvr_audio_source_id gvr_audio_create_sound_object(gvr_audio_context* api,
-                                                  const char* filename);
-
-/// Returns a new ambisonic sound field. Note that the sample needs to be
-/// preloaded and must have 4 separate audio channels. The handle automatically
-/// destroys itself at the moment the sound playback has stopped.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param filename The path/name of the file to be played.
-/// @return Id of new soundfield. Returns kInvalidId if the sound file has not
-///     been preloaded or if the number of input channels does not match that
-///     required.
-gvr_audio_source_id gvr_audio_create_soundfield(gvr_audio_context* api,
-                                                const char* filename);
-
-/// Returns a new stereo non-spatialized source, which directly plays back mono
-/// or stereo audio. Note the sample needs to be preloaded and may contain only
-/// one (mono) or two (stereo) audio channels.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param filename The path/name of the file to be played..
-/// @return Id of new stereo non-spatialized source. Returns kInvalidId if the
-///     sound file has not been preloaded or if the number of input channels is
-///     > 2;
-gvr_audio_source_id gvr_audio_create_stereo_sound(gvr_audio_context* api,
-                                                  const char* filename);
-
-/// Starts the playback of a sound.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be stopped.
-/// @param looping_enabled Enables looped audio playback.
-void gvr_audio_play_sound(gvr_audio_context* api, gvr_audio_source_id source_id,
-                          bool looping_enabled);
-
-/// Pauses the playback of a sound.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be paused.
-void gvr_audio_pause_sound(gvr_audio_context* api,
-                           gvr_audio_source_id source_id);
-
-/// Resumes the playback of a sound.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be resumed.
-void gvr_audio_resume_sound(gvr_audio_context* api,
-                            gvr_audio_source_id source_id);
-
-/// Stops the playback of a sound and destroys the corresponding sound object
-/// or Soundfield.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be stopped.
-void gvr_audio_stop_sound(gvr_audio_context* api,
-                          gvr_audio_source_id source_id);
-
-/// Checks if a sound is playing.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be checked.
-/// @return True if the sound is being played.
-bool gvr_audio_is_sound_playing(const gvr_audio_context* api,
-                                gvr_audio_source_id source_id);
-
-/// Checks if a |source_id| is valid, and that the corresponding source is in a
-/// playable state. Sources that have been stopped will be reported as invalid.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be checked.
-/// @return True if the source exists and is in a playable state.
-bool gvr_audio_is_source_id_valid(const gvr_audio_context* api,
-                                  gvr_audio_source_id source_id);
-
-/// Repositions an existing sound object.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param sound_object_id Id of the sound object to be moved.
-/// @param x X coordinate the sound will be placed at.
-/// @param y Y coordinate the sound will be placed at.
-/// @param z Z coordinate the sound will be placed at.
-void gvr_audio_set_sound_object_position(gvr_audio_context* api,
-                                         gvr_audio_source_id sound_object_id,
-                                         float x, float y, float z);
-
-/// Sets the given ambisonic soundfields's rotation.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param soundfield_id Id of the soundfield source to be rotated.
-/// @param soundfield_rotation Quaternion representing the soundfield rotation.
-void gvr_audio_set_soundfield_rotation(gvr_audio_context* api,
-                                       gvr_audio_source_id soundfield_id,
-                                       const gvr_quatf& soundfield_rotation);
-
-/// Sets the given sound object source's distance attenuation method with
-/// minimum and maximum distances. Maximum distance must be greater than the
-/// minimum distance for the method to be set.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param sound_object_id Id of sound object source.
-/// @param rolloff_model Linear or logarithmic distance rolloff models. Note
-///     setting the rolloff model to |GVR_AUDIO_ROLLOFF_NONE| will allow
-///     distance attenuation values to be set manually.
-/// @param min_distance Minimum distance to apply distance attenuation method.
-/// @param max_distance Maximum distance to apply distance attenuation method.
-void gvr_audio_set_sound_object_distance_rolloff_model(
-    gvr_audio_context* api, gvr_audio_source_id sound_object_id,
-    int32_t rolloff_model, float min_distance, float max_distance);
-
-/// Changes the master volume.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param volume Volume value. Should range from 0 (mute) to 1 (max).
-void gvr_audio_set_master_volume(gvr_audio_context* api, float volume);
-
-/// Changes the volume of an existing sound.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param source_id Id of the audio source to be modified.
-/// @param volume Volume value. Should range from 0 (mute) to 1 (max).
-void gvr_audio_set_sound_volume(gvr_audio_context* api,
-                                gvr_audio_source_id source_id, float volume);
-
-/// Sets the head pose from a matrix representation of the same.
-///
-/// @param api Pointer to a gvr_audio_context on which to set the pose.
-/// @param head_pose_matrix Matrix representing the head transform to be set.
-void gvr_audio_set_head_pose(gvr_audio_context* api,
-                             const gvr_mat4f& head_pose_matrix);
-
-/// Turns on/off the room reverberation effect.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param enable True to enable room effect.
-void gvr_audio_enable_room(gvr_audio_context* api, bool enable);
-
-/// Sets the room properties describing the dimensions and surface materials of
-/// a given room.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param size_x Dimension along X axis.
-/// @param size_y Dimension along Y axis.
-/// @param size_z Dimension along Z axis.
-/// @param wall_material Surface gvr_audio_material_type for the four walls.
-/// @param ceiling_material Surface gvr_audio_material_type for the ceiling.
-/// @param floor_material Surface gvr_audio_material_type for the floor.
-void gvr_audio_set_room_properties(gvr_audio_context* api, float size_x,
-                                   float size_y, float size_z,
-                                   int32_t wall_material,
-                                   int32_t ceiling_material,
-                                   int32_t floor_material);
-
-/// Adjusts the properties of the current reverb, allowing changes to the
-/// reverb's gain, duration and low/high frequency balance.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param gain Reverb volume (linear) adjustment in range [0, 1] for
-///     attenuation, range [1, inf) for gain boost.
-/// @param time_adjust Reverb time adjustment multiplier to scale the
-///     reverberation tail length. This value should be >= 0.
-/// @param brightness_adjust Reverb brightness adjustment that controls the
-///     reverberation ratio across low and high frequency bands.
-void gvr_audio_set_room_reverb_adjustments(gvr_audio_context* api, float gain,
-                                           float time_adjust,
-                                           float brightness_adjust);
-
-/// Enables the stereo speaker mode. It enforces stereo-panning when headphones
-/// are *not* plugged into the phone. This helps to avoid HRTF-based coloring
-/// effects and reduces computational complexity when speaker playback is
-/// active. By default the stereo speaker mode optimization is disabled.
-///
-/// @param api Pointer to a gvr_audio_context.
-/// @param enable True to enable the stereo speaker mode.
-void gvr_audio_enable_stereo_speaker_mode(gvr_audio_context* api, bool enable);
-
-/// @}
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-// Convenience C++ wrapper.
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#include <memory>
-#include <string>
-
-namespace gvr {
-/// This is a convenience C++ wrapper for the Audio C API.
-///
-/// This wrapper strategy prevents ABI compatibility issues between compilers
-/// by ensuring that the interface between client code and the implementation
-/// code in libgvr.so is a pure C interface. The translation from C++ calls
-/// to C calls provided by this wrapper runs entirely in the client's binary
-/// and is compiled by the client's compiler.
-///
-/// Methods in this class are only documented insofar as the C++ wrapping logic
-/// is concerned; for information about the method itself, please refer to the
-/// corresponding function in the C API.
-///
-///
-/// THREADING: this class is thread-safe and reentrant after initialized
-/// with Init().
-class AudioApi {
- public:
-  /// Creates an (uninitialized) ControllerApi object. You must initialize
-  /// it by calling Init() before interacting with it.
-  AudioApi() : context_(nullptr) {}
-
-  ~AudioApi() {
-    if (context_) {
-      gvr_audio_destroy(&context_);
-    }
-  }
-
-/// Creates and initializes a gvr_audio_context.
-/// For more information, see gvr_audio_create().
-#ifdef __ANDROID__
-  bool Init(JNIEnv* env, jobject android_context, jobject class_loader,
-            AudioRenderingMode rendering_mode) {
-    context_ =
-        gvr_audio_create(env, android_context, class_loader, rendering_mode);
-    return context_ != nullptr;
-  }
-#else
-  bool Init(AudioRenderingMode rendering_mode) {
-    context_ = gvr_audio_create(rendering_mode);
-    return context_ != nullptr;
-  }
-#endif  // #ifdef __ANDROID__
-
-  /// Pauses the audio engine.
-  /// For more information, see gvr_audio_pause().
-  void Pause() { gvr_audio_pause(context_); }
-
-  /// Resumes the audio engine.
-  /// For more information, see gvr_audio_resume().
-  void Resume() { gvr_audio_resume(context_); }
-
-  /// For more information, see gvr_audio_update().
-  void Update() { gvr_audio_update(context_); }
-
-  /// Preloads a local sound file.
-  /// For more information, see gvr_audio_preload_soundfile().
-  bool PreloadSoundfile(const std::string& filename) {
-    return gvr_audio_preload_soundfile(context_, filename.c_str());
-  }
-
-  /// Unloads a previously preloaded sample from memory.
-  /// For more information, see gvr_audio_preload_soundfile().
-  void UnloadSoundfile(const std::string& filename) {
-    gvr_audio_unload_soundfile(context_, filename.c_str());
-  }
-
-  /// Returns a new sound object.
-  /// For more information, see gvr_audio_create_sound_object().
-  AudioSourceId CreateSoundObject(const std::string& filename) {
-    return gvr_audio_create_sound_object(context_, filename.c_str());
-  }
-
-  /// Returns a new sound field.
-  /// For more information, see gvr_audio_create_soundfield().
-  AudioSourceId CreateSoundfield(const std::string& filename) {
-    return gvr_audio_create_soundfield(context_, filename.c_str());
-  }
-
-  /// Returns a new stereo sound.
-  /// For more information, see gvr_audio_create_stereo_sound().
-  AudioSourceId CreateStereoSound(const std::string& filename) {
-    return gvr_audio_create_stereo_sound(context_, filename.c_str());
-  }
-
-  /// Starts the playback of a sound.
-  /// For more information, see gvr_audio_play_sound().
-  void PlaySound(AudioSourceId source_id, bool looping_enabled) {
-    gvr_audio_play_sound(context_, source_id, looping_enabled);
-  }
-
-  /// Pauses the playback of a sound.
-  /// For more information, see gvr_audio_pause_sound().
-  void PauseSound(AudioSourceId source_id) {
-    gvr_audio_pause_sound(context_, source_id);
-  }
-
-  /// Resumes the playback of a sound.
-  /// For more information, see gvr_audio_resume_sound().
-  void ResumeSound(AudioSourceId source_id) {
-    gvr_audio_resume_sound(context_, source_id);
-  }
-
-  /// Stops the playback of a sound.
-  /// For more information, see gvr_audio_stop_sound().
-  void StopSound(AudioSourceId source_id) {
-    gvr_audio_stop_sound(context_, source_id);
-  }
-
-  /// Checks if a sound is playing.
-  /// For more information, see gvr_audio_is_sound_playing().
-  bool IsSoundPlaying(AudioSourceId source_id) const {
-    return gvr_audio_is_sound_playing(context_, source_id);
-  }
-
-  /// Checks if a source is in a valid playable state.
-  /// For more information, see gvr_audio_is_source_id_valid().
-  bool IsSourceIdValid(AudioSourceId source_id) {
-    return gvr_audio_is_source_id_valid(context_, source_id);
-  }
-
-  /// Repositions an existing sound object.
-  /// For more information, see gvr_audio_set_sound_object_position().
-  void SetSoundObjectPosition(AudioSourceId sound_object_id, float x, float y,
-                              float z) {
-    gvr_audio_set_sound_object_position(context_, sound_object_id, x, y, z);
-  }
-
-  void SetSoundObjectDistanceRolloffModel(
-      AudioSourceId sound_object_id,
-      gvr_audio_distance_rolloff_type rolloff_model, float min_distance,
-      float max_distance) {
-    gvr_audio_set_sound_object_distance_rolloff_model(
-        context_, sound_object_id, rolloff_model, min_distance, max_distance);
-  }
-
-  /// Rotates an existing soundfield.
-  /// For more information, see gvr_audio_set_soundfield_rotation().
-  void SetSoundfieldRotation(AudioSourceId soundfield_id,
-                             const Quatf& soundfield_rotation) {
-    gvr_audio_set_soundfield_rotation(context_, soundfield_id,
-                                      soundfield_rotation);
-  }
-
-  /// Changes the master volume.
-  /// For more information, see gvr_audio_set_master_volume().
-  void SetMasterVolume(float volume) {
-    gvr_audio_set_master_volume(context_, volume);
-  }
-
-  /// Changes the volume of an existing sound.
-  /// For more information, see gvr_audio_set_sound_volume().
-  void SetSoundVolume(AudioSourceId source_id, float volume) {
-    gvr_audio_set_sound_volume(context_, source_id, volume);
-  }
-
-  /// Sets the head position from a matrix representation.
-  /// For more information, see gvr_audio_set_head_pose().
-  void SetHeadPose(const Mat4f& head_pose_matrix) {
-    gvr_audio_set_head_pose(context_, head_pose_matrix);
-  }
-
-  /// Turns on/off the room reverberation effect.
-  /// For more information, see gvr_audio_enable_room().
-  void EnableRoom(bool enable) { gvr_audio_enable_room(context_, enable); }
-
-  /// Sets the room properties describing the dimensions and surface materials
-  /// of a given room. For more information, see
-  /// gvr_audio_set_room_properties().
-  void SetRoomProperties(float size_x, float size_y, float size_z,
-                         gvr_audio_material_type wall_material,
-                         gvr_audio_material_type ceiling_material,
-                         gvr_audio_material_type floor_material) {
-    gvr_audio_set_room_properties(context_, size_x, size_y, size_z,
-                                  wall_material, ceiling_material,
-                                  floor_material);
-  }
-
-  /// Adjusts the properties of the current reverb, allowing changes to the
-  /// reverb's gain, duration and low/high frequency balance. For more
-  /// information see gvr_audio_set_room_reverb_adjustments().
-  void SetRoomReverbAdjustments(float gain, float time_adjust,
-                                float brightness_adjust) {
-    gvr_audio_set_room_reverb_adjustments(context_, gain, time_adjust,
-                                          brightness_adjust);
-  }
-
-  /// Enables the stereo speaker mode. For more information see
-  /// gvr_audio_enable_stereo_speaker_mode().
-  void EnableStereoSpeakerMode(bool enable) {
-    gvr_audio_enable_stereo_speaker_mode(context_, enable);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit AudioApi(gvr_audio_context* context) : context_(context) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_audio_context* cobj() { return context_; }
-  const gvr_audio_context* cobj() const { return context_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_audio_context* Release() {
-    auto result = context_;
-    context_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  gvr_audio_context* context_;
-
-  // Disallow copy and assign:
-  AudioApi(const AudioApi&);
-  void operator=(const AudioApi&);
-};
-
-}  // namespace gvr
-#endif  // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_AUDIO_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h
deleted file mode 100644
index 8347393..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_controller.h
+++ /dev/null
@@ -1,793 +0,0 @@
-/* Copyright 2016 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_
-
-#ifdef __ANDROID__
-#include <jni.h>
-#endif
-
-#include <stdint.h>
-
-#include "vr/gvr/capi/include/gvr.h"
-#include "vr/gvr/capi/include/gvr_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/// @defgroup Controller Controller API
-/// @brief This is the Controller C API, which allows access to a VR controller.
-///
-/// If you are writing C++ code, you might prefer to use the C++ wrapper rather
-/// than implement this C API directly.
-///
-/// Typical initialization example:
-///
-///     // Get your gvr_context* pointer from GvrLayout:
-///     gvr_context* gvr = ......;  // (get from GvrLayout in Java)
-///
-///     // Set up the API features:
-///     int32_t options = gvr_controller_get_default_options();
-///
-///     // Enable non-default options, if needed:
-///     options |= GVR_CONTROLLER_ENABLE_GYRO | GVR_CONTROLLER_ENABLE_ACCEL;
-///
-///     // Create and init:
-///     gvr_controller_context* context =
-///         gvr_controller_create_and_init(options, gvr);
-///
-///     // Check if init was successful.
-///     if (!context) {
-///       // Handle error.
-///       return;
-///     }
-///
-///     gvr_controller_state* state = gvr_controller_state_create();
-///
-///     // Resume:
-///     gvr_controller_resume(api);
-///
-/// Usage:
-///
-///     void DrawFrame() {
-///       gvr_controller_state_update(context, 0, state);
-///       // ... process controller state ...
-///     }
-///
-///     // When your application gets paused:
-///     void OnPause() {
-///       gvr_controller_pause(context);
-///     }
-///
-///     // When your application gets resumed:
-///     void OnResume() {
-///       gvr_controller_resume(context);
-///     }
-///
-/// To conserve battery, be sure to call gvr_controller_pause and
-/// gvr_controller_resume when your app gets paused and resumed, respectively.
-///
-/// THREADING: unless otherwise noted, all functions are thread-safe, so
-/// you can operate on the same gvr_controller_context object from multiple
-/// threads.
-/// @{
-
-/// Represents a Daydream Controller API object, used to invoke the
-/// Daydream Controller API.
-typedef struct gvr_controller_context_ gvr_controller_context;
-
-/// Returns the default features for the controller API.
-///
-/// @return The set of default features, as bit flags (an OR'ed combination of
-///     the GVR_CONTROLLER_ENABLE_* feature flags).
-int32_t gvr_controller_get_default_options();
-
-/// Creates and initializes a gvr_controller_context instance which can be used
-/// to invoke the Daydream Controller API functions. Important: after creation
-/// the API will be in the paused state (the controller will be inactive).
-/// You must call gvr_controller_resume() explicitly (typically, in your Android
-/// app's onResume() callback).
-///
-/// @param options The API options. To get the defaults, use
-///     gvr_controller_get_default_options().
-/// @param context The GVR Context object to sync with (optional).
-///     This can be nullptr. If provided, the context's state will
-///     be synchronized with the controller's state where possible. For
-///     example, when the user recenters the controller, this will
-///     automatically recenter head tracking as well.
-///     WARNING: the caller is responsible for making sure the pointer
-///     remains valid for the lifetime of this object.
-/// @return A pointer to the initialized API, or NULL if an error occurs.
-gvr_controller_context* gvr_controller_create_and_init(
-    int32_t options, gvr_context* context);
-
-#ifdef __ANDROID__
-/// Creates and initializes a gvr_controller_context instance with an explicit
-/// Android context and class loader.
-///
-/// @param env The JNI Env associated with the current thread.
-/// @param android_context The Android application context. This must be the
-///     application context, NOT an Activity context (Note: from any Android
-///     Activity in your app, you can call getApplicationContext() to
-///     retrieve the application context).
-/// @param class_loader The class loader to use when loading Java
-///     classes. This must be your app's main class loader (usually
-///     accessible through activity.getClassLoader() on any of your Activities).
-/// @param options The API options. To get the defaults, use
-///     gvr_controller_get_default_options().
-/// @param context The GVR Context object to sync with (optional).
-///     This can be nullptr. If provided, the context's state will
-///     be synchronized with the controller's state where possible. For
-///     example, when the user recenters the controller, this will
-///     automatically recenter head tracking as well.
-///     WARNING: the caller is responsible for making sure the pointer
-///     remains valid for the lifetime of this object.
-/// @return A pointer to the initialized API, or NULL if an error occurs.
-gvr_controller_context* gvr_controller_create_and_init_android(
-    JNIEnv *env, jobject android_context, jobject class_loader,
-    int32_t options, gvr_context* context);
-#endif  // #ifdef __ANDROID__
-
-/// Destroys a gvr_controller_context that was previously created with
-/// gvr_controller_init.
-///
-/// @param api Pointer to a pointer to a gvr_controller_context. The pointer
-///     will be set to NULL after destruction.
-void gvr_controller_destroy(gvr_controller_context** api);
-
-/// Pauses the controller, possibly releasing resources.
-/// Call this when your app/game loses focus.
-/// Calling this when already paused is a no-op.
-/// Thread-safe (call from any thread).
-///
-/// @param api Pointer to a pointer to a gvr_controller_context.
-void gvr_controller_pause(gvr_controller_context* api);
-
-/// Resumes the controller. Call this when your app/game regains focus.
-/// Calling this when already resumed is a no-op.
-/// Thread-safe (call from any thread).
-///
-/// @param api Pointer to a pointer to a gvr_controller_context.
-void gvr_controller_resume(gvr_controller_context* api);
-
-/// Convenience to convert an API status code to string. The returned pointer
-/// is static and valid throughout the lifetime of the application.
-///
-/// @param status The gvr_controller_api_status to convert to string.
-/// @return A pointer to a string that describes the value.
-const char* gvr_controller_api_status_to_string(int32_t status);
-
-/// Convenience to convert an connection state to string. The returned pointer
-/// is static and valid throughout the lifetime of the application.
-///
-/// @param state The state to convert to string.
-/// @return A pointer to a string that describes the value.
-const char* gvr_controller_connection_state_to_string(int32_t state);
-
-/// Convenience to convert an connection state to string. The returned pointer
-/// is static and valid throughout the lifetime of the application.
-///
-/// @param button The gvr_controller_button to convert to string.
-/// @return A pointer to a string that describes the value.
-const char* gvr_controller_button_to_string(int32_t button);
-
-/// Creates a gvr_controller_state.
-gvr_controller_state* gvr_controller_state_create();
-
-/// Destroys a a gvr_controller_state that was previously created with
-/// gvr_controller_state_create.
-void gvr_controller_state_destroy(gvr_controller_state** state);
-
-/// Updates the controller state. Reading the controller state is not a
-/// const getter: it has side-effects. In particular, some of the
-/// gvr_controller_state fields (the ones documented as "transient") represent
-/// one-time events and will be true for only one read operation, and false
-/// in subsequente reads.
-///
-/// @param api Pointer to a pointer to a gvr_controller_context.
-/// @param flags Optional flags reserved for future use. A value of 0 should be
-///     used until corresponding flag attributes are defined and documented.
-/// @param out_state A pointer where the controller's state
-///     is to be written. This must have been allocated with
-///     gvr_controller_state_create().
-void gvr_controller_state_update(gvr_controller_context* api, int32_t flags,
-                                 gvr_controller_state* out_state);
-
-/// Gets the API status of the controller state. Returns one of the
-/// gvr_controller_api_status variants, but returned as an int32_t for ABI
-/// compatibility.
-int32_t gvr_controller_state_get_api_status(const gvr_controller_state* state);
-
-/// Gets the connection state of the controller. Returns one of the
-/// gvr_controller_connection_state variants, but returned as an int32_t for ABI
-/// compatibility.
-int32_t gvr_controller_state_get_connection_state(
-    const gvr_controller_state* state);
-
-/// Returns the current controller orientation, in Start Space. The Start Space
-/// is the same space as the headset space and has these three axes
-/// (right-handed):
-///
-/// * The positive X axis points to the right.
-/// * The positive Y axis points upwards.
-/// * The positive Z axis points backwards.
-///
-/// The definition of "backwards" and "to the right" are based on the position
-/// of the controller when tracking started. For Daydream, this is when the
-/// controller was first connected in the "Connect your Controller" screen
-/// which is shown when the user enters VR.
-///
-/// The definition of "upwards" is given by gravity (away from the pull of
-/// gravity). This API may not work in environments without gravity, such
-/// as space stations or near the center of the Earth.
-///
-/// Since the coordinate system is right-handed, rotations are given by the
-/// right-hand rule. For example, rotating the controller counter-clockwise
-/// on a table top as seen from above means a positive rotation about the
-/// Y axis, while clockwise would mean negative.
-///
-/// Note that this is the Start Space for the *controller*, which initially
-/// coincides with the Start Space for the headset, but they may diverge over
-/// time due to controller/headset drift. A recentering operation will bring
-/// the two spaces back into sync.
-///
-/// Remember that a quaternion expresses a rotation. Given a rotation of theta
-/// radians about the (x, y, z) axis, the corresponding quaternion (in
-/// xyzw order) is:
-///
-///     (x * sin(theta/2), y * sin(theta/2), z * sin(theta/2), cos(theta/2))
-///
-/// Here are some examples of orientations of the controller and their
-/// corresponding quaternions, all given in xyzw order:
-///
-///   * Initial pose, pointing forward and lying flat on a surface: identity
-///     quaternion (0, 0, 0, 1). Corresponds to "no rotation".
-///
-///   * Flat on table, rotated 90 degrees counter-clockwise: (0, 0.7071, 0,
-///     0.7071). Corresponds to a +90 degree rotation about the Y axis.
-///
-///   * Flat on table, rotated 90 degrees clockwise: (0, -0.7071, 0, 0.7071).
-///     Corresponds to a -90 degree rotation about the Y axis.
-///
-///   * Flat on table, rotated 180 degrees (pointing backwards): (0, 1, 0, 0).
-///     Corresponds to a 180 degree rotation about the Y axis.
-///
-///   * Pointing straight up towards the sky: (0.7071, 0, 0, 0.7071).
-///     Corresponds to a +90 degree rotation about the X axis.
-///
-///   * Pointing straight down towards the ground: (-0.7071, 0, 0, 0.7071).
-///     Corresponds to a -90 degree rotation about the X axis.
-///
-///   * Banked 90 degrees to the left: (0, 0, 0.7071, 0.7071). Corresponds
-///     to a +90 degree rotation about the Z axis.
-///
-///   * Banked 90 degrees to the right: (0, 0, -0.7071, 0.7071). Corresponds
-///     to a -90 degree rotation about the Z axis.
-gvr_quatf gvr_controller_state_get_orientation(
-    const gvr_controller_state* state);
-
-/// Returns the current controller gyro reading, in Start Space.
-///
-/// The gyro measures the controller's angular speed in radians per second.
-/// Note that this is an angular *speed*, so it reflects how fast the
-/// controller's orientation is changing with time.
-/// In particular, if the controller is not being rotated, the angular speed
-/// will be zero on all axes, regardless of the current pose.
-///
-/// The axes are in the controller's device space. Specifically:
-///
-///    * The X axis points to the right of the controller.
-///    * The Y axis points upwards perpendicular to the top surface of the
-///      controller.
-///    * The Z axis points backwards along the body of the controller,
-///      towards its rear, where the charging port is.
-///
-/// As usual in a right-handed coordinate system, the sign of the angular
-/// velocity is given by the right-hand rule. So, for example:
-///
-///    * If the controller is flat on a table top spinning counter-clockwise
-///      as seen from above, you will read a positive angular velocity
-///      about the Y axis. Clockwise would be negative.
-///    * If the controller is initially pointing forward and lying flat and
-///      is then gradually angled up so that its tip points towards the sky,
-///      it will report a positive angular velocity about the X axis during
-///      that motion. Likewise, angling it down will report a negative angular
-///      velocity about the X axis.
-///    * If the controller is banked (rolled) to the right, this will
-///      report a negative angular velocity about the Z axis during the
-///      motion (remember the Z axis points backwards along the controller).
-///      Banking to the left will report a positive angular velocity about
-///      the Z axis.
-gvr_vec3f gvr_controller_state_get_gyro(const gvr_controller_state* state);
-
-/// Current (latest) controller accelerometer reading, in Start Space.
-///
-/// The accelerometer indicates the direction in which the controller feels
-/// an acceleration, including gravity. The reading is given in meters
-/// per second squared (m/s^2). The axes are the same as for the gyro.
-/// To have an intuition for the signs used in the accelerometer, it is useful
-/// to imagine that, when at rest, the controller is being "pushed" by a
-/// force opposite to gravity. It is as if, by the equivalency princle, it were
-/// on a frame of reference that is accelerating in the opposite direction to
-/// gravity. For example:
-///
-///   * If the controller is lying flat on a table top, it will read a positive
-///     acceleration of about 9.8 m/s^2 along the Y axis, corresponding to
-///     the acceleration of gravity (as if the table were pushing the controller
-///     upwards at 9.8 m/s^2 to counteract gravity).
-///   * If, in that situation, the controller is now accelerated upwards at
-///     3.0 m/s^2, then the reading will be 12.8 m/s^2 along the Y axis,
-///     since the controller will now feel a stronger acceleration corresponding
-///     to the 9.8 m/s^2 plus the upwards push of 3.0 m/s^2.
-///   * If, the controller is accelerated downwards at 5.0 m/s^2, then the
-///     reading will now be 4.8 m/s^2 along the Y axis, since the controller
-///     will now feel a weaker acceleration (as the acceleration is giving in
-///     to gravity).
-///   * If you were to give in to gravity completely, letting the controller
-///     free fall towards the ground, it will read 0 on all axes, as there
-///     will be no force acting on the controller. (Please do not put your
-///     controller in a free-fall situation. This is just a theoretical
-///     example.)
-gvr_vec3f gvr_controller_state_get_accel(const gvr_controller_state* state);
-
-/// Returns whether the user is touching the touchpad.
-bool gvr_controller_state_is_touching(const gvr_controller_state* state);
-
-/// If the user is touching the touchpad, this returns the touch position in
-/// normalized coordinates, where (0,0) is the top-left of the touchpad
-/// and (1,1) is the bottom right. If the user is not touching the touchpad,
-/// then this is the position of the last touch.
-gvr_vec2f gvr_controller_state_get_touch_pos(const gvr_controller_state* state);
-
-/// Returns true if user just started touching touchpad (this is a transient
-/// event:
-/// it is true for only one frame after the event).
-bool gvr_controller_state_get_touch_down(const gvr_controller_state* state);
-
-/// Returns true if user just stopped touching touchpad (this is a transient
-/// event:
-/// it is true for only one frame after the event).
-bool gvr_controller_state_get_touch_up(const gvr_controller_state* state);
-
-/// Returns true if a recenter operation just ended (this is a transient event:
-/// it is true only for one frame after the recenter ended). If this is
-/// true then the `orientation` field is already relative to the new center.
-bool gvr_controller_state_get_recentered(const gvr_controller_state* state);
-
-/// Returns whether the recenter flow is currently in progress.
-///
-/// @deprecated Use gvr_controller_state_get_recentered instead.
-bool gvr_controller_state_get_recentering(const gvr_controller_state* state);
-
-/// Returns whether the given button is currently pressed.
-bool gvr_controller_state_get_button_state(const gvr_controller_state* state,
-
-                                           int32_t button);
-
-/// Returns whether the given button was just pressed (transient).
-bool gvr_controller_state_get_button_down(const gvr_controller_state* state,
-                                          int32_t button);
-
-/// Returns whether the given button was just released (transient).
-bool gvr_controller_state_get_button_up(const gvr_controller_state* state,
-                                        int32_t button);
-
-/// Returns the timestamp (nanos) when the last orientation event was received.
-int64_t gvr_controller_state_get_last_orientation_timestamp(
-    const gvr_controller_state* state);
-
-/// Returns the timestamp (nanos) when the last gyro event was received.
-int64_t gvr_controller_state_get_last_gyro_timestamp(
-    const gvr_controller_state* state);
-
-/// Returns the timestamp (nanos) when the last accelerometer event was
-/// received.
-int64_t gvr_controller_state_get_last_accel_timestamp(
-    const gvr_controller_state* state);
-
-/// Returns the timestamp (nanos) when the last touch event was received.
-int64_t gvr_controller_state_get_last_touch_timestamp(
-    const gvr_controller_state* state);
-
-/// Returns the timestamp (nanos) when the last button event was received.
-int64_t gvr_controller_state_get_last_button_timestamp(
-    const gvr_controller_state* state);
-
-// Current (latest) controller simulated position for use with an elbow model.
-gvr_vec3f gvr_controller_state_get_position(const gvr_controller_state* state);
-
-// Returns the timestamp (nanos) when the last position event was received.
-int64_t gvr_controller_state_get_last_position_timestamp(
-    const gvr_controller_state* state);
-
-/// Returns whether the controller battery is currently charging.
-/// This may not be real time information and may be slow to be updated.
-bool gvr_controller_state_get_battery_charging(
-    const gvr_controller_state* state);
-
-/// Returns the bucketed controller battery level.
-/// Note this is a gvr_controller_battery_level and not a percent.
-int32_t gvr_controller_state_get_battery_level(
-    const gvr_controller_state* state);
-
-/// Returns the timestamp (nanos) when the last battery event was received.
-int64_t gvr_controller_state_get_last_battery_timestamp(
-    const gvr_controller_state* state);
-
-/// Convenience to convert a battery level to string. The returned pointer
-/// is static and valid throughout the lifetime of the application.
-///
-/// @param level The gvr_controller_battery_level to convert to string.
-/// @return A pointer to a string that describes the value.
-const char* gvr_controller_battery_level_to_string(int32_t level);
-
-/// @}
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-
-// Convenience C++ wrapper.
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#include <memory>
-
-namespace gvr {
-/// This is a convenience C++ wrapper for the Controller C API.
-///
-/// This wrapper strategy prevents ABI compatibility issues between compilers
-/// by ensuring that the interface between client code and the implementation
-/// code in libgvr.so is a pure C interface. The translation from C++ calls
-/// to C calls provided by this wrapper runs entirely in the client's binary
-/// and is compiled by the client's compiler.
-///
-/// Methods in this class are only documented insofar as the C++ wrapping logic
-/// is concerned; for information about the method itself, please refer to the
-/// corresponding function in the C API.
-///
-/// Typical C++ initialization example:
-///
-///     std::unique_ptr<ControllerApi> controller_api(new ControllerApi);
-///
-///     // Your GVR context pointer (which can be obtained from GvrLayout)
-///     gvr_context* context = .....;  // (get it from GvrLayout)
-///
-///     // Set up the options:
-///     int32_t options = ControllerApi::DefaultOptions();
-///
-///     // Enable non-default options, if you need them:
-///     options |= GVR_CONTROLLER_ENABLE_GYRO;
-///
-///     // Init the ControllerApi object:
-///     bool success = controller_api->Init(options, context);
-///     if (!success) {
-///       // Handle failure.
-///       // Do NOT call other methods (like Resume, etc) if init failed.
-///       return;
-///     }
-///
-///     // Resume the ControllerApi (if your app is on the foreground).
-///     controller_api->Resume();
-///
-///     ControllerState state;
-///
-/// Usage example:
-///
-///     void DrawFrame() {
-///       state.Update(*controller_api);
-///       // ... process controller state ...
-///     }
-///
-///     // When your application gets paused:
-///     void OnPause() {
-///       controller_api->Pause();
-///     }
-///
-///     // When your application gets resumed:
-///     void OnResume() {
-///       controller_api->Resume();
-///     }
-///
-/// To conserve battery, be sure to call Pause() and Resume() when your app
-/// gets paused and resumed, respectively. This will allow the underlying
-/// logic to unbind from the VR service and let the controller sleep when
-/// no apps are using it.
-///
-/// THREADING: this class is thread-safe and reentrant after initialized
-/// with Init().
-class ControllerApi {
- public:
-  /// Creates an (uninitialized) ControllerApi object. You must initialize
-  /// it by calling Init() before interacting with it.
-  ControllerApi() : context_(nullptr) {}
-
-  /// Returns the default controller options.
-  static int32_t DefaultOptions() {
-    return gvr_controller_get_default_options();
-  }
-
-  // Deprecated factory-style create method.
-  // TODO(btco): remove this once no one is using it.
-  static std::unique_ptr<ControllerApi> Create() {
-    return std::unique_ptr<ControllerApi>(new ControllerApi);
-  }
-
-  /// Initializes the controller API.
-  ///
-  /// This method must be called exactly once in the lifetime of this object.
-  /// Other methods in this class may only be called after Init() returns true.
-  /// Note: this does not cause the ControllerApi to be resumed. You must call
-  /// Resume() explicitly in order to start using the controller.
-  ///
-  /// For more information see gvr_controller_create_and_init().
-  ///
-  /// @return True if initialization was successful, false if it failed.
-  ///     Initialization may fail, for example, because invalid options were
-  ///     supplied.
-  bool Init(int32_t options, gvr_context* context) {
-    context_ = gvr_controller_create_and_init(options, context);
-    return context_ != nullptr;
-  }
-
-#ifdef __ANDROID__
-  /// Overload of Init() with explicit Android context and class loader
-  /// (for Android only). For more information, see:
-  /// gvr_controller_create_and_init_android().
-  bool Init(JNIEnv *env, jobject android_context, jobject class_loader,
-            int32_t options, gvr_context* context) {
-    context_ = gvr_controller_create_and_init_android(
-        env, android_context, class_loader, options, context);
-    return context_ != nullptr;
-  }
-#endif  // #ifdef __ANDROID__
-
-  /// Convenience overload that calls Init without a gvr_context.
-  // TODO(btco): remove once it is no longer being used.
-  bool Init(int32_t options) {
-    return Init(options, nullptr);
-  }
-
-  /// Pauses the controller.
-  /// For more information, see gvr_controller_pause().
-  void Pause() {
-    gvr_controller_pause(context_);
-  }
-
-  /// Resumes the controller.
-  /// For more information, see gvr_controller_resume().
-  void Resume() {
-    gvr_controller_resume(context_);
-  }
-
-  /// Destroys this ControllerApi instance.
-  ~ControllerApi() {
-    if (context_) gvr_controller_destroy(&context_);
-  }
-
-  /// Convenience functions to convert enums to strings.
-  /// For more information, see the corresponding functions in the C API.
-  static const char* ToString(ControllerApiStatus status) {
-    return gvr_controller_api_status_to_string(status);
-  }
-
-  static const char* ToString(ControllerConnectionState state) {
-    return gvr_controller_connection_state_to_string(state);
-  }
-
-  static const char* ToString(ControllerButton button) {
-    return gvr_controller_button_to_string(button);
-  }
-
-  static const char* ToString(ControllerBatteryLevel level) {
-    return gvr_controller_battery_level_to_string(level);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit ControllerApi(gvr_controller_context* context)
-      : context_(context) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_controller_context* cobj() { return context_; }
-  const gvr_controller_context* cobj() const { return context_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_controller_context* release() {
-    auto result = context_;
-    context_ = nullptr;
-    return result;
-  }
-  /// @}
-
- protected:
-  gvr_controller_context* context_;
-
- private:
-  friend class ControllerState;
-
-  // Disallow copy and assign:
-  ControllerApi(const ControllerApi&);
-  void operator=(const ControllerApi&);
-};
-
-/// Convenience C++ wrapper for the opaque gvr_controller_state type. See the
-/// gvr_controller_state functions for more information.
-class ControllerState {
- public:
-  ControllerState() : state_(gvr_controller_state_create()) {}
-
-  ~ControllerState() {
-    if (state_) gvr_controller_state_destroy(&state_);
-  }
-
-  /// For more information, see gvr_controller_state_update().
-  void Update(const ControllerApi& api) {
-    gvr_controller_state_update(api.context_, 0, state_);
-  }
-
-  /// For more information, see gvr_controller_state_update().
-  void Update(const ControllerApi& api, int32_t flags) {
-    gvr_controller_state_update(api.context_, flags, state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_api_status().
-  ControllerApiStatus GetApiStatus() const {
-    return static_cast<ControllerApiStatus>(
-        gvr_controller_state_get_api_status(state_));
-  }
-
-  /// For more information, see gvr_controller_state_get_connection_state().
-  ControllerConnectionState GetConnectionState() const {
-    return static_cast<ControllerConnectionState>(
-        gvr_controller_state_get_connection_state(state_));
-  }
-
-  /// For more information, see gvr_controller_state_get_orientation().
-  gvr_quatf GetOrientation() const {
-    return gvr_controller_state_get_orientation(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_gyro().
-  gvr_vec3f GetGyro() const { return gvr_controller_state_get_gyro(state_); }
-
-  /// For more information, see gvr_controller_state_get_accel().
-  gvr_vec3f GetAccel() const { return gvr_controller_state_get_accel(state_); }
-
-  /// For more information, see gvr_controller_state_is_touching().
-  bool IsTouching() const { return gvr_controller_state_is_touching(state_); }
-
-  /// For more information, see gvr_controller_state_get_touch_pos().
-  gvr_vec2f GetTouchPos() const {
-    return gvr_controller_state_get_touch_pos(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_touch_down().
-  bool GetTouchDown() const {
-    return gvr_controller_state_get_touch_down(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_touch_up().
-  bool GetTouchUp() const { return gvr_controller_state_get_touch_up(state_); }
-
-  /// For more information, see gvr_controller_state_get_recentered().
-  bool GetRecentered() const {
-    return gvr_controller_state_get_recentered(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_recentering().
-  bool GetRecentering() const {
-    return gvr_controller_state_get_recentering(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_button_state().
-  bool GetButtonState(ControllerButton button) const {
-    return gvr_controller_state_get_button_state(state_, button);
-  }
-
-  /// For more information, see gvr_controller_state_get_button_down().
-  bool GetButtonDown(ControllerButton button) const {
-    return gvr_controller_state_get_button_down(state_, button);
-  }
-
-  /// For more information, see gvr_controller_state_get_button_up().
-  bool GetButtonUp(ControllerButton button) const {
-    return gvr_controller_state_get_button_up(state_, button);
-  }
-
-  /// For more information, see
-  /// gvr_controller_state_get_last_orientation_timestamp().
-  int64_t GetLastOrientationTimestamp() const {
-    return gvr_controller_state_get_last_orientation_timestamp(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_last_gyro_timestamp().
-  int64_t GetLastGyroTimestamp() const {
-    return gvr_controller_state_get_last_gyro_timestamp(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_last_accel_timestamp().
-  int64_t GetLastAccelTimestamp() const {
-    return gvr_controller_state_get_last_accel_timestamp(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_last_touch_timestamp().
-  int64_t GetLastTouchTimestamp() const {
-    return gvr_controller_state_get_last_touch_timestamp(state_);
-  }
-
-  /// For more information, see
-  /// gvr_controller_state_get_last_button_timestamp().
-  int64_t GetLastButtonTimestamp() const {
-    return gvr_controller_state_get_last_button_timestamp(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_position().
-  gvr_vec3f GetPosition() const {
-    return gvr_controller_state_get_position(state_);
-  }
-
-  /// For more information, see
-  /// gvr_controller_state_get_last_position_timestamp().
-  int64_t GetLastPositionTimestamp() const {
-    return gvr_controller_state_get_last_position_timestamp(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_battery_charging
-  bool GetBatteryCharging() const {
-    return gvr_controller_state_get_battery_charging(state_);
-  }
-
-  /// For more information, see gvr_controller_state_get_battery_level
-  ControllerBatteryLevel GetBatteryLevel() const {
-    return static_cast<ControllerBatteryLevel>(
-        gvr_controller_state_get_battery_level(state_));
-  }
-
-  /// For more information, see gvr_controller_state_get_last_battery_timestamp
-  int64_t GetLastBatteryTimestamp() const {
-    return gvr_controller_state_get_last_battery_timestamp(state_);
-  }
-
-  /// @name Wrapper manipulation
-  /// @{
-  /// Creates a C++ wrapper for a C object and takes ownership.
-  explicit ControllerState(gvr_controller_state* state) : state_(state) {}
-
-  /// Returns the wrapped C object. Does not affect ownership.
-  gvr_controller_state* cobj() { return state_; }
-  const gvr_controller_state* cobj() const { return state_; }
-
-  /// Returns the wrapped C object and transfers its ownership to the caller.
-  /// The wrapper becomes invalid and should not be used.
-  gvr_controller_state* release() {
-    auto result = state_;
-    state_ = nullptr;
-    return result;
-  }
-  /// @}
-
- private:
-  gvr_controller_state* state_;
-};
-
-}  // namespace gvr
-#endif  // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_CONTROLLER_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h
deleted file mode 100644
index cf81b51..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/include/gvr_types.h
+++ /dev/null
@@ -1,658 +0,0 @@
-/* Copyright 2016 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_
-#define VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/// @defgroup types Google VR Types
-/// @brief Various types used in the Google VR NDK.
-/// @{
-
-/// Primary context for invoking Google VR APIs.
-typedef struct gvr_context_ gvr_context;
-
-/// An enum for the left and right eye.
-typedef enum {
-  GVR_LEFT_EYE = 0,
-  GVR_RIGHT_EYE,
-  GVR_NUM_EYES
-} gvr_eye;
-
-/// The type of VR viewer.
-typedef enum {
-  /// A Cardboard-compatible viewer. A typical Cardboard viewer supports a
-  /// simple touchscreen-based trigger input mechanism. On most platforms, this
-  // is the default viewer type if no viewer has been explicitly paired.
-  GVR_VIEWER_TYPE_CARDBOARD = 0,
-  /// A Daydream-compatible viewer. A typical Daydream viewer supports 3DOF
-  /// controller input (as defined in gvr_controller.h), and is intended only
-  /// for Daydream-ready platforms. It does *not* support touchscreen-based
-  /// input unless Cardboard emulation is explicitly enabled.
-  GVR_VIEWER_TYPE_DAYDREAM = 1,
-} gvr_viewer_type;
-
-// Types of VR-specific features which may or may not be supported on the
-// underlying platform.
-typedef enum {
-  // Asynchronous reprojection warps the app's rendered frame using the most
-  // recent head pose just before pushing the frame to the display.
-  GVR_FEATURE_ASYNC_REPROJECTION = 0,
-} gvr_feature;
-
-/// @}
-
-/// Version information for the Google VR API.
-typedef struct gvr_version_ {
-  int32_t major;
-  int32_t minor;
-  int32_t patch;
-} gvr_version;
-
-/// An integral 2D size. Used for render target sizes.
-typedef struct gvr_sizei {
-  int32_t width;
-  int32_t height;
-} gvr_sizei;
-
-/// An integral 2D rect. Used for window bounds in pixels.
-typedef struct gvr_recti {
-  int32_t left;
-  int32_t right;
-  int32_t bottom;
-  int32_t top;
-} gvr_recti;
-
-/// A floating point 2D rect. Used for field of view, and also for ranges
-/// in texture space. When used for a field of view, all angles are in positive
-/// degrees from the optical axis.
-typedef struct gvr_rectf {
-  float left;
-  float right;
-  float bottom;
-  float top;
-} gvr_rectf;
-
-/// A floating point 2D vector.
-typedef struct gvr_vec2f {
-  float x;
-  float y;
-} gvr_vec2f;
-
-/// A floating point 3D vector.
-typedef struct gvr_vec3f {
-  float x;
-  float y;
-  float z;
-} gvr_vec3f;
-
-/// A floating point 4x4 matrix.
-typedef struct gvr_mat4f { float m[4][4]; } gvr_mat4f;
-
-/// A floating point quaternion, in JPL format.
-/// We use this simple struct in order not to impose a dependency on a
-/// particular math library. The user of this API is free to encapsulate this
-/// into any math library they want.
-typedef struct gvr_quatf {
-  /// qx, qy, qz are the vector component.
-  float qx;
-  float qy;
-  float qz;
-  /// qw is the linelar component.
-  float qw;
-} gvr_quatf;
-
-/// A *monotonic system time* representation. On Android, this is equivalent to
-/// System.nanoTime(), or clock_gettime(CLOCK_MONOTONIC). If there is any doubt
-/// about how to get the current time for the current platform, simply use
-/// gvr_get_time_point_now().
-typedef struct gvr_clock_time_point {
-  int64_t monotonic_system_time_nanos;
-} gvr_clock_time_point;
-
-/// A structure that ties together a region of a buffer, the field of view
-/// rendered into that region and a target eye index to define part of the
-/// user's field of view. The SDK implementation uses this information to
-/// transform the images generated by the app output into the final display that
-/// is sent to the screen.
-///
-/// A set of these structures will most often be generated by the API, via
-/// gvr_get_recommended_buffer_viewports() or
-/// gvr_get_screen_buffer_viewports(). However, the client may also customize
-/// these values via gvr_buffer_viewport_list_set(), constructing a custom
-/// gvr_buffer_viewport_list for use in the distortion pass.
-typedef struct gvr_buffer_viewport_ gvr_buffer_viewport;
-
-/// List of buffer viewports that completely specifies how to transform the
-/// frame's buffers into the image displayed on the screen.
-typedef struct gvr_buffer_viewport_list_ gvr_buffer_viewport_list;
-
-/// Specification of a pixel buffer. A pixel buffer can have color, depth and
-/// stencil attachments and mostly corresponds to the OpenGL concept of a
-/// framebuffer object. However, since there can be multiple such objects for
-/// each frame, we avoid calling them "framebuffers". Pixel buffers which are
-/// part of the currently acquired frame are immutable, i.e., they cannot be
-/// resized or otherwise reconfigured.
-typedef struct gvr_buffer_spec_ gvr_buffer_spec;
-
-/// Swap chain that contains some number of frames. Frames in the swap chain
-/// can be unused, in the process of being distorted and presented on the
-/// screen, or acquired and being rendered to by the application. The swap chain
-/// ensures that the most recent available frame is always shown and that the
-/// application never has to wait to render the next frame.
-typedef struct gvr_swap_chain_ gvr_swap_chain;
-
-/// A single frame acquired from the swap chain. Each frame is composed of one
-/// or more buffers, which are then lens distorted and composited into the final
-/// output. Buffers are identified by indices that correspond to the position
-/// of their gvr_buffer_spec in the list passed when constructing the swap
-/// chain.
-typedef struct gvr_frame_ gvr_frame;
-
-/// @addtogroup types
-/// @{
-
-/// Constants that represent GVR error codes.
-typedef enum {
-  GVR_ERROR_NONE = 0,
-  GVR_ERROR_CONTROLLER_CREATE_FAILED = 2,
-  GVR_ERROR_NO_FRAME_AVAILABLE = 3,
-} gvr_error;
-
-/// Controller API options (bit flags).
-enum {
-  /// Indicates that controller orientation data should be reported.
-  GVR_CONTROLLER_ENABLE_ORIENTATION = 1 << 0,
-  /// Indicates that controller touchpad data should be reported.
-  GVR_CONTROLLER_ENABLE_TOUCH = 1 << 1,
-  /// Indicates that controller gyroscope data should be reported.
-  GVR_CONTROLLER_ENABLE_GYRO = 1 << 2,
-  /// Indicates that controller accelerometer data should be reported.
-  GVR_CONTROLLER_ENABLE_ACCEL = 1 << 3,
-  /// Indicates that controller gestures should be reported.
-  GVR_CONTROLLER_ENABLE_GESTURES = 1 << 4,
-  /// Indicates that controller pose prediction should be enabled.
-  GVR_CONTROLLER_ENABLE_POSE_PREDICTION = 1 << 5,
-  /// Indicates that controller position data should be reported.
-  GVR_CONTROLLER_ENABLE_POSITION = 1 << 6,
-  /// Indicates that controller battery data should be reported.
-  GVR_CONTROLLER_ENABLE_BATTERY = 1 << 7,
-};
-
-/// Constants that represent the status of the controller API.
-typedef enum {
-  /// API is happy and healthy. This doesn't mean the controller itself
-  /// is connected, it just means that the underlying service is working
-  /// properly.
-  GVR_CONTROLLER_API_OK = 0,
-
-  /// Any other status represents a permanent failure that requires
-  /// external action to fix:
-
-  /// API failed because this device does not support controllers (API is too
-  /// low, or other required feature not present).
-  GVR_CONTROLLER_API_UNSUPPORTED = 1,
-  /// This app was not authorized to use the service (e.g., missing permissions,
-  /// the app is blacklisted by the underlying service, etc).
-  GVR_CONTROLLER_API_NOT_AUTHORIZED = 2,
-  /// The underlying VR service is not present.
-  GVR_CONTROLLER_API_UNAVAILABLE = 3,
-  /// The underlying VR service is too old, needs upgrade.
-  GVR_CONTROLLER_API_SERVICE_OBSOLETE = 4,
-  /// The underlying VR service is too new, is incompatible with current client.
-  GVR_CONTROLLER_API_CLIENT_OBSOLETE = 5,
-  /// The underlying VR service is malfunctioning. Try again later.
-  GVR_CONTROLLER_API_MALFUNCTION = 6,
-} gvr_controller_api_status;
-
-/// Constants that represent the state of the controller.
-typedef enum {
-  /// Controller is disconnected.
-  GVR_CONTROLLER_DISCONNECTED = 0,
-  /// Controller is scanning.
-  GVR_CONTROLLER_SCANNING = 1,
-  /// Controller is connecting.
-  GVR_CONTROLLER_CONNECTING = 2,
-  /// Controller is connected.
-  GVR_CONTROLLER_CONNECTED = 3,
-} gvr_controller_connection_state;
-
-/// Controller buttons.
-typedef enum {
-  GVR_CONTROLLER_BUTTON_NONE = 0,
-  GVR_CONTROLLER_BUTTON_CLICK = 1,  ///< Touchpad Click.
-  GVR_CONTROLLER_BUTTON_HOME = 2,
-  GVR_CONTROLLER_BUTTON_APP = 3,
-  GVR_CONTROLLER_BUTTON_VOLUME_UP = 4,
-  GVR_CONTROLLER_BUTTON_VOLUME_DOWN = 5,
-
-  /// Note: there are 5 buttons on the controller, but the state arrays have
-  /// this many elements due to the inclusion of a dummy "none" button.
-  GVR_CONTROLLER_BUTTON_COUNT = 6,
-} gvr_controller_button;
-
-/// Controller battery states.
-typedef enum {
-  GVR_CONTROLLER_BATTERY_LEVEL_UNKNOWN = 0,
-  GVR_CONTROLLER_BATTERY_LEVEL_CRITICAL_LOW = 1,
-  GVR_CONTROLLER_BATTERY_LEVEL_LOW = 2,
-  GVR_CONTROLLER_BATTERY_LEVEL_MEDIUM = 3,
-  GVR_CONTROLLER_BATTERY_LEVEL_ALMOST_FULL = 4,
-  GVR_CONTROLLER_BATTERY_LEVEL_FULL = 5,
-
-  /// Note: there are 5 distinct levels, but there are 6 due to the inclusion
-  /// of an UNKNOWN state before any battery information is collected, etc.
-  GVR_CONTROLLER_BATTERY_LEVEL_COUNT = 6,
-} gvr_controller_battery_level;
-
-
-/// @}
-
-/// Opaque handle to controller state.
-typedef struct gvr_controller_state_ gvr_controller_state;
-
-/// @addtogroup types
-/// @{
-
-/// Rendering modes define CPU load / rendering quality balances.
-typedef enum {
-  /// Stereo panning of all Sound Objects. This disables HRTF-based rendering.
-  GVR_AUDIO_RENDERING_STEREO_PANNING = 0,
-  /// HRTF-based rendering over a virtual array of 8 loudspeakers arranged in
-  /// a cube configuration around the listener’s head.
-  GVR_AUDIO_RENDERING_BINAURAL_LOW_QUALITY = 1,
-  /// HRTF-based rendering over a virtual array of 16 loudspeakers arranged in
-  /// an approximate equidistribution about the around the listener’s head.
-  GVR_AUDIO_RENDERING_BINAURAL_HIGH_QUALITY = 2,
-} gvr_audio_rendering_mode;
-
-/// Room surface material names, used to set room properties.
-typedef enum {
-  /// Acoustically transparent material, reflects no sound.
-  GVR_AUDIO_MATERIAL_TRANSPARENT = 0,
-  /// Acoustic ceiling tiles, absorbs most frequencies.
-  GVR_AUDIO_MATERIAL_ACOUSTIC_CEILING_TILES = 1,
-  /// Bare brick, relatively reflective.
-  GVR_AUDIO_MATERIAL_BRICK_BARE = 2,
-  /// Painted brick
-  GVR_AUDIO_MATERIAL_BRICK_PAINTED = 3,
-  /// Coarse surface concrete block.
-  GVR_AUDIO_MATERIAL_CONCRETE_BLOCK_COARSE = 4,
-  /// Painted concrete block.
-  GVR_AUDIO_MATERIAL_CONCRETE_BLOCK_PAINTED = 5,
-  /// Heavy curtains.
-  GVR_AUDIO_MATERIAL_CURTAIN_HEAVY = 6,
-  /// Fiber glass insulation.
-  GVR_AUDIO_MATERIAL_FIBER_GLASS_INSULATION = 7,
-  /// Thin glass.
-  GVR_AUDIO_MATERIAL_GLASS_THIN = 8,
-  /// Thick glass.
-  GVR_AUDIO_MATERIAL_GLASS_THICK = 9,
-  /// Grass.
-  GVR_AUDIO_MATERIAL_GRASS = 10,
-  /// Linoleum on concrete.
-  GVR_AUDIO_MATERIAL_LINOLEUM_ON_CONCRETE = 11,
-  /// Marble.
-  GVR_AUDIO_MATERIAL_MARBLE = 12,
-  /// Galvanized sheet metal.
-  GVR_AUDIO_MATERIAL_METAL = 13,
-  /// Wooden parquet on concrete.
-  GVR_AUDIO_MATERIAL_PARQUET_ON_CONCRETE = 14,
-  /// Rough plaster surface.
-  GVR_AUDIO_MATERIAL_PLASTER_ROUGH = 15,
-  /// Smooth plaster surface.
-  GVR_AUDIO_MATERIAL_PLASTER_SMOOTH = 16,
-  /// Plywood panel.
-  GVR_AUDIO_MATERIAL_PLYWOOD_PANEL = 17,
-  /// Polished concrete OR tile surface.
-  GVR_AUDIO_MATERIAL_POLISHED_CONCRETE_OR_TILE = 18,
-  /// Sheet rock.
-  GVR_AUDIO_MATERIAL_SHEET_ROCK = 19,
-  /// Surface of water or ice.
-  GVR_AUDIO_MATERIAL_WATER_OR_ICE_SURFACE = 20,
-  /// Wooden ceiling.
-  GVR_AUDIO_MATERIAL_WOOD_CEILING = 21,
-  /// Wood paneling.
-  GVR_AUDIO_MATERIAL_WOOD_PANEL = 22,
-} gvr_audio_material_type;
-
-/// Distance rolloff models used for distance attenuation.
-typedef enum {
-  /// Logarithmic distance rolloff model.
-  GVR_AUDIO_ROLLOFF_LOGARITHMIC = 0,
-  /// Linear distance rolloff model.
-  GVR_AUDIO_ROLLOFF_LINEAR = 1,
-  /// No distance attenuation will be applied.
-  GVR_AUDIO_ROLLOFF_NONE = 2,
-} gvr_audio_distance_rolloff_type;
-
-/// Sound object and sound field identifier.
-typedef int32_t gvr_audio_source_id;
-
-/// Supported surround sound formats.
-typedef enum {
-  // Enables to initialize a yet undefined rendering mode.
-  GVR_AUDIO_SURROUND_FORMAT_INVALID = 0,
-
-  // Virtual stereo speakers at -30 degrees and +30 degrees.
-  GVR_AUDIO_SURROUND_FORMAT_SURROUND_STEREO = 1,
-
-  // 5.1 surround sound according to the ITU-R BS 775 speaker configuration
-  // recommendation:
-  //   - Front left (FL) at 30 degrees.
-  //   - Front right (FR) at -30 degrees.
-  //   - Front center (FC) at 0 degrees.
-  //   - Low frequency effects (LFE) at front center at 0 degrees.
-  //   - Left side (LS) at 110 degrees.
-  //   - Right side (RS) at -110 degrees.
-  //
-  // The 5.1 channel input layout must matches AAC: FL, FR, FC, LFE, LS, RS.
-  // Note that this differs from the Vorbis/Opus 5.1 channel layout, which
-  // is: FL, FC, FR, LS, RS, LFE.
-  GVR_AUDIO_SURROUND_FORMAT_SURROUND_FIVE_DOT_ONE = 2,
-
-  // First-order ambisonics (AmbiX format: 4 channels, ACN channel ordering,
-  // SN3D normalization).
-  GVR_AUDIO_SURROUND_FORMAT_FIRST_ORDER_AMBISONICS = 3,
-
-  // Second-order ambisonics (AmbiX format: 9 channels, ACN channel ordering,
-  // SN3D normalization).
-  GVR_AUDIO_SURROUND_FORMAT_SECOND_ORDER_AMBISONICS = 4,
-
-  // Third-order ambisonics (AmbiX format: 16 channels, ACN channel ordering,
-  // SN3D normalization).
-  GVR_AUDIO_SURROUND_FORMAT_THIRD_ORDER_AMBISONICS = 5,
-} gvr_audio_surround_format_type;
-
-/// Valid color formats for swap chain buffers.
-typedef enum {
-  /// Equivalent to GL_RGBA8
-  GVR_COLOR_FORMAT_RGBA_8888 = 0,
-  /// Equivalent to GL_RGB565
-  GVR_COLOR_FORMAT_RGB_565 = 1,
-} gvr_color_format_type;
-
-typedef enum {
-  /// No depth or stencil buffer.
-  GVR_DEPTH_STENCIL_FORMAT_NONE = 255,
-  /// Equivalent to GL_DEPTH_COMPONENT16.
-  GVR_DEPTH_STENCIL_FORMAT_DEPTH_16 = 0,
-  /// Equivalent to GL_DEPTH_COMPONENT24.
-  GVR_DEPTH_STENCIL_FORMAT_DEPTH_24 = 1,
-  /// Equivlaent to GL_DEPTH24_STENCIL8.
-  GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8 = 2,
-  /// Equivalent to GL_DEPTH_COMPONENT32F.
-  GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F = 3,
-  /// Equivalent to GL_DEPTH_32F_STENCIL8.
-  GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8 = 4,
-  /// Equivalent to GL_STENCIL8.
-  GVR_DEPTH_STENCIL_FORMAT_STENCIL_8 = 5,
-} gvr_depth_stencil_format_type;
-
-/// Types of asynchronous reprojection.
-typedef enum {
-  /// Do not reproject.
-  GVR_REPROJECTION_NONE = 0,
-  /// Reproject in all dimensions.
-  GVR_REPROJECTION_FULL = 1,
-} gvr_reprojection;
-
-typedef enum {
-  GVR_CONTROLLER_RIGHT_HANDED = 0,
-  GVR_CONTROLLER_LEFT_HANDED = 1,
-} gvr_controller_handedness;
-
-typedef struct gvr_user_prefs_ gvr_user_prefs;
-
-// Anonymous enum for miscellaneous integer constants.
-enum {
-  /// Constant that represents a nonexistent external surface. Pass to
-  /// gvr_buffer_viewport_set_external_surface_id() to disable sampling from
-  /// an external surface.
-  GVR_EXTERNAL_SURFACE_ID_NONE = -1,
-  /// Special index for a source buffer that has the same contents as the
-  /// external surface attached to the given viewport. Pass this to
-  /// gvr_buffer_viewport_set_source_buffer_index() to use the external surface
-  /// as the buffer contents.
-  GVR_BUFFER_INDEX_EXTERNAL_SURFACE = -1,
-};
-
-/// @}
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-// These typedefs convert the C-style names to C++-style names.
-
-namespace gvr {
-
-const int32_t kControllerEnableOrientation =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_ORIENTATION);
-const int32_t kControllerEnableTouch =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_TOUCH);
-const int32_t kControllerEnableGyro =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_GYRO);
-const int32_t kControllerEnableAccel =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_ACCEL);
-const int32_t kControllerEnableGestures =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_GESTURES);
-const int32_t kControllerEnablePosePrediction =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_POSE_PREDICTION);
-const int32_t kControllerEnablePosition =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_POSITION);
-const int32_t kControllerEnableBattery =
-    static_cast<int32_t>(GVR_CONTROLLER_ENABLE_BATTERY);
-
-typedef gvr_controller_api_status ControllerApiStatus;
-const ControllerApiStatus kControllerApiOk =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_OK);
-const ControllerApiStatus kControllerApiUnsupported =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_UNSUPPORTED);
-const ControllerApiStatus kControllerApiNotAuthorized =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_NOT_AUTHORIZED);
-const ControllerApiStatus kControllerApiUnavailable =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_UNAVAILABLE);
-const ControllerApiStatus kControllerApiServiceObsolete =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_SERVICE_OBSOLETE);
-const ControllerApiStatus kControllerApiClientObsolete =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_CLIENT_OBSOLETE);
-const ControllerApiStatus kControllerApiMalfunction =
-    static_cast<ControllerApiStatus>(GVR_CONTROLLER_API_MALFUNCTION);
-
-typedef gvr_controller_connection_state ControllerConnectionState;
-const ControllerConnectionState kControllerDisconnected =
-    static_cast<ControllerConnectionState>(GVR_CONTROLLER_DISCONNECTED);
-const ControllerConnectionState kControllerScanning =
-    static_cast<ControllerConnectionState>(GVR_CONTROLLER_SCANNING);
-const ControllerConnectionState kControllerConnecting =
-    static_cast<ControllerConnectionState>(GVR_CONTROLLER_CONNECTING);
-const ControllerConnectionState kControllerConnected =
-    static_cast<ControllerConnectionState>(GVR_CONTROLLER_CONNECTED);
-
-typedef gvr_controller_button ControllerButton;
-const ControllerButton kControllerButtonNone =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_NONE);
-const ControllerButton kControllerButtonClick =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_CLICK);
-const ControllerButton kControllerButtonHome =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_HOME);
-const ControllerButton kControllerButtonApp =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_APP);
-const ControllerButton kControllerButtonVolumeUp =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_VOLUME_UP);
-const ControllerButton kControllerButtonVolumeDown =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_VOLUME_DOWN);
-const ControllerButton kControllerButtonCount =
-    static_cast<ControllerButton>(GVR_CONTROLLER_BUTTON_COUNT);
-
-typedef gvr_controller_battery_level ControllerBatteryLevel;
-const ControllerBatteryLevel kControllerBatteryLevelUnknown =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_UNKNOWN);
-const ControllerBatteryLevel kControllerBatteryLevelCriticalLow =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_CRITICAL_LOW);
-const ControllerBatteryLevel kControllerBatteryLevelLow =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_LOW);
-const ControllerBatteryLevel kControllerBatteryLevelMedium =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_MEDIUM);
-const ControllerBatteryLevel kControllerBatteryLevelAlmostFull =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_ALMOST_FULL);
-const ControllerBatteryLevel kControllerBatteryLevelFull =
-    static_cast<ControllerBatteryLevel>(
-        GVR_CONTROLLER_BATTERY_LEVEL_FULL);
-
-/// An uninitialized external surface ID.
-const int32_t kUninitializedExternalSurface = GVR_BUFFER_INDEX_EXTERNAL_SURFACE;
-/// The default source buffer index for viewports.
-const int32_t kDefaultBufferIndex = 0;
-
-typedef gvr_eye Eye;
-
-typedef gvr_viewer_type ViewerType;
-const ViewerType kViewerTypeCardboard =
-    static_cast<ViewerType>(GVR_VIEWER_TYPE_CARDBOARD);
-const ViewerType kViewerTypeDaydream =
-    static_cast<ViewerType>(GVR_VIEWER_TYPE_DAYDREAM);
-
-typedef gvr_version Version;
-typedef gvr_sizei Sizei;
-typedef gvr_recti Recti;
-typedef gvr_rectf Rectf;
-typedef gvr_vec2f Vec2f;
-typedef gvr_vec3f Vec3f;
-typedef gvr_mat4f Mat4f;
-typedef gvr_quatf Quatf;
-typedef gvr_clock_time_point ClockTimePoint;
-
-typedef gvr_vec2f ControllerVec2;
-typedef gvr_vec3f ControllerVec3;
-typedef gvr_quatf ControllerQuat;
-
-typedef gvr_audio_rendering_mode AudioRenderingMode;
-typedef gvr_audio_material_type AudioMaterialName;
-typedef gvr_audio_distance_rolloff_type AudioRolloffMethod;
-typedef gvr_audio_source_id AudioSourceId;
-typedef gvr_audio_surround_format_type AudioSurroundFormat;
-
-typedef gvr_color_format_type ColorFormat;
-const ColorFormat kColorFormatRgba8888 =
-    static_cast<ColorFormat>(GVR_COLOR_FORMAT_RGBA_8888);
-const ColorFormat kColorFormatRgb565 =
-    static_cast<ColorFormat>(GVR_COLOR_FORMAT_RGB_565);
-
-typedef gvr_depth_stencil_format_type DepthStencilFormat;
-const DepthStencilFormat kDepthStencilFormatNone =
-    static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_NONE);
-const DepthStencilFormat kDepthStencilFormatDepth16 =
-    static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
-const DepthStencilFormat kDepthStencilFormatDepth24 =
-    static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_24);
-const DepthStencilFormat kDepthStencilFormatDepth24Stencil8 =
-    static_cast<DepthStencilFormat>(
-        GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8);
-const DepthStencilFormat kDepthStencilFormatDepth32f =
-    static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F);
-const DepthStencilFormat kDepthStencilFormatDepth32fStencil8 =
-    static_cast<DepthStencilFormat>(
-        GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8);
-const DepthStencilFormat kDepthStencilFormatStencil8 =
-    static_cast<DepthStencilFormat>(GVR_DEPTH_STENCIL_FORMAT_STENCIL_8);
-
-typedef gvr_controller_handedness ControllerHandedness;
-const ControllerHandedness kControllerRightHanded =
-    static_cast<ControllerHandedness>(GVR_CONTROLLER_RIGHT_HANDED);
-const ControllerHandedness kControllerLeftHanded =
-    static_cast<ControllerHandedness>(GVR_CONTROLLER_LEFT_HANDED);
-
-typedef gvr_error Error;
-const Error kErrorNone = static_cast<Error>(GVR_ERROR_NONE);
-const Error kErrorControllerCreateFailed =
-    static_cast<Error>(GVR_ERROR_CONTROLLER_CREATE_FAILED);
-const Error kErrorNoFrameAvailable =
-    static_cast<Error>(GVR_ERROR_NO_FRAME_AVAILABLE);
-
-class AudioApi;
-class BufferSpec;
-class ControllerApi;
-class ControllerState;
-class Frame;
-class GvrApi;
-class BufferViewport;
-class BufferViewportList;
-class SwapChain;
-class UserPrefs;
-
-}  // namespace gvr
-
-// Non-member equality operators for convenience. Since typedefs do not trigger
-// argument-dependent lookup, these operators have to be defined for the
-// underlying types.
-inline bool operator==(const gvr_vec2f& lhs, const gvr_vec2f& rhs) {
-  return lhs.x == rhs.x && lhs.y == rhs.y;
-}
-
-inline bool operator!=(const gvr_vec2f& lhs, const gvr_vec2f& rhs) {
-  return !(lhs == rhs);
-}
-
-inline bool operator==(const gvr_vec3f& lhs, const gvr_vec3f& rhs) {
-  return lhs.x == rhs.x && lhs.y == rhs.y;
-}
-
-inline bool operator!=(const gvr_vec3f& lhs, const gvr_vec3f& rhs) {
-  return !(lhs == rhs);
-}
-
-inline bool operator==(const gvr_recti& lhs, const gvr_recti& rhs) {
-  return lhs.left == rhs.left && lhs.right == rhs.right &&
-         lhs.bottom == rhs.bottom && lhs.top == rhs.top;
-}
-
-inline bool operator!=(const gvr_recti& lhs, const gvr_recti& rhs) {
-  return !(lhs == rhs);
-}
-
-inline bool operator==(const gvr_rectf& lhs, const gvr_rectf& rhs) {
-  return lhs.left == rhs.left && lhs.right == rhs.right &&
-         lhs.bottom == rhs.bottom && lhs.top == rhs.top;
-}
-
-inline bool operator!=(const gvr_rectf& lhs, const gvr_rectf& rhs) {
-  return !(lhs == rhs);
-}
-
-inline bool operator==(const gvr_sizei& lhs, const gvr_sizei& rhs) {
-  return lhs.width == rhs.width && lhs.height == rhs.height;
-}
-
-inline bool operator!=(const gvr_sizei& lhs, const gvr_sizei& rhs) {
-  return !(lhs == rhs);
-}
-
-#endif  // #if defined(__cplusplus) && !defined(GVR_NO_CPP_WRAPPER)
-
-#endif  // VR_GVR_CAPI_INCLUDE_GVR_TYPES_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h
deleted file mode 100644
index 5bd6174..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_experimental.h
+++ /dev/null
@@ -1,231 +0,0 @@
-#ifndef VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_
-#define VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "vr/gvr/capi/include/gvr_types.h"
-#include "vr/gvr/capi/src/gvr_types_experimental.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// NOTE: APIs added to this file are *not* part of the core GVR library, and
-// should only be used for prototyping or experimental projects. The idea is
-// that APIs added here can be used for testing and development, graduating to
-// the core API (gvr.h or gvr_private.h) after we're ready to commit to them
-// indefinitely.
-
-// ************************************************************************** //
-// *                     DaydreamOS experimental APIs                       * //
-// ************************************************************************** //
-
-/// Gets the position and rotation from start space to head space.  The head
-/// space is a space where the head is at the origin and faces the -Z direction.
-///
-/// @param gvr Pointer to the gvr instance from which to get the pose.
-/// @param time The time at which to get the head pose. The time should be in
-///     the future. If the time is not in the future, it will be clamped to now.
-/// @return A matrix representation of the position and rotation from start
-//      space (the space where the head was last reset) to head space (the space
-///     with the head at the origin, and the axes aligned to the view vector).
-gvr_mat4f gvr_get_head_space_from_start_space_pose(
-    gvr_context* gvr, const gvr_clock_time_point time);
-
-/// Sets the compositor z-order of the swap chain.
-///
-/// @param swap_chain the swap chain to change.
-/// @param z_order Z order, higher values are displayed on top of lower ones,
-///     the default value is 0.
-void gvr_swap_chain_set_z_order(const gvr_swap_chain* swap_chain, int z_order);
-
-/// Creates a gvr_external_surface instance.
-/// An external surface is mainly used to pass external content (such as video
-/// frames, pre-rendered 2D Android UI) into distortion pass for compositing.
-/// The method gvr_external_surface_get_surface can be used to bridge Android
-/// components with GVR distortion pass via a traditional Android Surface
-/// instance.
-///
-/// @param gvr Pointer to the gvr instance from which to create the external
-///     surface.
-/// @return Pointer to an allocated gvr_external_surface object. The caller
-//      is responsible for calling gvr_external_surface_destroy() on the
-///     returned object when it is no longer needed.
-gvr_external_surface* gvr_external_surface_create(gvr_context* gvr);
-
-/// Frees a gvr_external_surface instance and clears the pointer.
-/// Note that once a gvr_external_surface is destroyed, the Java Surface object
-/// returned from gvr_external_surface_get_surface remains to be accessible and
-/// functioning. It's up to Java's garbage collection to release all resources
-/// behind the Java Surface object.
-///
-/// @param surface Pointer to a pointer to the gvr_external_surface instance to
-///     be destroyed and nulled.
-void gvr_external_surface_destroy(gvr_external_surface** surface);
-
-/// Get an Android Surface as a Java object from the gvr_external_surface. This
-/// API is mainly used by standalone display service (aka when
-/// gvr_using_vr_display_service returns true) to access an Android Surface.
-///
-/// @param surface The gvr_external_surface associated with the Android Surface.
-///     Note that this API has to be called within a JNIEnv and is using the
-///     JNIEnv passed in during gvr_create.
-/// @return A jobject that is an instance of the 'android/view/Surface' Java
-///     class, NULL on failure. Note that the return value is really an opaque
-///     handle to a Java object and the life cycle of that object is maintained
-///     by Java (i.e. it will get garbage collected eventually). Thus, there is
-///     no need for an explicit destroy call.
-void* gvr_external_surface_get_surface(const gvr_external_surface* surface);
-
-/// Get the Surface ID associated with the gvr_external_surface. Note that the
-/// returned ID is used for internal bookkeeping only and should not be used
-/// by the app itself for lookups.
-/// @param surface The gvr_external_surface to query the ID for.
-/// @return The external surface ID associated with the gvr_external_surface.
-int32_t gvr_external_surface_get_surface_id(
-    const gvr_external_surface* surface);
-
-/// Sets the z order of the layer to be created.
-/// Note that this API is a short-term workaround for SysUI work and is never
-/// meant to graduate as is to either gvr.h or gvr_private.h. The proper
-/// solution is tracked in b/33946428 and probably involves setting the
-/// attribute on some data structure that represents a layer.
-///
-/// @param spec Buffer specification.
-/// @param z_order Z order, higher values are displayed on top of lower ones,
-///     the default value is 0.
-void gvr_buffer_spec_set_z_order(gvr_buffer_spec* spec, int z_order);
-
-/// Sets the initial visibility of the layer to be created.
-/// Note that this API is a short-term workaround for SysUI work and is never
-/// meant to graduate as is to either gvr.h or gvr_private.h. The proper
-/// solution is tracked in b/33946428 and probably involves setting the
-/// attribute on some data structure that represents a layer.
-///
-/// @param spec Buffer specification.
-/// @param visibility Initial visibility of the layer, defaults to GVR_VISIBLE.
-///     See enum gvr_visibility for possible values.
-void gvr_buffer_spec_set_visibility(gvr_buffer_spec* spec,
-                                    int32_t visibility);
-
-/// Sets whether to blur layers below the layer to be created.
-/// Blurring is applied only to visible layers and only when the layer is
-/// visible.
-/// Note that this API currently is only implemented by the DreamOS
-/// implementation of GVR and is a no-op in other implementations.
-/// TODO(b/33946428): investigate the proper way to surface this feature
-/// to SysUI.
-///
-/// @param spec Buffer specification.
-/// @param blur_behind whether to blur layers behind, defaults to
-///     GVR_BLUR_BEHIND_TRUE. See enum gvr_blur_behind for possible values.
-void gvr_buffer_spec_set_blur_behind(gvr_buffer_spec* spec,
-                                     int32_t blur_behind);
-
-// ************************************************************************** //
-// *                     Daydream PlexEng experimental APIs                 * //
-// ************************************************************************** //
-
-// Registers a new performance event listener that will be invoked on points
-// of interest. By default no event listener is attached.  If multiple event
-// listeners are attached they will all be invoked.  Failures can be checked
-// with gvr_get_error().
-// @param out_handle The pointer to memory where a successfully created handle
-//     will be written.
-// @param gvr The context to register callbacks for.
-// @param user_data The pointer that will be passed back on callbacks for
-//     user_data.
-// @param event_callback The callback to be invoked when an event is observed.
-//     On performance events callback will be invoked with the
-//     user_data passed here, the gvr_perf_event_callback_type, and a float
-//     value (if applicable) or -1.f.
-// @return Returns GVR_EXPERIMENTAL_ERROR_NONE if a handle was created,
-//     GVR_EXPERIMENTAL_ERROR_UNIMPLEMENTED if this feature is disabled,
-//     or GVR_EXPERIMENTAL_ERROR_INVALID_ARGUMENT if a null pointer was passed.
-bool gvr_experimental_register_perf_event_callback(
-    gvr_context* gvr, int* out_handle, void* user_data,
-    void (*event_callback)(void*, int, float));
-
-// Unregisters a previously registered callback by its handle. Failures can be
-// checked with gvr_get_error().
-// @param handle The handle which was returned when registering the callback.
-// @return Returns GVR_EXPERIMENTAL_ERROR_NONE if callback was unregistered,
-//     GVR_EXPERIMENTAL_ERROR_INVALID_ARGUMENT if the if the handle wasn't
-//     previously
-//     registered.  If this feature is not enabled it will return
-//     GVR_EXPERIMENTAL_ERROR_UNIMPLEMENTED.
-bool gvr_experimental_unregister_perf_event_callback(gvr_context* gvr,
-                                                     int handle);
-
-// ************************************************************************** //
-// *                    GVR Analytics experimental APIs                     * //
-// ************************************************************************** //
-// TODO(b/31634289): These functions are experimental because their main client
-// case is the performance monitoring HUD, whose form and function is still
-// under development. Consequently, the analytics API may change as the HUD's
-// needs become clearer.
-//
-// These functions will be moved into the main API (probably gvr_private.h) once
-// the HUD is ready to be shipped as part of the SDK.
-//
-// Contacts: georgelu@
-
-/// Returns whether the "Performance Monitoring" developer option is enabled.
-///
-/// @param user_prefs Pointer to the gvr_user_prefs object returned by
-///     gvr_get_user_prefs.
-/// @return True if the "Performance Monitoring" developer option is enabled.
-bool gvr_user_prefs_get_performance_monitoring_enabled(
-    const gvr_user_prefs* user_prefs);
-
-// Opaque struct returned by gvr_get_analytics that can be queried through
-// gvr_analytics_get* functions.
-//
-// Note: The struct is never actually defined since gvr_analytics is actually
-// just a static_cast of a gvr_context, similar to how gvr_user_prefs works.
-typedef struct gvr_analytics_ gvr_analytics;
-
-// Returns an opaque struct that can be queried for analytics data. The returned
-// struct remains valid as long as the context is valid.
-//
-// @param gvr Pointer to the current gvr_context instance.
-// @return An opaque struct that can be queried through gvr_analytics_*
-//     functions.
-const gvr_analytics* gvr_get_analytics(gvr_context* gvr);
-
-// If the "Performance Monitoring" developer option in VR settings is enabled,
-// returns a gvr_analytics_sample* containing analytics data. Caller is
-// responsible for calling gvr_analytics_destroy_sample on the returned object.
-//
-// @param analytics gvr_analytics* returned by gvr_get_analytics.
-// @return gvr_analytics_sample* containing analytics data.
-const gvr_analytics_sample* gvr_analytics_create_sample(
-    const gvr_analytics* analytics);
-
-// Returns pointer to a buffer containing a serialized AnalyticsSample proto.
-// The buffer is valid only for the lifetime of the gvr_analytics_sample.
-//
-// @param Pointer to a gvr_analytics_sample object.
-// @return Pointer to buffer.
-const char* gvr_analytics_sample_get_buffer(const gvr_analytics_sample* sample);
-
-// Returns the length of the buffer returned by gvr_analytics_sample_get_buffer.
-//
-// @param Pointer to a gvr_analytics_sample object.
-// @return Length of buffer.
-size_t gvr_analytics_sample_get_buffer_length(
-    const gvr_analytics_sample* sample);
-
-// Destroys a gvr_analytics_sample* previously created through
-// gvr_analytics_create_sample.
-//
-// @param sample Pointer to pointer that will be set to null and whose
-//     underlying gvr_analytics_sample will be destroyed.
-void gvr_analytics_destroy_sample(const gvr_analytics_sample** sample);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // VR_GVR_CAPI_SRC_GVR_EXPERIMENTAL_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h
deleted file mode 100644
index 0a9d30e..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_private.h
+++ /dev/null
@@ -1,378 +0,0 @@
-#ifndef VR_GVR_CAPI_SRC_GVR_PRIVATE_H_
-#define VR_GVR_CAPI_SRC_GVR_PRIVATE_H_
-
-#include <stddef.h>
-
-#include "vr/gvr/capi/include/gvr_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Opaque handle to gvr_tracker_state object containing serialized state.
-typedef struct gvr_tracker_state_ gvr_tracker_state;
-
-// Opaque handle to gvr_display_synchronizer object for display synchronization.
-typedef struct gvr_display_synchronizer_ gvr_display_synchronizer;
-
-// Internal Google VR C API methods. These methods are exposed only to internal
-// targets, but should follow all the same backwards-compatible restrictions
-// as the public C API.
-
-/// Sets whether asynchronous reprojection is currently enabled.
-///
-/// If enabled, frames will be collected by the rendering system and
-/// asynchronously re-projected in sync with the scanout of the display. This
-/// feature may not be available on every platform, and requires a
-/// high-priority render thread with special extensions to function properly.
-///
-/// Note: On Android, this feature can be enabled solely via the GvrLayout Java
-/// instance which (indirectly) owns this gvr_context. The corresponding
-/// method call is GvrLayout.setAsyncReprojectionEnabled().
-///
-/// @param gvr Pointer to the gvr instance.
-/// @Param enabled Whether to enable async reprojection.
-/// @return Whether the setting was succesfully applied.
-bool gvr_set_async_reprojection_enabled(gvr_context* gvr, bool enabled);
-
-// Initializes necessary GL-related objects and uses the current thread and
-// GL context for racing the scanline. This function should only be called
-// by the SDK itself, not by any application, unless that application is
-// providing a high-priority thread and GL context for async reprojection.
-//
-// Note: This method is private as it is intended for use solely by the
-// hidden async reprojection implementation in ScanlineRacingRenderer.java,
-// called in onSurfaceCreated().
-//
-// @param gvr Pointer to the gvr_context instance.
-void gvr_on_surface_created_reprojection_thread(gvr_context* gvr);
-
-// Renders the scanline layer. This function should only be called
-// in the same thread that gvr_initialize_gl_projection_thread was called in.
-// This function should only be called by the SDK itself, not by any
-// application, unless that application is providing a high-priority
-// thread and GL context for async reprojection.
-//
-// Note: This method is private as it is intended for use solely by the
-// hidden async reprojection implementation in ScanlineRacingRenderer.java.
-//
-// @param gvr Pointer to the gvr_context instance.
-void gvr_render_reprojection_thread(gvr_context* gvr);
-
-// Signals to the reprojection thread that it is paused. This is necessary
-// in case the application render thread is blocked on pending work by the
-// reprojection thread. This function will abort any blocking.
-//
-// @param gvr Pointer to the gvr_context instance.
-void gvr_on_pause_reprojection_thread(gvr_context* gvr);
-
-// Sets the parameters for the external surface managed by the reprojection
-// thread.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param surface_id The ID of the external Surface managed by the reprojection
-//     thread. The ID is issued by the SurfaceTextureManager.
-// @param texture_id The GL texture ID associated with the external Surface.
-// @param timestamp The timestamp of the most recent frame the Surface holds.
-// @param surface_transfrom Matrix that transforms homogeneous texture coords to
-//     the external surface texture space.
-void gvr_update_surface_reprojection_thread(gvr_context* gvr,
-      int32_t surface_id, int32_t texture_id, gvr_clock_time_point timestamp,
-      gvr_mat4f surface_transform);
-
-// Removes all external surfaces managed by the reprojection thread. This does
-// not destoy the surfaces: it removes tracking by the reprojection thread.
-//
-// @param gvr Pointer to the gvr_context instance.
-void gvr_remove_all_surfaces_reprojection_thread(gvr_context* gvr);
-
-// Reconnects the sensors when the sensor producers are created internally.
-//
-// Note: This function is not thread-safe, and should be called only on the
-// rendering thread. It is intended to be used internally by GvrLayout when
-// the target presentation display changes.
-//
-// @param gvr Pointer to the gvr_context instance.
-void gvr_reconnect_sensors(gvr_context* gvr);
-
-// Sets VR viewer params for the current context.
-//
-// Note: This function does not update the viewer proto in the common storage
-// location. Rather, it overrides the viewer params solely for the provided
-// gvr_context.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param serialized_viewer_params A pointer to the payload containing the
-//     serialized viewer params proto.
-// @param serialized_viewer_params_size_bytes The length in bytes of the
-//     serialized viewer params payload.
-// @return Whether the serialized viewer params proto was successfully applied.
-bool gvr_set_viewer_params(gvr_context* gvr,
-                           const void* serialized_viewer_params,
-                           size_t serialized_viewer_params_size_bytes);
-
-// Sets the lens offset.
-//
-// @param offset The offset of the lens center from the expected location in
-// screen space.
-void gvr_set_lens_offset(gvr_context* gvr, gvr_vec2f offset);
-
-// Sets display metrics for the current context.
-//
-// Note: This function does not update the phone proto in the commom storage
-// location. Rather, it overrides the internal metrics solely for the provided
-// |gvr| context.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param size_pixels The dimensions in pixels of the active display.
-// @param meters_per_pixel The density of the current display in meters/pixel.
-// @param border_size_meters The size of the border around the display
-//     in meters.  When the device sits on a surface in the proper
-//     orientation this is the distance from the surface to the edge
-//     of the display.
-void gvr_set_display_metrics(gvr_context* gvr, gvr_sizei size_pixels,
-                             gvr_vec2f meters_per_pixel,
-                             float border_size_meters);
-
-// Sets the display rotation offset that is applied at distortion correction
-// time to take into account the device's display orientation.
-//
-// For instance, calling this with display_output_rotation set to 1 allows
-// clients to lock their phone orientation to portrait on an Android phone and
-// still get a correctly rendered VR mode with the two eyes stacked up along the
-// longer phone dimension.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param display_output_rotation Value encoding the rotation used when
-//     performing distortion correction. Supported values are:
-//     0 - Default mode. Eye viewports are positioned side-by-side along the
-//         "width" dimension, with left eye in the x < 0.5 half.
-//     1 - Applies a clock-wise rotation of 90 degrees on the display when
-//         doing distortion correction. Eye viewports are positioned
-//         side-by-side along the "height" dimension, with left eye in the
-//         y > 0.5 half.
-// Rotation modes used when performing distortion correction.
-enum {
-  GVR_PRIVATE_DISPLAY_OUTPUT_ROTATION_0 = 0,
-  GVR_PRIVATE_DISPLAY_OUTPUT_ROTATION_90 = 1,
-};
-void gvr_set_display_output_rotation(gvr_context* gvr,
-                                     int32_t display_output_rotation);
-
-// Gets the size of the border around the display used by the given gvr_context.
-//
-// @param gvr Pointer to the gvr_context instance.
-float gvr_get_border_size_meters(const gvr_context* gvr);
-
-// Returns whether the surface size was changed since the last call to this
-// function (it's changed with gvr_set_surface_size()).
-//
-// @param gvr Pointer to the gvr_context instance.
-// @return Whether the surface size was changed.
-bool gvr_check_surface_size_changed(gvr_context* gvr);
-
-// Returns the current surface size in pixels, or (0, 0) if the surface size
-// matches that of the active display (which is the default).
-//
-// @param gvr Pointer to the gvr_context instance.
-// @return The current surface size in pixels.
-gvr_sizei gvr_get_surface_size(const gvr_context* gvr);
-
-// Sets a handler that is called back when the back gesture is detected,
-// which is when the phone changes from landscape to portrait orientation
-// within a few seconds.
-//
-// @param gvr Pointer to the gvr_context instance.
-// @param handler The event_handler callback. May be null to clear the
-//     registered event_handler.
-// @param user_data An opaque pointer to user_data which will be supplied
-//     as the callback argument. The caller is responsible for ensuring the
-//     validity of this data for the duration of the handler registration.
-typedef void (*event_handler)(void* user_data);
-void gvr_set_back_gesture_event_handler(gvr_context* gvr, event_handler handler,
-                                        void* user_data);
-
-// Internal method to pause head tracking used by GvrLayout. Disables all
-// sensors (to save power) and gets the serialized tracker state.
-//
-// @param gvr Pointer to the gvr instance for which tracking will be paused and
-//     sensors disabled.
-//
-// @return Pointer to a tracker_state object containing the serialized tracker
-//     state. The caller is responsible for calling destroy on the returned
-//     handle.
-gvr_tracker_state* gvr_pause_tracking_get_state(gvr_context* gvr);
-
-// Internal method to resume head tracking used by GvrLayout. Re-enables all
-// sensors and sets the tracker state.
-//
-// @param gvr Pointer to the gvr instance for which tracking will be resumed.
-//     serialized tracker state object.
-// @param tracker_state Pointer to a tracker_state object containing the
-//     serialized tracker state object.
-void gvr_resume_tracking_set_state(
-    gvr_context* gvr, gvr_tracker_state* tracker_state);
-
-// Sets the internal flag that ignores calls to the public API's
-// gvr_pause_tracking and gvr_resume_tracking.
-// When true, the tracker is handled through GvrLayout
-// gvr_pause_tracking_private / gvr_resume_tracking_private direct calls through
-// the GvrApi instance are ignored. This is workaround to temporarily support
-// clients using GvrLayout that manually call pause/ resume tracking.
-// TODO(b/30404822) : clean this up once all existing clients move away from the
-// obsolete behavior.
-//
-// @param gvr Pointer to the gvr instance.
-// @param should_ignore Whether manual pause / resume tracker should be ignored.
-void gvr_set_ignore_manual_tracker_pause_resume(gvr_context* gvr,
-                                                bool should_ignore);
-
-// Creates a new tracker state object from the serialized tracker state buffer.
-//
-// @param tracker_state_buffer Pointer to buffer containing the serialized
-// tracker state.
-// @param buf_size Size of the tracker state buffer.
-//
-// @return Pointer to a tracker_state object containing the serialized tracker
-// state string. The caller is responsible for calling destroy on the returned
-// handle.
-gvr_tracker_state* gvr_tracker_state_create(const char* tracker_state_buffer,
-                                            size_t buf_size);
-
-// Gets the size of the buffer that is required to hold the serialized
-// gvr_tracker_state.
-//
-// @param Pointer to a gvr_tracker_state object containing the serialized
-// tracker state.
-//
-// @return Size of the buffer,
-size_t gvr_tracker_state_get_buffer_size(gvr_tracker_state* tracker_state);
-
-// Gets the buffer that holds the serialized gvr_tracker_state.
-//
-// @param Pointer to a tracker_state object containing the serialized tracker
-// state.
-//
-// @return Pointer to the buffer.
-const char* gvr_tracker_state_get_buffer(gvr_tracker_state* tracker_state);
-
-// Destroys a gvr_tracker_state instance.
-//
-// @param tracker_state Pointer to a pointer of the gvr_tracker_state instance
-// to be destroyed and nulled.
-void gvr_tracker_state_destroy(gvr_tracker_state** tracker_state);
-
-// Creates a new synchronizer instance.
-//
-// @return synchronizer Pointer to the new gvr_display_synchronizer instance.
-gvr_display_synchronizer* gvr_display_synchronizer_create();
-
-// Destroy the synchonronizer instance and null the pointer.
-//
-// @param synchronizer Pointer to a pointer to the gvr_display_synchronizer
-//     instance.
-void gvr_display_synchronizer_destroy(gvr_display_synchronizer** synchronizer);
-
-// Resets the synchronizer with updated vsync timing data.
-//
-// @param synchronizer Pointer to the new gvr_display_synchronizer instance.
-// @param expected_interval_nanos The expected average time between
-//     synchronization times, in nanoseconds, or 0 if unknown.
-// @param vsync_offset_nanos The duration, in nanos, such that the current sync
-//     time minus the display vsync offset is the time when the physical
-//     scan-out hardware begins to read data from the frame buffer.
-void gvr_display_synchronizer_reset(gvr_display_synchronizer* synchronizer,
-                                    int64_t expected_interval_nanos,
-                                    int64_t vsync_offset_nanos);
-
-// Updates the synchronizer with dispplay data for a new frame.
-//
-// @param vsync_time The new frame's vsync time.
-// @param rotation_degrees The screen rotation from sensor space to display
-//     space in degrees.
-void gvr_display_synchronizer_update(gvr_display_synchronizer* synchronizer,
-                                     gvr_clock_time_point vsync_time,
-                                     int32_t rotation);
-
-// Installs the display synchronizer into a GVR context.
-//
-// @param gvr Pointer to the current gvr_context instance.
-// @param synchronizer Pointer to the gvr_display_synchronizer instance, to be
-//     used by the context implementation during rendering.
-void gvr_set_display_synchronizer(gvr_context* gvr,
-                                  gvr_display_synchronizer* synchronizer);
-
-// Sets the current error code. Overwrites any existing error code.
-//
-// @param gvr Pointer to the current gvr_context instance.
-// @param error_code The error code to set.
-void gvr_set_error(gvr_context* gvr, int32_t error_code);
-
-// Called by the platform layer to to indicate the application is paused. (e.g.
-// On Android, this function is called by GvrLayout.OnPause().)
-//
-// @param gvr Pointer to the current gvr_context instance.
-void gvr_pause(gvr_context* gvr);
-
-// Called by the platform layer to to indicate the application has resumed.
-// (e.g. On Android, this function is called by GvrLayout.OnResume().)
-//
-// @param gvr Pointer to the current gvr_context instance.
-void gvr_resume(gvr_context* gvr);
-
-// Dumps additional data to logcat or disk to be included in bug reports.
-//
-// @param gvr Pointer to the current gvr_context instance.
-void gvr_dump_debug_data(gvr_context* gvr);
-
-// Returns true if the libgvr implementation is using the dedicated VR display
-// service, false otherwise.
-//
-// @param gvr Pointer to the current gvr_context instance.
-bool gvr_using_vr_display_service(gvr_context* gvr);
-
-// Creates a new gvr_context using the supplied tracker, only for testing.
-//
-// Note: The pose returned is *in start space*. This is *not* the same space as
-// the pose normally returned by |gvr_get_head_space_from_start_space_rotation|.
-//
-// @param tracker The test pose tracker to use.
-// @param user_data An opaque pointer to user_data which will be supplied
-//     as the callback argument. The caller is responsible for ensuring the
-//     validity of this data for the duration of the handler registration.
-typedef gvr_mat4f (*gvr_test_pose_tracker)(void*, gvr_clock_time_point);
-gvr_context* gvr_create_with_tracker_for_testing(gvr_test_pose_tracker tracker,
-                                                 void* user_data);
-
-// Request resource sharing between the application's OpenGL context and the
-// scanline racing context.  This must be called before gvr_initialize_gl.
-// <p>
-// This is a best effort request rather than an explicit toggle; it is a no-op
-// if the client does not enable async reprojection, or if the platform does not
-// support resource sharing.
-// <p>
-// The only OpenGL resource that we need sharing for is the framebuffer texture
-// that the app renders to, and that distortion samples from.  If resource
-// sharing is disabled, then we use an EGLImage so that it can be accessed from
-// both contexts.
-// <p>
-// Also sets a callback function that is called at the end of gvr_initialize_gl,
-// while the application's OpenGL context is still active on the current thread.
-// This is used internally to notify the scanline racing renderer that the
-// application's OpenGL context has been created.
-//
-// @param gvr Pointer to the current gvr_context instance.
-// @param handler Callback that gets called when the app context becomes ready.
-// @param user_data An opaque pointer to user data which will be supplied
-//     as the callback argument. The caller is responsible for ensuring the
-//     validity of this data for the duration of the handler registration.
-typedef void (*gvr_egl_context_listener)(void*);
-void gvr_request_context_sharing(gvr_context* gvr,
-                                 gvr_egl_context_listener handler,
-                                 void* user_data);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // VR_GVR_CAPI_SRC_GVR_PRIVATE_H_
diff --git a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h b/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h
deleted file mode 100644
index f7ae6a5..0000000
--- a/libs/vr/libgvr/prebuilt/include/vr/gvr/capi/src/gvr_types_experimental.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_
-#define VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_
-
-#include <string>
-
-// ************************************************************************** //
-// *                     DaydreamOS experimental Types                * //
-// ************************************************************************** //
-
-// Visibility of a layer.
-typedef enum {
-  GVR_INVISIBLE = 0,
-  GVR_VISIBLE = 1,
-} gvr_visibility;
-
-// Whether to blur layers behind a layer.
-typedef enum {
-  GVR_BLUR_BEHIND_FALSE = 0,
-  GVR_BLUR_BEHIND_TRUE = 1,
-} gvr_blur_behind;
-
-// GVR external surface
-typedef struct gvr_external_surface_ gvr_external_surface;
-
-// ************************************************************************** //
-// *                     Daydream PlexEng experimental Types                * //
-// ************************************************************************** //
-
-// Types of events that can have callbacks registered.
-// If documented, type will return a payload value when called, or will
-// otherwise be invoked with -1.f.
-// This enum has to be duplicated because there is no way to include from
-// /vr/gvr/render/performance_registry.h.  Duplicate changes made here there.
-typedef enum {
-  // Will be invoked with value -1.f.
-  GVR_ON_ASYNC_REPROJECTION_FRAME_START = 0,
-  // Will be invoked with value -1.f.
-  GVR_ON_ASYNC_REPROJECTION_FRAME_STOP = 1,
-  // When invoked will be called with how late in microseconds the frame was.
-  GVR_ON_ASYNC_REPROJECTION_FRAME_DROP = 2,
-  // The number of types of performance events you can have.
-  // Also note that this value is considered invalid.
-  GVR_NUM_PERF_EVENT_CALLBACK_TYPES = 3,
-} gvr_perf_event_callback_type;
-
-// Experimental VR-specific features which may or may not be supported on the
-// underlying platform.  These values should not overlap with current or future
-// gvr_feature values, so we're starting with 1000000 and increasing upward.
-typedef enum {
-  // Head tracking with 6 degrees of freedom (position & rotation)
-  GVR_FEATURE_HEAD_POSE_6DOF = 1000000,
-} gvr_experimental_feature;
-
-// ************************************************************************** //
-// *                    GVR Analytics experimental APIs                     * //
-// ************************************************************************** //
-
-// Opaque struct returned by gvr_analytics_create_sample, used to transmit an
-// AnaylticsSample proto across the native layer.
-typedef struct gvr_analytics_sample_ {
-  // Serialized AnalyticsSample proto. Note that this is not a C string, meaning
-  // it is not null-terminated and may contain non-terminating nulls.
-  std::string serialized_proto;
-} gvr_analytics_sample;
-
-#endif  // VR_GVR_CAPI_SRC_GVR_TYPES_EXPERIMENTAL_H_
diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so
deleted file mode 100644
index bfd5956..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so
deleted file mode 100644
index c3012b1..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_arm/libgvr_audio.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so
deleted file mode 100644
index 6608c25..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so
deleted file mode 100644
index b1d7690..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_arm64/libgvr_audio.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so
deleted file mode 100644
index f7f7786..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so
deleted file mode 100644
index 97aec40..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_x86/libgvr_audio.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so b/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so
deleted file mode 100644
index 2e2dbc1..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so b/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so
deleted file mode 100644
index cd8d0e0..0000000
--- a/libs/vr/libgvr/prebuilt/lib/android_x86_64/libgvr_audio.so
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/prebuilt/lib/common_library.aar b/libs/vr/libgvr/prebuilt/lib/common_library.aar
deleted file mode 100644
index 9c1fbd0..0000000
--- a/libs/vr/libgvr/prebuilt/lib/common_library.aar
+++ /dev/null
Binary files differ
diff --git a/libs/vr/libgvr/shim_gvr.cpp b/libs/vr/libgvr/shim_gvr.cpp
deleted file mode 100644
index 5eb6e3d..0000000
--- a/libs/vr/libgvr/shim_gvr.cpp
+++ /dev/null
@@ -1,1352 +0,0 @@
-#define LOG_TAG "libgvr_shim"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES3/gl31.h>
-#include <GLES3/gl3ext.h>
-#include <algorithm>
-#include <cmath>
-
-#ifdef __ARM_NEON
-#include <arm_neon.h>
-#else
-#ifndef __FLOAT32X4T_86
-#define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
-#endif
-#endif
-
-#include <dvr/graphics.h>
-#include <dvr/performance_client_api.h>
-#include <dvr/pose_client.h>
-#include <log/log.h>
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/buffer_hub_queue_producer.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/display_client.h>
-#include <private/dvr/graphics_private.h>
-#include <private/dvr/internal_types.h>
-#include <private/dvr/numeric.h>
-#include <private/dvr/types.h>
-#include <private/dvr/video_mesh_surface_client.h>
-#include <sys/system_properties.h>
-#include <vr/gvr/capi/include/gvr.h>
-#include <vr/gvr/capi/include/gvr_ext.h>
-#include <vr/gvr/capi/include/gvr_util.h>
-#include <vr/gvr/capi/src/gvr_experimental.h>
-#include <vr/gvr/capi/src/gvr_private.h>
-
-#include <android_runtime/android_view_Surface.h>
-#include <gui/Surface.h>
-
-using android::dvr::DisplayClient;
-using android::dvr::EigenToGvrMatrix;
-using android::dvr::FieldOfView;
-using android::dvr::FovRadiansToDegrees;
-using android::dvr::GetSystemClockNs;
-using android::dvr::GvrIdentityMatrix;
-using android::dvr::GvrMatrixToPosef;
-using android::dvr::GvrToDvrFov;
-using android::dvr::GvrToEigenMatrix;
-using android::dvr::GvrToEigenRotation;
-using android::dvr::GvrTranslationMatrix;
-using android::dvr::IsEqual;
-using android::dvr::PosefToGvrMatrix;
-using android::dvr::mat3;
-using android::dvr::mat4;
-using android::dvr::Posef;
-using android::dvr::quat;
-using android::dvr::vec3;
-
-namespace {
-
-constexpr static int32_t GVR_SDK_MAJOR_VERSION = 2;
-constexpr static int32_t GVR_SDK_MINOR_VERSION = 0;
-constexpr static int32_t GVR_SDK_PATCH_VERSION = 0;
-
-// The "DaydreamOS" part has been appended to make easier to see when VrCore
-// dynamic GVR API loading is effectively working.
-static const char* kVersionString = "2.0.0 DaydreamOS";
-static const char* kViewerVendor = "Google";
-static const char* kViewerModel = "Lucid";
-
-// Experimental system property used to provide 6DoF information on 3DoF APIs.
-static const char* kForce6DofProp = "experimental.force_6dof";
-
-static constexpr int kControllerCount = 2;
-
-gvr_frame* GetFrameFromSwapChain(gvr_swap_chain* swap_chain) {
-  return reinterpret_cast<gvr_frame*>(swap_chain);
-}
-
-gvr_swap_chain* GetSwapChainForFrame(gvr_frame* frame) {
-  return reinterpret_cast<gvr_swap_chain*>(frame);
-}
-
-const gvr_swap_chain* GetSwapChainForFrame(const gvr_frame* frame) {
-  return reinterpret_cast<const gvr_swap_chain*>(frame);
-}
-
-// Returns the world to head transform as a Posef.
-Posef ToPosef(const DvrPoseAsync& pose) {
-  return Posef(
-      quat(pose.orientation[3], pose.orientation[0], pose.orientation[1],
-           pose.orientation[2]),
-      vec3(pose.translation[0], pose.translation[1], pose.translation[2]));
-}
-
-// Returns the world to head transform, with 0 position, as a gvr matrix
-gvr_mat4f Gvr6dofTo3dof(const gvr_mat4f& pose) {
-  gvr_mat4f ret = pose;
-  ret.m[0][3] = 0;
-  ret.m[1][3] = 0;
-  ret.m[2][3] = 0;
-  return ret;
-}
-
-void GvrToDvrPose(gvr_mat4f world_to_head_transform,
-                  /*out*/ float32x4_t* orientation,
-                  /*out */ float32x4_t* translation) {
-  Posef pose = GvrMatrixToPosef(world_to_head_transform);
-  (*orientation)[0] = pose.GetRotation().x();
-  (*orientation)[1] = pose.GetRotation().y();
-  (*orientation)[2] = pose.GetRotation().z();
-  (*orientation)[3] = pose.GetRotation().w();
-  (*translation)[0] = pose.GetPosition().x();
-  (*translation)[1] = pose.GetPosition().y();
-  (*translation)[2] = pose.GetPosition().z();
-  (*translation)[3] = 0;
-}
-
-bool MatricesAlmostEqual(const gvr_mat4f& m1, const gvr_mat4f& m2,
-                         float tolerance) {
-  for (int row = 0; row < 4; ++row) {
-    for (int col = 0; col < 4; ++col) {
-      if (!IsEqual(m1.m[row][col], m2.m[row][col], tolerance))
-        return false;
-    }
-  }
-  return true;
-}
-
-gvr_mat4f FovToViewportTransform(const gvr_rectf& fov) {
-  // Depth range (1 1000) is chosen to match gvr impl in google3, which is
-  // chosen to match Unity integration.
-  return EigenToGvrMatrix(
-      GvrToDvrFov(fov).GetProjectionMatrix(1.f, 1000.f).inverse());
-}
-
-gvr_rectf ViewportTransformToFov(const gvr_mat4f& transform) {
-  return DvrToGvrFov(
-      FieldOfView::FromProjectionMatrix(GvrToEigenMatrix(transform).inverse()));
-}
-
-bool GetGlColorFormat(int32_t gvr_color_format,
-                      /*out*/ GLenum* gl_color_format) {
-  switch (gvr_color_format) {
-    case GVR_COLOR_FORMAT_RGBA_8888:
-      *gl_color_format = GL_RGBA8;
-      break;
-    case GVR_COLOR_FORMAT_RGB_565:
-      *gl_color_format = GL_RGB565;
-      break;
-    default:
-      return false;
-  }
-  return true;
-}
-
-bool GetGlDepthFormat(int32_t gvr_depth_format,
-                      /*out*/ GLenum* gl_depth_format) {
-  switch (gvr_depth_format) {
-    case GVR_DEPTH_STENCIL_FORMAT_DEPTH_16:
-      *gl_depth_format = GL_DEPTH_COMPONENT16;
-      break;
-    case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24:
-      *gl_depth_format = GL_DEPTH_COMPONENT24;
-      break;
-    case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8:
-      *gl_depth_format = GL_DEPTH24_STENCIL8;
-      break;
-    case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F:
-      *gl_depth_format = GL_DEPTH_COMPONENT32F;
-      break;
-    case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8:
-      *gl_depth_format = GL_DEPTH32F_STENCIL8;
-      break;
-    default:
-      return false;
-  }
-  return true;
-}
-
-// Returns true on success, false on failure. If the swap_chain already has a
-// DvrGraphicsContext and gvr buffer, they'll be freed first. If creation fails,
-// the DvrGraphicsContext in the swap_chain will be set to null and the
-// corresponding gvr buffer will be freed.
-bool CreateDvrGraphicsContextAndGvrBuffer(gvr_swap_chain* swap_chain) {
-  if (swap_chain->buffers_.empty()) {
-    ALOGE("Can't create a graphics context for an empty swap chain");
-    return false;
-  }
-
-  // We currently only render the first gvr buffer. Create a DvrGraphicsContext
-  // for the first buffer only.
-  gvr_buffer& buf = swap_chain->buffers_[0];
-  buf.FreeGl();
-
-  bool visible;
-  int z_order;
-  if (swap_chain->graphics_context_ != nullptr) {
-    visible = dvrGraphicsSurfaceGetVisible(swap_chain->graphics_context_);
-    z_order = dvrGraphicsSurfaceGetZOrder(swap_chain->graphics_context_);
-    dvrGraphicsContextDestroy(swap_chain->graphics_context_);
-    swap_chain->graphics_context_ = nullptr;
-  } else {
-    visible = buf.spec.initially_visible;
-    z_order = buf.spec.z_order;
-  }
-
-  int width = 0, height = 0;
-  GLuint texture_id = 0;
-  GLenum texture_target = 0;
-  DvrSurfaceParameter surface_params[] = {
-      DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, false),
-      DVR_SURFACE_PARAMETER_IN(CREATE_GL_CONTEXT, 0),
-      DVR_SURFACE_PARAMETER_IN(WIDTH, buf.spec.size.width),
-      DVR_SURFACE_PARAMETER_IN(HEIGHT, buf.spec.size.height),
-      DVR_SURFACE_PARAMETER_IN(BLUR_BEHIND, buf.spec.blur_behind),
-      DVR_SURFACE_PARAMETER_IN(VISIBLE, visible),
-      DVR_SURFACE_PARAMETER_IN(Z_ORDER, z_order),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &width),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &height),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_TYPE, &texture_target),
-      DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_ID, &texture_id),
-      DVR_SURFACE_PARAMETER_LIST_END,
-  };
-
-  DvrGraphicsContext* graphics_context;
-  int ret = dvrGraphicsContextCreate(surface_params, &graphics_context);
-  if (ret < 0) {
-    ALOGE("dvrGraphicsContextCreate failed: %d (%s)", ret, strerror(-ret));
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return false;
-  }
-
-  // Sanity check that the size of the buffer we allocated from the system is
-  // what we expect
-  if (buf.spec.size != gvr_sizei{width, height}) {
-    ALOGE(
-        "The created surface is the wrong size."
-        " Should be %dx%d, instead got %dx%d.",
-        buf.spec.size.width, buf.spec.size.height, width, height);
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    dvrGraphicsContextDestroy(graphics_context);
-    return false;
-  }
-
-  buf = gvr_buffer(swap_chain->context, buf.spec, texture_id, texture_target);
-  if (buf.frame_buffer == 0) {
-    dvrGraphicsContextDestroy(graphics_context);
-    return false;
-  }
-
-  swap_chain->graphics_context_ = graphics_context;
-  return true;
-}
-
-bool SwapChainResizeBuffer(gvr_swap_chain* swap_chain, int buffer_index) {
-  gvr_buffer& buf = swap_chain->buffers_[buffer_index];
-  buf.FreeGl();
-  gvr_sizei orig_size = buf.spec.size;
-  buf.spec.size = buf.requested_size;
-  bool resize_successful = false;
-  if (buffer_index == 0) {
-    resize_successful = CreateDvrGraphicsContextAndGvrBuffer(swap_chain);
-  } else {
-    buf = gvr_buffer(swap_chain->context, buf.spec, 0, GL_TEXTURE_2D);
-    resize_successful = buf.frame_buffer != 0;
-  }
-
-  if (resize_successful) {
-    // The resize was successful, so clear the resize request
-    buf.requested_size = {-1, -1};
-  } else {
-    ALOGE("Failed to resize buffer. orig_size=%dx%d requested_size=%dx%d.",
-          orig_size.width, orig_size.height, buf.requested_size.width,
-          buf.requested_size.height);
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    buf.spec.size = orig_size;
-  }
-
-  return resize_successful;
-}
-
-void WaitNextFrame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos,
-                   gvr_frame_schedule* out_next_frame_schedule,
-                   bool called_by_app) {
-  if (called_by_app)
-    swap_chain->wait_next_frame_called_by_app_ = true;
-
-  DvrFrameSchedule dvr_schedule;
-  int ret = dvrGraphicsWaitNextFrame(swap_chain->graphics_context_,
-                                     start_delay_nanos, &dvr_schedule);
-  if (ret < 0) {
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return;
-  }
-  if (out_next_frame_schedule) {
-    out_next_frame_schedule->vsync_count = dvr_schedule.vsync_count;
-    out_next_frame_schedule->scheduled_finish.monotonic_system_time_nanos =
-        dvr_schedule.scheduled_frame_finish_ns;
-  }
-
-  DvrPoseAsync pose;
-  ret = dvrPoseGet(swap_chain->context->pose_client_, dvr_schedule.vsync_count,
-                   &pose);
-  if (ret < 0) {
-    ALOGW("dvrPoseGet failed: %d", ret);
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return;
-  }
-
-  swap_chain->context->next_frame_6dof_pose_ = PosefToGvrMatrix(ToPosef(pose));
-
-  for (int i = 0; i < kControllerCount; ++i) {
-    ret = dvrPoseGetController(swap_chain->context->pose_client_, i,
-                               dvr_schedule.vsync_count, &pose);
-    if (ret == 0) {
-      // Silently fail when there are no controllers.
-      swap_chain->context->next_frame_controller_pose_[i] =
-          PosefToGvrMatrix(ToPosef(pose).Inverse());
-    }
-  }
-}
-
-bool VerifyBufferIndex(const std::string& function_name,
-                       const gvr_swap_chain* swap_chain, int index) {
-  if (index > static_cast<int32_t>(swap_chain->buffers_.size())) {
-    ALOGE("%s out of range buffer index. index=%d num_buffers=%zu.",
-          function_name.c_str(), index, swap_chain->buffers_.size());
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return false;
-  }
-  return true;
-}
-
-}  // anonymous namespace
-
-gvr_context* gvr_create(JNIEnv* env, jobject /* app_context */,
-                        jobject /* class_loader */) {
-  std::unique_ptr<gvr_context> context(new gvr_context);
-
-  // Set cpu set to avoid default scheduling randomness.
-  dvrSetCpuPartition(0, "/application/performance");
-
-  context->jni_env_ = env;
-  context->pose_client_ = dvrPoseCreate();
-  if (!context->pose_client_) {
-    ALOGE("Failed to create pose client");
-    return nullptr;
-  }
-
-  context->display_client_ = DisplayClient::Create();
-  if (!context->display_client_) {
-    ALOGE("Failed to create display client");
-    return nullptr;
-  }
-
-  int ret =
-      context->display_client_->GetDisplayMetrics(&context->display_metrics_);
-  if (ret < 0) {
-    ALOGE("Failed to get display metrics: %d (%s)", ret, strerror(-ret));
-    return nullptr;
-  }
-
-  const float* left_fov = context->display_metrics_.left_fov_lrbt.data();
-  context->left_eye_viewport_transform_ =
-      FovToViewportTransform(FovRadiansToDegrees(
-          gvr_rectf{left_fov[0], left_fov[1], left_fov[2], left_fov[3]}));
-
-  const float* right_fov = context->display_metrics_.right_fov_lrbt.data();
-  context->right_eye_viewport_transform_ =
-      FovToViewportTransform(FovRadiansToDegrees(
-          gvr_rectf{right_fov[0], right_fov[1], right_fov[2], right_fov[3]}));
-
-  context->next_frame_6dof_pose_ = GvrIdentityMatrix();
-
-  for (int i = 0; i < kControllerCount; ++i) {
-    context->next_frame_controller_pose_[i] = GvrIdentityMatrix();
-  }
-
-  // Check the system property to force 6DoF when requested 3DoF.
-  char prop_buffer[PROP_VALUE_MAX];
-  if (__system_property_get(kForce6DofProp, prop_buffer) &&
-      (!strncasecmp("1", prop_buffer, PROP_VALUE_MAX) ||
-       !strncasecmp("true", prop_buffer, PROP_VALUE_MAX))) {
-    context->force_6dof_ = true;
-  }
-
-  return context.release();
-}
-
-gvr_version gvr_get_version() {
-  gvr_version version = {};
-  version.major = GVR_SDK_MAJOR_VERSION;
-  version.minor = GVR_SDK_MINOR_VERSION;
-  version.patch = GVR_SDK_PATCH_VERSION;
-  return version;
-}
-
-const char* gvr_get_version_string() { return kVersionString; }
-
-int32_t gvr_get_error(gvr_context* gvr) { return gvr->last_error_; }
-
-int32_t gvr_clear_error(gvr_context* gvr) {
-  int32_t last_error = gvr->last_error_;
-  gvr->last_error_ = GVR_ERROR_NONE;
-  return last_error;
-}
-
-const char* gvr_get_error_string(int32_t error_code) {
-  switch (error_code) {
-    case GVR_ERROR_NONE:
-      return "No error";
-    case GVR_ERROR_CONTROLLER_CREATE_FAILED:
-      return "Creation of GVR controller context failed";
-    case GVR_ERROR_NO_FRAME_AVAILABLE:
-      return "No frame available in swap chain";
-    case GVR_ERROR_INTERNAL:
-      return "Internal error";
-    default:
-      return "(Internal error: unknown error code)";
-  }
-}
-
-const gvr_user_prefs* gvr_get_user_prefs(gvr_context* gvr) {
-  return &gvr->user_prefs_;
-}
-
-int32_t gvr_user_prefs_get_controller_handedness(
-    const gvr_user_prefs* /* user_prefs */) {
-  return GVR_CONTROLLER_RIGHT_HANDED;
-}
-
-gvr_context_::~gvr_context_() {
-  for (gvr_swap_chain* swap_chain : swap_chains_)
-    swap_chain->context = nullptr;
-  if (pose_client_)
-    dvrPoseDestroy(pose_client_);
-}
-
-void gvr_destroy(gvr_context** gvr) {
-  if (!gvr || !(*gvr)) {
-    ALOGW("gvr_destroy: Invalid gvr_context pointer.");
-    return;
-  }
-  delete *gvr;
-  *gvr = nullptr;
-}
-
-void gvr_initialize_gl(gvr_context* /* gvr */) {}
-
-bool gvr_get_async_reprojection_enabled(const gvr_context* /* gvr */) {
-  return true;
-}
-
-void gvr_get_recommended_buffer_viewports(
-    const gvr_context* gvr, gvr_buffer_viewport_list* viewport_list) {
-  gvr_buffer_viewport left(
-      /*buffer_index*/ 0,
-      /*uv*/ {0, .5f, 0, 1}, gvr->left_eye_viewport_transform_, GVR_LEFT_EYE,
-      GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL);
-
-  gvr_buffer_viewport right(
-      /*buffer_index*/ 0,
-      /*uv*/ {.5f, 1, 0, 1}, gvr->right_eye_viewport_transform_, GVR_RIGHT_EYE,
-      GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL);
-
-  viewport_list->viewports.resize(2);
-  viewport_list->viewports[0] = left;
-  viewport_list->viewports[1] = right;
-}
-
-void gvr_get_screen_buffer_viewports(const gvr_context* gvr,
-                                     gvr_buffer_viewport_list* viewport_list) {
-  gvr_get_recommended_buffer_viewports(gvr, viewport_list);
-}
-
-gvr_sizei gvr_get_maximum_effective_render_target_size(const gvr_context* gvr) {
-  return gvr_sizei{
-      static_cast<int32_t>(gvr->display_metrics_.distorted_width),
-      static_cast<int32_t>(gvr->display_metrics_.distorted_height)};
-}
-
-gvr_sizei gvr_get_screen_target_size(const gvr_context* gvr) {
-  // DisplayMetrics returns native_width and native_height for the display in
-  // portrait orientation, which our device is never in. Swap the width and
-  // height to account for this.
-  return gvr_sizei{
-      static_cast<int32_t>(gvr->display_metrics_.display_native_height),
-      static_cast<int32_t>(gvr->display_metrics_.display_native_width)};
-}
-
-void gvr_set_surface_size(gvr_context* gvr,
-                          gvr_sizei /* surface_size_pixels */) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_set_surface_size not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-}
-
-void gvr_distort_to_screen(
-    gvr_context* gvr, int32_t /* texture_id */,
-    const gvr_buffer_viewport_list* /* viewport_list */,
-    gvr_mat4f /* head_space_from_start_space */,
-    gvr_clock_time_point /* target_presentation_time */) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_distort_to_screen not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-}
-
-bool gvr_is_feature_supported(const gvr_context* /*gvr*/, int32_t feature) {
-  return feature == GVR_FEATURE_ASYNC_REPROJECTION ||
-      feature == GVR_FEATURE_HEAD_POSE_6DOF;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Viewports and viewport lists
-/////////////////////////////////////////////////////////////////////////////
-
-bool gvr_buffer_viewport::operator==(const gvr_buffer_viewport_& other) const {
-  return buffer_index == other.buffer_index && uv == other.uv &&
-         eye == other.eye && external_surface_id == other.external_surface_id &&
-         reprojection == other.reprojection &&
-         MatricesAlmostEqual(transform, other.transform, 1e-5f);
-}
-
-gvr_buffer_viewport* gvr_buffer_viewport_create(gvr_context* /* gvr */) {
-  return new gvr_buffer_viewport;
-}
-
-void gvr_buffer_viewport_destroy(gvr_buffer_viewport** viewport) {
-  if (viewport) {
-    delete *viewport;
-    *viewport = nullptr;
-  }
-}
-
-gvr_rectf gvr_buffer_viewport_get_source_uv(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->uv;
-}
-
-void gvr_buffer_viewport_set_source_uv(gvr_buffer_viewport* viewport,
-                                       gvr_rectf uv) {
-  viewport->uv = uv;
-}
-
-gvr_rectf gvr_buffer_viewport_get_source_fov(
-    const gvr_buffer_viewport* viewport) {
-  return ViewportTransformToFov(viewport->transform);
-}
-
-void gvr_buffer_viewport_set_source_fov(gvr_buffer_viewport* viewport,
-                                        gvr_rectf fov) {
-  viewport->transform = FovToViewportTransform(fov);
-}
-
-gvr_mat4f gvr_buffer_viewport_get_transform(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->transform;
-}
-
-void gvr_buffer_viewport_set_transform(gvr_buffer_viewport* viewport,
-                                       gvr_mat4f transform) {
-  viewport->transform = transform;
-}
-
-int32_t gvr_buffer_viewport_get_target_eye(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->eye;
-}
-
-void gvr_buffer_viewport_set_target_eye(gvr_buffer_viewport* viewport,
-                                        int32_t index) {
-  viewport->eye = index;
-}
-
-int32_t gvr_buffer_viewport_get_source_buffer_index(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->buffer_index;
-}
-
-void gvr_buffer_viewport_set_source_buffer_index(gvr_buffer_viewport* viewport,
-                                                 int32_t buffer_index) {
-  viewport->buffer_index = buffer_index;
-}
-
-int32_t gvr_buffer_viewport_get_external_surface_id(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->external_surface_id;
-}
-
-void gvr_buffer_viewport_set_external_surface_id(gvr_buffer_viewport* viewport,
-                                                 int32_t external_surface_id) {
-  viewport->external_surface_id = external_surface_id;
-}
-
-int32_t gvr_buffer_viewport_get_reprojection(
-    const gvr_buffer_viewport* viewport) {
-  return viewport->reprojection;
-}
-
-void gvr_buffer_viewport_set_reprojection(gvr_buffer_viewport* viewport,
-                                          int32_t reprojection) {
-  viewport->reprojection = static_cast<gvr_reprojection>(reprojection);
-}
-
-bool gvr_buffer_viewport_equal(const gvr_buffer_viewport* a,
-                               const gvr_buffer_viewport* b) {
-  return *a == *b;
-}
-
-gvr_buffer_viewport_list* gvr_buffer_viewport_list_create(
-    const gvr_context* /* gvr */) {
-  return new gvr_buffer_viewport_list;
-}
-
-void gvr_buffer_viewport_list_destroy(
-    gvr_buffer_viewport_list** viewport_list) {
-  if (!viewport_list || !(*viewport_list)) {
-    ALOGW("gvr_buffer_viewport_list_destroy: Invalid list pointer.");
-    return;
-  }
-  delete *viewport_list;
-  *viewport_list = nullptr;
-}
-
-size_t gvr_buffer_viewport_list_get_size(
-    const gvr_buffer_viewport_list* viewport_list) {
-  return viewport_list->viewports.size();
-}
-
-void gvr_buffer_viewport_list_get_item(
-    const gvr_buffer_viewport_list* viewport_list, size_t index,
-    gvr_buffer_viewport* viewport) {
-  *viewport = viewport_list->viewports[index];
-}
-
-void gvr_buffer_viewport_list_set_item(gvr_buffer_viewport_list* viewport_list,
-                                       size_t index,
-                                       const gvr_buffer_viewport* viewport) {
-  if (index < viewport_list->viewports.size())
-    viewport_list->viewports[index] = *viewport;
-  else
-    viewport_list->viewports.push_back(*viewport);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Swapchains and frames
-/////////////////////////////////////////////////////////////////////////////
-
-gvr_buffer_spec* gvr_buffer_spec_create(gvr_context* /* gvr */) {
-  return new gvr_buffer_spec;
-}
-
-void gvr_buffer_spec_destroy(gvr_buffer_spec** spec) {
-  if (spec) {
-    delete *spec;
-    *spec = nullptr;
-  }
-}
-
-gvr_sizei gvr_buffer_spec_get_size(const gvr_buffer_spec* spec) {
-  return spec->size;
-}
-
-void gvr_buffer_spec_set_size(gvr_buffer_spec* spec, gvr_sizei size) {
-  spec->size = size;
-}
-
-int32_t gvr_buffer_spec_get_samples(const gvr_buffer_spec* spec) {
-  return spec->msaa_samples;
-}
-
-void gvr_buffer_spec_set_samples(gvr_buffer_spec* spec, int32_t num_samples) {
-  spec->msaa_samples = num_samples;
-}
-
-void gvr_buffer_spec_set_color_format(gvr_buffer_spec* spec,
-                                      int32_t color_format) {
-  spec->color_format = color_format;
-}
-
-void gvr_buffer_spec_set_depth_stencil_format(gvr_buffer_spec* spec,
-                                              int32_t depth_stencil_format) {
-  spec->depth_stencil_format = depth_stencil_format;
-}
-
-void gvr_buffer_spec_set_z_order(gvr_buffer_spec* spec, int z_order) {
-  spec->z_order = z_order;
-}
-
-void gvr_buffer_spec_set_visibility(gvr_buffer_spec* spec,
-                                    int32_t visibility) {
-  spec->initially_visible = (visibility != GVR_INVISIBLE);
-}
-
-void gvr_buffer_spec_set_blur_behind(gvr_buffer_spec* spec,
-                                     int32_t blur_behind) {
-  spec->blur_behind = (blur_behind != GVR_BLUR_BEHIND_FALSE);
-}
-
-void gvr_buffer::SetDefaults() {
-  spec = gvr_buffer_spec();
-  frame_buffer = 0;
-  color_render_buffer = 0;
-  depth_stencil_render_buffer = 0;
-  requested_size = {-1, -1};
-}
-
-gvr_buffer::gvr_buffer() { SetDefaults(); }
-
-gvr_buffer::gvr_buffer(gvr_context* gvr, const gvr_buffer_spec& spec_in,
-                       GLuint texture_id, GLenum texture_target) {
-  SetDefaults();
-  spec = spec_in;
-
-  glGetError();  // Clear error state
-  glGenFramebuffers(1, &frame_buffer);
-  glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);
-
-  if (texture_id == 0) {
-    GLenum gl_color_format;
-    if (!GetGlColorFormat(spec.color_format, &gl_color_format)) {
-      ALOGE("Unknown color format: %d", spec.color_format);
-      gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-      FreeGl();
-      return;
-    }
-
-    glGenRenderbuffers(1, &color_render_buffer);
-    glBindRenderbuffer(GL_RENDERBUFFER, color_render_buffer);
-    if (spec.msaa_samples < 2) {
-      glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format, spec.size.width,
-                            spec.size.height);
-    } else {
-      glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples,
-                                       gl_color_format, spec.size.width,
-                                       spec.size.height);
-    }
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                              GL_RENDERBUFFER, color_render_buffer);
-  } else {
-    if (spec.msaa_samples < 2) {
-      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                             texture_target, texture_id, 0);
-    } else {
-      glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                           texture_target, texture_id, 0,
-                                           spec.msaa_samples);
-    }
-  }
-
-  if (spec.depth_stencil_format != GVR_DEPTH_STENCIL_FORMAT_NONE) {
-    GLenum gl_depth_format;
-    if (!GetGlDepthFormat(spec.depth_stencil_format, &gl_depth_format)) {
-      ALOGE("Unknown depth/stencil format: %d", spec.depth_stencil_format);
-      gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-      FreeGl();
-      return;
-    }
-
-    glGenRenderbuffers(1, &depth_stencil_render_buffer);
-    glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_render_buffer);
-    if (spec.msaa_samples < 2) {
-      glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format, spec.size.width,
-                            spec.size.height);
-    } else {
-      glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples,
-                                       gl_depth_format, spec.size.width,
-                                       spec.size.height);
-    }
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-                              GL_RENDERBUFFER, depth_stencil_render_buffer);
-  }
-
-  GLenum gl_error = glGetError();
-  if (gl_error != GL_NO_ERROR) {
-    ALOGE("GL error after creating framebuffer: %d", gl_error);
-    gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-    FreeGl();
-    return;
-  }
-
-  GLenum framebuffer_complete_result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-  if (framebuffer_complete_result != GL_FRAMEBUFFER_COMPLETE) {
-    ALOGE("Framebuffer setup failed. glCheckFramebufferStatus returned %d",
-          framebuffer_complete_result);
-    gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-    FreeGl();
-    return;
-  }
-}
-
-void gvr_buffer::FreeGl() {
-  if (frame_buffer != 0) {
-    glDeleteFramebuffers(1, &frame_buffer);
-    frame_buffer = 0;
-  }
-  if (color_render_buffer != 0) {
-    glDeleteRenderbuffers(1, &color_render_buffer);
-    color_render_buffer = 0;
-  }
-  if (depth_stencil_render_buffer != 0) {
-    glDeleteRenderbuffers(1, &depth_stencil_render_buffer);
-    depth_stencil_render_buffer = 0;
-  }
-}
-
-gvr_buffer::~gvr_buffer() { FreeGl(); }
-
-gvr_buffer::gvr_buffer(gvr_buffer&& other) {
-  spec = other.spec;
-  frame_buffer = other.frame_buffer;
-  color_render_buffer = other.color_render_buffer;
-  depth_stencil_render_buffer = other.depth_stencil_render_buffer;
-  requested_size = other.requested_size;
-  other.SetDefaults();
-}
-
-gvr_buffer& gvr_buffer::operator=(gvr_buffer&& other) {
-  if (this == &other)
-    return *this;
-  spec = other.spec;
-  frame_buffer = other.frame_buffer;
-  color_render_buffer = other.color_render_buffer;
-  depth_stencil_render_buffer = other.depth_stencil_render_buffer;
-  requested_size = other.requested_size;
-  other.SetDefaults();
-  return *this;
-}
-
-gvr_swap_chain* gvr_swap_chain_create(gvr_context* gvr,
-                                      const gvr_buffer_spec** buffers,
-                                      int32_t count) {
-  if (count == 0) {
-    ALOGE("At least one buffer must be requested");
-    gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-    return nullptr;
-  }
-
-  // We only support one buffer, but it's common for gvr apps to use more than
-  // one. Print an error to the log if the app requests more than one buffer,
-  // but continue on. We'll only render the first buffer in that case.
-  if (count > 1) {
-    ALOGE(
-        "Only one buffer is supported but the app requested %d."
-        " Only the first buffer will be rendered.",
-        count);
-  }
-
-  std::unique_ptr<gvr_swap_chain> swap_chain(new gvr_swap_chain(gvr));
-
-  // The first buffer gets a DvrGraphicsContext, which contains the surface we
-  // pass to displayd for rendering.
-  swap_chain->buffers_.push_back(gvr_buffer());
-  swap_chain->buffers_.back().spec = *buffers[0];
-  if (!CreateDvrGraphicsContextAndGvrBuffer(swap_chain.get()))
-    return nullptr;
-
-  // The rest of the buffers, which we don't render for now, get color render
-  // buffers.
-  for (int i = 1; i < count; ++i) {
-    swap_chain->buffers_.push_back(
-        gvr_buffer(gvr, *buffers[i], 0, GL_TEXTURE_2D));
-    if (swap_chain->buffers_.back().frame_buffer == 0)
-      return nullptr;
-  }
-
-  gvr->swap_chains_.push_back(swap_chain.get());
-  return swap_chain.release();
-}
-
-gvr_swap_chain_::~gvr_swap_chain_() {
-  if (context) {
-    auto iter = std::find(std::begin(context->swap_chains_),
-                          std::end(context->swap_chains_), this);
-    if (iter != context->swap_chains_.end())
-      context->swap_chains_.erase(iter);
-  }
-  buffers_.clear();
-  if (graphics_context_ != nullptr)
-    dvrGraphicsContextDestroy(graphics_context_);
-}
-
-void gvr_swap_chain_destroy(gvr_swap_chain** swap_chain) {
-  if (!swap_chain || !(*swap_chain)) {
-    ALOGW("gvr_swap_chain_destroy: Invalid swap chain pointer.");
-    return;
-  }
-  delete *swap_chain;
-  *swap_chain = nullptr;
-}
-
-int32_t gvr_swap_chain_get_buffer_count(const gvr_swap_chain* swap_chain) {
-  return swap_chain ? static_cast<int32_t>(swap_chain->buffers_.size()) : 0;
-}
-
-gvr_sizei gvr_swap_chain_get_buffer_size(gvr_swap_chain* swap_chain,
-                                         int32_t index) {
-  if (!VerifyBufferIndex("gvr_swap_chain_get_buffer_size", swap_chain, index))
-    return gvr_sizei{0, 0};
-
-  gvr_buffer& buf = swap_chain->buffers_[index];
-  if (buf.requested_size != gvr_sizei{-1, -1})
-    return buf.requested_size;
-  else
-    return buf.spec.size;
-}
-
-void gvr_swap_chain_resize_buffer(gvr_swap_chain* swap_chain, int32_t index,
-                                  gvr_sizei size) {
-  if (!VerifyBufferIndex("gvr_swap_chain_resize_buffer", swap_chain, index))
-    return;
-
-  gvr_buffer& buf = swap_chain->buffers_[index];
-  if (size != buf.spec.size)
-    buf.requested_size = size;
-  else
-    buf.requested_size = {-1, -1};
-}
-
-gvr_frame* gvr_swap_chain_acquire_frame(gvr_swap_chain* swap_chain) {
-  if (!swap_chain)
-    return nullptr;
-
-  if (swap_chain->frame_acquired_) {
-    gvr_set_error(swap_chain->context, GVR_ERROR_NO_FRAME_AVAILABLE);
-    return nullptr;
-  }
-
-  // Resize buffers if necessary
-  for (int i = 0; i < static_cast<int>(swap_chain->buffers_.size()); ++i) {
-    gvr_buffer& buf = swap_chain->buffers_[i];
-    if (buf.requested_size != gvr_sizei{-1, -1}) {
-      if (!SwapChainResizeBuffer(swap_chain, i))
-        return nullptr;
-    }
-  }
-
-  // Only call gvr_wait_next_frame() if the app didn't call it already.
-  if (!swap_chain->wait_next_frame_called_by_app_)
-    WaitNextFrame(swap_chain, 0, nullptr, /*called_by_app*/ false);
-
-  int ret = dvrBeginRenderFrame(swap_chain->graphics_context_);
-  if (ret < 0) {
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return nullptr;
-  }
-
-  swap_chain->frame_acquired_ = true;
-  return GetFrameFromSwapChain(swap_chain);
-}
-
-void gvr_frame_bind_buffer(gvr_frame* frame, int32_t index) {
-  gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
-  if (!VerifyBufferIndex("gvr_frame_bind_buffer", swap_chain, index))
-    return;
-  glBindFramebuffer(GL_FRAMEBUFFER, swap_chain->buffers_[index].frame_buffer);
-}
-
-void gvr_frame_unbind(gvr_frame* /* frame */) {
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-gvr_sizei gvr_frame_get_buffer_size(const gvr_frame* frame, int32_t index) {
-  const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
-  if (!VerifyBufferIndex("gvr_frame_get_buffer_size", swap_chain, index))
-    return gvr_sizei{0, 0};
-  return swap_chain->buffers_[index].spec.size;
-}
-
-int32_t gvr_frame_get_framebuffer_object(const gvr_frame* frame,
-                                         int32_t index) {
-  const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
-  if (!VerifyBufferIndex("gvr_frame_get_framebuffer_object", swap_chain, index))
-    return 0;
-  return swap_chain->buffers_[index].frame_buffer;
-}
-
-void gvr_frame_submit(gvr_frame** frame, const gvr_buffer_viewport_list* list,
-                      gvr_mat4f head_space_from_start_space) {
-  if (!frame)
-    return;
-
-  gvr_swap_chain* swap_chain = GetSwapChainForFrame(*frame);
-
-  if (!swap_chain->frame_acquired_) {
-    ALOGE("Frame was never acquired before being submitted");
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return;
-  }
-
-  *frame = nullptr;
-  swap_chain->frame_acquired_ = false;
-
-  // Currently, support for arbitrary buffer viewport configs is very limited.
-  // We assume that the first two viewports have to be the recommended color
-  // buffer viewports, followed by pairs of external external buffer viewports
-  // for video rendering.
-  gvr_buffer_viewport_list supported_viewports;
-  gvr_get_recommended_buffer_viewports(swap_chain->context,
-                                       &supported_viewports);
-  for (size_t i = 0; i < supported_viewports.viewports.size(); ++i) {
-    if (i >= list->viewports.size() ||
-        supported_viewports.viewports[i] != list->viewports[i]) {
-      ALOGE("Custom viewport configurations are not fully supported.");
-      gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-      return;
-    }
-  }
-
-  for (size_t i = supported_viewports.viewports.size();
-       i < list->viewports.size(); ++i) {
-    int32_t external_surface_id = list->viewports[i].external_surface_id;
-    // Ignore additional custom buffer viewport for now, only those buffer
-    // viewports backed by external surfaces are supported.
-    // TODO(b/31442094, b/31771861, 28954457) Add full GVR buffer viewport
-    // support.
-    if (external_surface_id == GVR_EXTERNAL_SURFACE_ID_NONE)
-      continue;
-
-    auto surface_it = swap_chain->external_surfaces_.find(external_surface_id);
-    if (surface_it == swap_chain->external_surfaces_.end()) {
-      ALOGE("Cannot find external_surface by id: %d.", external_surface_id);
-      gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-      return;
-    }
-
-    // Pass the transfrom matrix of video mesh to displayd.
-    dvrGraphicsVideoMeshSurfacePresent(
-        swap_chain->graphics_context_, surface_it->second->video_surface,
-        list->viewports[i].eye,
-        GvrToEigenMatrix(list->viewports[i].transform).data());
-  }
-
-  float32x4_t pose_orientation, pose_translation;
-  GvrToDvrPose(head_space_from_start_space, &pose_orientation,
-               &pose_translation);
-  int ret = dvrSetEdsPose(swap_chain->graphics_context_, pose_orientation,
-                          pose_translation);
-  if (ret < 0)
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-
-  ret = dvrPresent(swap_chain->graphics_context_);
-  if (ret < 0) {
-    gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
-    return;
-  }
-}
-
-void gvr_bind_default_framebuffer(gvr_context* /* gvr */) {
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Head tracking
-/////////////////////////////////////////////////////////////////////////////
-
-gvr_clock_time_point gvr_get_time_point_now() {
-  return gvr_clock_time_point{GetSystemClockNs()};
-}
-
-gvr_mat4f gvr_get_head_space_from_start_space_rotation(
-    const gvr_context* gvr, const gvr_clock_time_point /* time */) {
-  // TODO(steventhomas): Implement prediction according to the supplied time
-  // value.
-  return gvr->force_6dof_ ? gvr->next_frame_6dof_pose_
-                          : Gvr6dofTo3dof(gvr->next_frame_6dof_pose_);
-}
-
-gvr_mat4f gvr_apply_neck_model(const gvr_context* /* gvr */,
-                               gvr_mat4f head_space_from_start_space_rotation,
-                               float /* factor */) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_apply_neck_model not implemented.");
-  return head_space_from_start_space_rotation;
-}
-
-// This is used to turn off sensors to save power. Not relevant for our all in
-// one device.
-void gvr_pause_tracking(gvr_context* /* gvr */) {}
-
-// This is used to turn on sensors. Not relevant for our all in one device.
-void gvr_resume_tracking(gvr_context* /* gvr */) {}
-
-void gvr_reset_tracking(gvr_context* gvr) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_reset_tracking not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-}
-
-void gvr_recenter_tracking(gvr_context* gvr) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_recenter_tracking not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Head mounted display
-/////////////////////////////////////////////////////////////////////////////
-
-bool gvr_set_default_viewer_profile(gvr_context* gvr,
-                                    const char* /* viewer_profile_uri */) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_set_default_viewer_profile not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-  return false;
-}
-
-void gvr_refresh_viewer_profile(gvr_context* /* gvr */) {}
-
-const char* gvr_get_viewer_vendor(const gvr_context* /* gvr */) {
-  return kViewerVendor;
-}
-
-const char* gvr_get_viewer_model(const gvr_context* /* gvr */) {
-  return kViewerModel;
-}
-
-int32_t gvr_get_viewer_type(const gvr_context* /* gvr */) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  // In this case, we will probably need to define a new viewer type that
-  // has 6DoF support.
-  return GVR_VIEWER_TYPE_DAYDREAM;
-}
-
-gvr_mat4f gvr_get_eye_from_head_matrix(const gvr_context* gvr,
-                                       const int32_t eye) {
-  float eye_mult = eye == GVR_LEFT_EYE ? 1 : -1;
-  return GvrTranslationMatrix(
-      .5f * eye_mult * gvr->display_metrics_.inter_lens_distance_m, 0, 0);
-}
-
-gvr_recti gvr_get_window_bounds(const gvr_context* gvr) {
-  // Our app windows are always full screen
-  gvr_sizei screen_size = gvr_get_screen_target_size(gvr);
-  return gvr_recti{0, screen_size.width, 0, screen_size.height};
-}
-
-void gvr_compute_distorted_point(const gvr_context* /* gvr */,
-                                 const int32_t /* eye */,
-                                 const gvr_vec2f /* uv_in */,
-                                 gvr_vec2f /* uv_out */[3]) {
-  // TODO(leandrogracia): this needs to be properly implemented.
-  ALOGE("gvr_compute_distorted_point not implemented.");
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// GVR API extension (from gvr_ext.h)
-/////////////////////////////////////////////////////////////////////////////
-
-gvr_frame_schedule* gvr_frame_schedule_create() {
-  return new gvr_frame_schedule;
-}
-
-void gvr_frame_schedule_destroy(gvr_frame_schedule** schedule) {
-  if (!schedule || !(*schedule)) {
-    ALOGW("gvr_frame_schedule_destroy: Invalid frame schedule pointer.");
-    return;
-  }
-  delete *schedule;
-  *schedule = nullptr;
-}
-
-uint32_t gvr_frame_schedule_get_vsync_count(gvr_frame_schedule* schedule) {
-  return schedule->vsync_count;
-}
-
-gvr_clock_time_point gvr_frame_schedule_get_scheduled_finish(
-    gvr_frame_schedule* schedule) {
-  return schedule->scheduled_finish;
-}
-
-void gvr_wait_next_frame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos,
-                         gvr_frame_schedule* out_next_frame_schedule) {
-  WaitNextFrame(swap_chain, start_delay_nanos, out_next_frame_schedule,
-                /*called_by_app*/ true);
-}
-
-gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr,
-                                                uint32_t vsync_count) {
-  DvrPoseAsync pose;
-  int ret = dvrPoseGet(gvr->pose_client_, vsync_count, &pose);
-  if (ret < 0) {
-    ALOGW("dvrPoseGet failed: %d", ret);
-    gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-    return GvrIdentityMatrix();
-  }
-
-  return PosefToGvrMatrix(ToPosef(pose));
-}
-
-gvr_mat4f gvr_get_head_space_from_start_space_pose(
-    gvr_context* gvr, const gvr_clock_time_point /* time */) {
-  // TODO(leandrogracia): implement prediction based on the provided time.
-  // We need to do the same for the 3dof version too.
-  return gvr->next_frame_6dof_pose_;
-}
-
-void gvr_swap_chain_set_z_order(const gvr_swap_chain* swap_chain, int z_order) {
-  dvrGraphicsSurfaceSetZOrder(swap_chain->graphics_context_, z_order);
-}
-
-bool gvr_experimental_register_perf_event_callback(
-    gvr_context* gvr, int* /* out_handle */, void* /* user_data */,
-    void (* /* event_callback */)(void*, int, float)) {
-  ALOGE("gvr_experimental_register_perf_event_callback not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-  return false;
-}
-
-bool gvr_experimental_unregister_perf_event_callback(gvr_context* gvr,
-                                                     int /* handle */) {
-  ALOGE("gvr_experimental_unregister_perf_event_callback not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-  return false;
-}
-
-const gvr_analytics* gvr_get_analytics(gvr_context* gvr) {
-  ALOGE("gvr_get_analytics not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-  return nullptr;
-}
-
-const gvr_analytics_sample* gvr_analytics_create_sample(
-    const gvr_analytics* analytics) {
-  ALOGE("gvr_analytics_create_sample not implemented.");
-  return nullptr;
-}
-
-const char* gvr_analytics_sample_get_buffer(const gvr_analytics_sample* sample) {
-  ALOGE("gvr_analytics_sample_get_buffer not implemented.");
-  return nullptr;
-}
-
-size_t gvr_analytics_sample_get_buffer_length(
-    const gvr_analytics_sample* sample) {
-  ALOGE("gvr_analytics_sample_get_buffer_length not implemented.");
-  return 0;
-}
-
-void gvr_analytics_destroy_sample(const gvr_analytics_sample** sample) {
-  ALOGE("gvr_analytics_destroy_sample not implemented.");
-}
-
-bool gvr_user_prefs_get_performance_monitoring_enabled(
-    const gvr_user_prefs* /* user_prefs */) {
-  ALOGW("gvr_user_prefs_get_performance_monitoring_enabled not implemented.");
-  return false;
-}
-
-void gvr_enable_context_sharing(gvr_context* gvr,
-                                gvr_egl_context_listener /* handler */,
-                                void* /* user_data */) {
-  ALOGW("gvr_enable_context_sharing not implemented.");
-  gvr_set_error(gvr, GVR_ERROR_INTERNAL);
-}
-
-gvr_mat4f gvr_get_start_space_from_controller_space_pose(
-    gvr_context* gvr, int controller_id,
-    const gvr_clock_time_point /* time */) {
-  if (controller_id < 0 || controller_id >= kControllerCount) {
-    return GvrIdentityMatrix();
-  }
-
-  // TODO(leandrogracia): implement prediction based on the provided time.
-  // We need to do the same for the 3dof version too.
-  return gvr->next_frame_controller_pose_[controller_id];
-}
-
-gvr_external_surface* gvr_external_surface_create(gvr_context* context) {
-  // A |gvr_external_surface| is bound to a DVR Graphics context at the
-  // moment, which means we need an |gvr_swap_chain| created prior to the call
-  // of |gvr_external_surface_create|. Check whether the current GVR context
-  // has |gvr_swap_chain| created. Fail if there is no swap chain created
-  // already.
-  if (context->swap_chains_.empty()) {
-    ALOGE("gvr_external_surface_create: No swapchain has been created yet.");
-    return nullptr;
-  }
-
-  // In case there are multiple swap chains in the context, the first is
-  // implicitly chosen. Actually, this should not happen as current scanline
-  // racing based GVR implementation only supports single swap chain per GVR
-  // context.
-  if (context->swap_chains_.size() > 1) {
-    ALOGW("gvr_external_surface_create: Multiple swap chains detected. "
-          "Choosing the first one but this may yield unexpected results.");
-  }
-  gvr_swap_chain* swap_chain = context->swap_chains_[0];
-  DvrVideoMeshSurface* video_surface = dvrGraphicsVideoMeshSurfaceCreate(
-      swap_chain->graphics_context_);
-
-  if (video_surface == nullptr) {
-    ALOGE("gvr_external_surface_create: Failed to create video mesh surface.");
-    return nullptr;
-  }
-
-  gvr_external_surface* surface = new gvr_external_surface;
-  surface->id = swap_chain->next_external_surface_id_++;
-  surface->swap_chain = swap_chain;
-  surface->video_surface = video_surface;
-
-  // Insert the surface into a lookup table in swap_chain. This will be
-  // needed to by the external_surface_id in |gvr_buffer_viewport|.
-  swap_chain->external_surfaces_.insert({surface->id, surface});
-  return surface;
-}
-
-void gvr_external_surface_destroy(gvr_external_surface** surface) {
-  if (!surface || !(*surface)) {
-    ALOGW("gvr_external_surface_destroy: Invalid external surface pointer.");
-    return;
-  }
-
-  (*surface)->swap_chain->external_surfaces_.erase((*surface)->id);
-  if ((*surface)->video_surface != nullptr) {
-    dvrGraphicsVideoMeshSurfaceDestroy((*surface)->video_surface);
-  }
-
-  delete *surface;
-  *surface = nullptr;
-}
-
-void* gvr_external_surface_get_surface(const gvr_external_surface* surface) {
-  LOG_ALWAYS_FATAL_IF(surface->swap_chain == nullptr ||
-                          surface->swap_chain->context == nullptr ||
-                          surface->swap_chain->context->jni_env_ == nullptr,
-                      "gvr_external_surface_get_surface: Surface must be "
-                      "constructed within a JNIEnv. Check |gvr_create| call.");
-
-  LOG_ALWAYS_FATAL_IF(surface->video_surface == nullptr,
-                      "gvr_external_surface_get_surface: Invalid surface.");
-
-  std::shared_ptr<android::dvr::ProducerQueue> producer_queue =
-      surface->video_surface->client->GetProducerQueue();
-  std::shared_ptr<android::dvr::BufferHubQueueCore> core =
-      android::dvr::BufferHubQueueCore::Create(producer_queue);
-
-  return android_view_Surface_createFromIGraphicBufferProducer(
-      surface->swap_chain->context->jni_env_,
-      new android::dvr::BufferHubQueueProducer(core));
-}
-
-int32_t gvr_external_surface_get_surface_id(
-    const gvr_external_surface* surface) {
-  return surface->id;
-}
diff --git a/libs/vr/libgvr/shim_gvr_controller.cpp b/libs/vr/libgvr/shim_gvr_controller.cpp
deleted file mode 100644
index 0f55903..0000000
--- a/libs/vr/libgvr/shim_gvr_controller.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-#define LOG_TAG "libgvr_controller_shim"
-
-#include <log/log.h>
-#include <vr/gvr/capi/include/gvr_controller.h>
-#include <vr/gvr/capi/include/gvr_types.h>
-
-gvr_controller_context* gvr_controller_create_and_init(int32_t options,
-                                                       gvr_context* context) {
-  ALOGE("gvr_controller_create_and_init not implemented.");
-  return nullptr;
-}
-
-gvr_controller_context* gvr_controller_create_and_init_android(
-    JNIEnv* env, jobject android_context, jobject class_loader, int32_t options,
-    gvr_context* context) {
-  ALOGE("gvr_controller_create_and_init_android not implemented.");
-  return nullptr;
-}
-
-void gvr_controller_destroy(gvr_controller_context** api) {
-  ALOGE("gvr_controller_destroy not implemented.");
-}
-
-gvr_controller_state* gvr_controller_state_create() {
-  ALOGE("gvr_controller_state_create not implemented.");
-  return nullptr;
-}
-
-void gvr_controller_state_destroy(gvr_controller_state** state) {
-  ALOGE("gvr_controller_state_destroy not implemented.");
-}
-
-void gvr_controller_state_update(gvr_controller_context* api, int32_t flags,
-                                 gvr_controller_state* out_state) {
-  ALOGE("gvr_controller_state_update not implemented.");
-}
-
-int64_t gvr_controller_state_get_last_button_timestamp(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_last_button_timestamp not implemented.");
-  return 0;
-}
-
-bool gvr_controller_state_get_button_state(const gvr_controller_state* state,
-                                           int32_t button) {
-  ALOGE("gvr_controller_state_get_button_state not implemented.");
-  return false;
-}
-
-bool gvr_controller_state_get_button_down(const gvr_controller_state* state,
-                                          int32_t button) {
-  ALOGE("gvr_controller_state_get_button_down not implemented.");
-  return false;
-}
-
-bool gvr_controller_state_get_button_up(const gvr_controller_state* state,
-                                        int32_t button) {
-  ALOGE("gvr_controller_state_get_button_up not implemented.");
-  return false;
-}
-
-bool gvr_controller_state_is_touching(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_is_touching not implemented.");
-  return false;
-}
-
-gvr_vec2f gvr_controller_state_get_touch_pos(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_touch_pos not implemented.");
-  return {0.0f, 0.0f};
-}
-
-bool gvr_controller_state_get_touch_down(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_touch_down not implemented.");
-  return false;
-}
-
-bool gvr_controller_state_get_touch_up(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_touch_up not implemented.");
-  return false;
-}
-
-int64_t gvr_controller_state_get_last_touch_timestamp(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_last_touch_timestamp not implemented.");
-  return 0;
-}
-
-gvr_quatf gvr_controller_state_get_orientation(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_orientation not implemented.");
-  return {0.0f, 0.0f, 0.0f, 0.0f};
-}
-
-int64_t gvr_controller_state_get_last_orientation_timestamp(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_last_orientation_timestamp not implemented.");
-  return 0;
-}
-
-const char* gvr_controller_api_status_to_string(int32_t status) {
-  ALOGE("gvr_controller_api_status_to_string not implemented.");
-  return nullptr;
-}
-
-const char* gvr_controller_connection_state_to_string(int32_t state) {
-  ALOGE("gvr_controller_connection_state_to_string not implemented.");
-  return nullptr;
-}
-
-const char* gvr_controller_button_to_string(int32_t button) {
-  ALOGE("gvr_controller_button_to_string not implemented.");
-  return nullptr;
-}
-
-int32_t gvr_controller_get_default_options() {
-  ALOGE("gvr_controller_get_default_options not implemented.");
-  return 0;
-}
-
-void gvr_controller_pause(gvr_controller_context* api) {
-  ALOGE("gvr_controller_pause not implemented.");
-}
-
-void gvr_controller_resume(gvr_controller_context* api) {
-  ALOGE("gvr_controller_resume not implemented.");
-}
-
-int32_t gvr_controller_state_get_api_status(const gvr_controller_state* state) {
-  return GVR_CONTROLLER_API_OK;
-}
-
-int32_t gvr_controller_state_get_connection_state(
-    const gvr_controller_state* state) {
-  return GVR_CONTROLLER_CONNECTED;
-}
-
-gvr_vec3f gvr_controller_state_get_gyro(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_gyro not implemented.");
-  return {0.0, 0.0, 0.0};
-}
-
-gvr_vec3f gvr_controller_state_get_accel(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_accel not implemented.");
-  return {0.0, 0.0, 0.0};
-}
-
-int64_t gvr_controller_state_get_last_gyro_timestamp(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_last_gyro_timestamp not implemented.");
-  return 0;
-}
-
-int64_t gvr_controller_state_get_last_accel_timestamp(
-    const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_last_accel_timestamp not implemented.");
-  return 0;
-}
-
-bool gvr_controller_state_get_recentered(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_recentered not implemented.");
-  return false;
-}
-
-bool gvr_controller_state_get_recentering(const gvr_controller_state* state) {
-  ALOGE("gvr_controller_state_get_recentering not implemented.");
-  return false;
-}
diff --git a/libs/vr/libgvr/shim_gvr_private.cpp b/libs/vr/libgvr/shim_gvr_private.cpp
deleted file mode 100644
index 25a5110..0000000
--- a/libs/vr/libgvr/shim_gvr_private.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-#define LOG_TAG "libgvr_shim_private"
-
-#include <log/log.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/internal_types.h>
-#include <vr/gvr/capi/include/gvr.h>
-#include <vr/gvr/capi/src/gvr_private.h>
-
-#include <pdx/rpc/remote_method.h>
-#include "deviceparams/CardboardDevice.nolite.pb.h"
-
-bool gvr_set_async_reprojection_enabled(gvr_context* /* gvr */,
-                                        bool /* enabled */) {
-  return true;
-}
-
-void gvr_on_surface_created_reprojection_thread(gvr_context* /* gvr */) {}
-
-void gvr_render_reprojection_thread(gvr_context* /* gvr */) {}
-
-void gvr_on_pause_reprojection_thread(gvr_context* /* gvr */) {}
-
-void gvr_update_surface_reprojection_thread(
-    gvr_context* /* gvr */, int32_t /* surface_id */, int32_t /* texture_id */,
-    gvr_clock_time_point /* timestamp */, gvr_mat4f /* surface_transform */) {
-  ALOGE("gvr_update_surface_reprojection_thread not implemented");
-}
-
-void gvr_remove_all_surfaces_reprojection_thread(gvr_context* /* gvr */) {
-  ALOGE("gvr_remove_all_surfaces_reprojection_thread not implemented");
-}
-
-void gvr_reconnect_sensors(gvr_context* /* gvr */) {
-  ALOGE("gvr_reconnect_sensors not implemented");
-}
-
-bool gvr_set_viewer_params(gvr_context* gvr,
-                           const void* serialized_viewer_params,
-                           size_t serialized_viewer_params_size_bytes) {
-  std::string serialized_device_params_string(
-      reinterpret_cast<const char*>(serialized_viewer_params),
-      serialized_viewer_params_size_bytes);
-  std::unique_ptr<proto::DeviceParams> device_params(new proto::DeviceParams);
-  if (!device_params->ParseFromString(serialized_device_params_string)) {
-    ALOGE("Invalid serialized Cardboard DeviceParams");
-    return false;
-  }
-
-  android::dvr::ViewerParams viewer_params;
-
-  viewer_params.screen_to_lens_distance =
-      device_params->screen_to_lens_distance();
-  viewer_params.inter_lens_distance = device_params->inter_lens_distance();
-  for (int i = 0; i < device_params->left_eye_field_of_view_angles_size();
-       ++i) {
-    viewer_params.left_eye_field_of_view_angles.push_back(
-        device_params->left_eye_field_of_view_angles(i));
-  }
-
-  viewer_params.vertical_alignment =
-      static_cast<android::dvr::ViewerParams::VerticalAlignmentType>(
-          device_params->vertical_alignment());
-  viewer_params.tray_to_lens_distance = device_params->tray_to_lens_distance();
-
-  // TODO(hendrikw) Leave the g and b coefficients empty until we support
-  // chromatic aberration correction.
-  for (int i = 0; i < device_params->distortion_coefficients_size(); ++i) {
-    viewer_params.distortion_coefficients_r.push_back(
-        device_params->distortion_coefficients(i));
-  }
-
-  viewer_params.screen_center_to_lens_distance =
-      viewer_params.inter_lens_distance / 2.0;
-  if (device_params->has_internal()) {
-    for (int i = 0; i < device_params->internal().eye_orientations_size();
-         ++i) {
-      viewer_params.eye_orientations.push_back(
-          static_cast<android::dvr::ViewerParams::EyeOrientation>(
-              device_params->internal().eye_orientations(i)));
-    }
-
-    if (device_params->internal().has_screen_center_to_lens_distance())
-      viewer_params.screen_center_to_lens_distance =
-          device_params->internal().screen_center_to_lens_distance();
-  }
-
-  if (device_params->has_daydream_internal()) {
-    viewer_params.daydream_internal.version =
-        device_params->daydream_internal().version();
-    for (int i = 0;
-         i < device_params->daydream_internal().alignment_markers_size(); ++i) {
-      viewer_params.daydream_internal.alignment_markers.push_back(
-          {device_params->daydream_internal().alignment_markers(i).horizontal(),
-           device_params->daydream_internal().alignment_markers(i).vertical()});
-    }
-  }
-
-  gvr->display_client_->SetViewerParams(viewer_params);
-  return true;
-}
-
-void gvr_set_lens_offset(gvr_context* /* gvr */, gvr_vec2f /* offset */) {
-  ALOGE("gvr_set_lens_offset not implemented");
-}
-
-void gvr_set_display_metrics(gvr_context* /* gvr */,
-                             gvr_sizei /* size_pixels */,
-                             gvr_vec2f /* meters_per_pixel */,
-                             float /* border_size_meters */) {
-  ALOGE("gvr_set_display_metrics not implemented");
-}
-
-void gvr_set_display_output_rotation(gvr_context* /* gvr */,
-                                     int /* display_output_rotation */) {
-  ALOGE("gvr_set_display_output_rotation not implemented");
-}
-
-float gvr_get_border_size_meters(const gvr_context* /* gvr */) {
-  ALOGE("gvr_get_border_size_meters not implemented");
-  return 0.0f;
-}
-
-bool gvr_check_surface_size_changed(gvr_context* /* gvr */) { return false; }
-
-gvr_sizei gvr_get_surface_size(const gvr_context* /* gvr */) {
-  ALOGE("gvr_get_surface_size not implemented");
-  return {0, 0};
-}
-
-void gvr_set_back_gesture_event_handler(gvr_context* /* gvr */,
-                                        event_handler /* handler */,
-                                        void* /* user_data */) {
-  ALOGE("gvr_set_back_gesture_event_handler not implemented");
-}
-
-gvr_tracker_state* gvr_pause_tracking_get_state(gvr_context* /* gvr */) {
-  ALOGE("gvr_pause_tracking_get_state not implemented");
-  return nullptr;
-}
-
-void gvr_resume_tracking_set_state(gvr_context* /* gvr */,
-                                   gvr_tracker_state* /* tracker_state */) {
-  ALOGE("gvr_resume_tracking_set_state not implemented");
-}
-
-void gvr_set_ignore_manual_tracker_pause_resume(gvr_context* /* gvr */,
-                                                bool /* should_ignore */) {
-  ALOGE("gvr_set_ignore_manual_tracker_pause_resume not implemented");
-}
-
-gvr_tracker_state* gvr_tracker_state_create(
-    const char* /* tracker_state_buffer */, size_t /* buf_size */) {
-  ALOGE("gvr_tracker_state_create not implemented");
-  return nullptr;
-}
-
-size_t gvr_tracker_state_get_buffer_size(
-    gvr_tracker_state* /* tracker_state */) {
-  ALOGE("gvr_tracker_state_get_buffer_size not implemented");
-  return 0;
-}
-
-const char* gvr_tracker_state_get_buffer(
-    gvr_tracker_state* /* tracker_state */) {
-  ALOGE("gvr_tracker_state_get_buffer not implemented");
-  return nullptr;
-}
-
-void gvr_tracker_state_destroy(gvr_tracker_state** /* tracker_state */) {
-  ALOGE("gvr_tracker_state_destroy not implemented");
-}
-
-gvr_display_synchronizer* gvr_display_synchronizer_create() {
-  // We don't actually support (or need) any of the synchronizer functionality,
-  // but if we return null here the gvr setup code in the app fails. Instead
-  // return a dummy object that does nothing, which allows gvr apps to work.
-  return new gvr_display_synchronizer;
-}
-
-void gvr_display_synchronizer_destroy(gvr_display_synchronizer** synchronizer) {
-  if (synchronizer) {
-    delete *synchronizer;
-    *synchronizer = nullptr;
-  }
-}
-
-void gvr_display_synchronizer_reset(
-    gvr_display_synchronizer* /* synchronizer */,
-    int64_t /* expected_interval_nanos */, int64_t /* vsync_offset_nanos */) {}
-
-void gvr_display_synchronizer_update(
-    gvr_display_synchronizer* /* synchronizer */,
-    gvr_clock_time_point /* vsync_time */, int32_t /* rotation */) {}
-
-void gvr_set_display_synchronizer(
-    gvr_context* /* gvr */, gvr_display_synchronizer* /* synchronizer */) {}
-
-void gvr_set_error(gvr_context* gvr, int32_t error_code) {
-  if (gvr->last_error_ != GVR_ERROR_NONE) {
-    ALOGW("Overwriting existing error code: %d (%s)", gvr->last_error_,
-          gvr_get_error_string(gvr->last_error_));
-  }
-  gvr->last_error_ = error_code;
-}
-
-void gvr_pause(gvr_context* gvr) {
-  if (gvr == nullptr) {
-    ALOGW("gvr_pause called with a null gvr_context. This is a bug.");
-    return;
-  }
-  for (gvr_swap_chain* swap_chain : gvr->swap_chains_) {
-    if (swap_chain->graphics_context_)
-      dvrGraphicsSurfaceSetVisible(swap_chain->graphics_context_, 0);
-  }
-}
-
-void gvr_resume(gvr_context* gvr) {
-  if (gvr == nullptr) {
-    ALOGW("gvr_resume called with a null gvr_context. This is a bug.");
-    return;
-  }
-  for (gvr_swap_chain* swap_chain : gvr->swap_chains_) {
-    if (swap_chain->graphics_context_)
-      dvrGraphicsSurfaceSetVisible(swap_chain->graphics_context_, 1);
-  }
-}
-
-void gvr_dump_debug_data(gvr_context* /* gvr */) {}
-
-bool gvr_using_vr_display_service(gvr_context* /* gvr */) { return true; }
-
-void gvr_request_context_sharing(gvr_context* /* gvr */,
-                                 gvr_egl_context_listener /* handler */,
-                                 void* /* user_data */) {}
diff --git a/services/vr/vr_manager/Android.mk b/libs/vr/libvr_manager/Android.mk
similarity index 79%
rename from services/vr/vr_manager/Android.mk
rename to libs/vr/libvr_manager/Android.mk
index 54b1c1a..e9987f7 100644
--- a/services/vr/vr_manager/Android.mk
+++ b/libs/vr/libvr_manager/Android.mk
@@ -14,11 +14,16 @@
 
 LOCAL_PATH := $(call my-dir)
 
+exported_include_dirs := \
+  $(LOCAL_PATH)/include
+
+include_dirs := \
+  frameworks/native/include/vr/vr_manager \
+  $(exported_include_dirs)
+
 src_files := \
   vr_manager.cpp \
-
-inc_files := \
-  frameworks/native/include/vr/vr_manager
+  trusted_uids.cpp
 
 static_libs := \
   libutils \
@@ -26,13 +31,12 @@
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(src_files)
-LOCAL_C_INCLUDES := $(inc_files)
+LOCAL_C_INCLUDES := $(include_dirs)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(exported_include_dirs)
 LOCAL_CFLAGS += -Wall
 LOCAL_CFLAGS += -Werror
 LOCAL_CFLAGS += -Wunused
 LOCAL_CFLAGS += -Wunreachable-code
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(inc_files)
-#LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
 LOCAL_STATIC_LIBRARIES := $(static_libs)
 LOCAL_MODULE := libvr_manager
 include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h b/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h
new file mode 100644
index 0000000..4496fbf
--- /dev/null
+++ b/libs/vr/libvr_manager/include/private/dvr/trusted_uids.h
@@ -0,0 +1,33 @@
+#ifndef ANDROID_DVR_TRUSTED_UIDS_H_
+#define ANDROID_DVR_TRUSTED_UIDS_H_
+
+#include <sys/types.h>
+
+namespace android {
+namespace dvr {
+
+/**
+ * Tells if a provided UID can be trusted to access restricted VR APIs.
+ *
+ * UID trust is based on the android.permission.RESTRICTED_VR_ACCESS permission.
+ * AID_SYSTEM and AID_ROOT are automatically trusted by Android.
+ *
+ * UIDs are guaranteed not to be reused until the next reboot even in case
+ * of package reinstall. For performance reasons this method caches results by
+ * default, as otherwise every check would trigger a Java call.
+ *
+ * This function is thread-safe.
+ *
+ * @param uid The uid to check.
+ * @param use_cache If true any cached result for the provided uid will be
+ *     reused. If false this call will reach the Application Manager Service
+ *     in Java to get updated values. Any updates will be stored in the cache.
+ * @return true if the uid is trusted, false if not or if the VR Manager Service
+ *         could not be reached to verify the uid.
+ */
+bool IsTrustedUid(uid_t uid, bool use_cache = true);
+
+}  // namespace dvr
+}  // namespace android
+
+#endif  // ANDROID_DVR_TRUSTED_UIDS_H_
diff --git a/libs/vr/libvr_manager/trusted_uids.cpp b/libs/vr/libvr_manager/trusted_uids.cpp
new file mode 100644
index 0000000..4228a05
--- /dev/null
+++ b/libs/vr/libvr_manager/trusted_uids.cpp
@@ -0,0 +1,51 @@
+#include "private/dvr/trusted_uids.h"
+
+#include <mutex>
+#include <unordered_map>
+
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
+#include <private/android_filesystem_config.h>
+#include <utils/String16.h>
+#include <vr/vr_manager/vr_manager.h>
+
+namespace android {
+namespace dvr {
+
+bool IsTrustedUid(uid_t uid, bool use_cache) {
+  static std::unordered_map<uid_t, bool> uid_cache;
+  static std::mutex uid_cache_mutex;
+
+  // Whitelist requests from the system UID.
+  // These are already whitelisted by the permission service, but it might not
+  // be available if the ActivityManagerService is up during boot.
+  // This ensures the correct result for system services while booting up.
+  if (uid == AID_SYSTEM)
+    return true;
+
+  std::lock_guard<std::mutex> lock(uid_cache_mutex);
+
+  if (use_cache) {
+    auto it = uid_cache.find(uid);
+    if (it != uid_cache.end())
+      return it->second;
+  }
+
+  sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+  if (binder == 0) {
+    ALOGW("Could not access permission service");
+    return false;
+  }
+
+  // Note: we ignore the pid because it's only used to automatically reply
+  // true if the caller is the Activity Manager Service.
+  bool trusted = interface_cast<IPermissionController>(binder)->checkPermission(
+      String16("android.permission.RESTRICTED_VR_ACCESS"), -1, uid);
+
+  // Cache the information for this uid to avoid future Java calls.
+  uid_cache[uid] = trusted;
+  return trusted;
+}
+
+}  // namespace dvr
+}  // namespace android
diff --git a/services/vr/vr_manager/vr_manager.cpp b/libs/vr/libvr_manager/vr_manager.cpp
similarity index 100%
rename from services/vr/vr_manager/vr_manager.cpp
rename to libs/vr/libvr_manager/vr_manager.cpp
diff --git a/libs/vr/libvrflinger/Android.mk b/libs/vr/libvrflinger/Android.mk
index 6b5e7cc..1706f30 100644
--- a/libs/vr/libvrflinger/Android.mk
+++ b/libs/vr/libvrflinger/Android.mk
@@ -45,6 +45,7 @@
 	libperformance \
 	libsensor \
 	libpdx_default_transport \
+	libvr_manager \
 
 sharedLibraries := \
 	android.dvr.composer@1.0 \
@@ -76,11 +77,6 @@
 LOCAL_CFLAGS += -DTRACE=0
 LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-ifeq ($(TARGET_USES_QCOM_BSP), true)
-    LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
-    LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils
-    LOCAL_SHARED_LIBRARIES += libqdutils
-endif
 LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
 LOCAL_WHOLE_STATIC_LIBRARIES := $(staticLibraries)
 LOCAL_MODULE := libvrflinger
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index c464c98..5309acf 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -318,6 +318,10 @@
   return hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
+void DisplayService::OnHardwareComposerRefresh() {
+  hardware_composer_.OnHardwareComposerRefresh();
+}
+
 void DisplayService::SetDisplayConfigurationUpdateNotifier(
     DisplayConfigurationUpdateNotifier update_notifier) {
   update_notifier_ = update_notifier;
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index ebd97de..5de4f1d 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -68,6 +68,8 @@
     }
   }
 
+  void OnHardwareComposerRefresh();
+
  private:
   friend BASE;
   friend DisplaySurface;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 5253b26..e6ed665 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1287,6 +1287,10 @@
   // TODO(eieio): implement display hotplug callbacks.
 }
 
+void HardwareComposer::OnHardwareComposerRefresh() {
+  // TODO(steventhomas): Handle refresh.
+}
+
 void HardwareComposer::SetBacklightBrightness(int brightness) {
   if (backlight_brightness_fd_) {
     std::array<char, 32> text;
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 33f090d..b6aa807 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -224,6 +224,8 @@
 
   Compositor* GetCompositor() { return &compositor_; }
 
+  void OnHardwareComposerRefresh();
+
  private:
   int32_t EnableVsync(bool enabled);
 
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index 04c8363..17dce96 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -21,6 +21,7 @@
 
   void EnterVrMode();
   void ExitVrMode();
+  void OnHardwareComposerRefresh();
 
  private:
   std::thread displayd_thread_;
diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp
index e174943..fd1c582 100644
--- a/libs/vr/libvrflinger/screenshot_service.cpp
+++ b/libs/vr/libvrflinger/screenshot_service.cpp
@@ -3,7 +3,9 @@
 #include <utils/Trace.h>
 
 #include <pdx/default_transport/service_endpoint.h>
+#include <private/android_filesystem_config.h>
 #include <private/dvr/display_types.h>
+#include <private/dvr/trusted_uids.h>
 
 using android::pdx::Message;
 using android::pdx::MessageInfo;
@@ -40,6 +42,12 @@
 
 ScreenshotData ScreenshotService::OnTakeScreenshot(pdx::Message& message,
                                                    int layer_index) {
+  // Also allow AID_SHELL to support vrscreencap commands.
+  if (message.GetEffectiveUserId() != AID_SHELL &&
+      !IsTrustedUid(message.GetEffectiveUserId())) {
+    REPLY_ERROR_RETURN(message, EACCES, {});
+  }
+
   AddWaiter(std::move(message), layer_index);
   return {};
 }
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 82ce067..9163e71 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -106,5 +106,13 @@
   }
 }
 
+void VrFlinger::OnHardwareComposerRefresh() {
+  if (display_service_) {
+    display_service_->OnHardwareComposerRefresh();
+  } else {
+    ALOGE("OnHardwareComposerRefresh failed : Display service is not started.");
+  }
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 027c18d..df84c93 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -619,6 +619,16 @@
 #endif
 #endif
 
+#ifndef EGL_ANDROID_get_native_client_buffer
+#define EGL_ANDROID_get_native_client_buffer 1
+struct AHardwareBuffer;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const AHardwareBuffer *buffer);
+#else
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const AHardwareBuffer *buffer);
+#endif
+#endif
+
 #ifndef EGL_ANDROID_front_buffer_auto_refresh
 #define EGL_ANDROID_front_buffer_auto_refresh 1
 #define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
@@ -632,22 +642,31 @@
 #ifndef EGL_ANDROID_get_frame_timestamps
 #define EGL_ANDROID_get_frame_timestamps 1
 #define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
-#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
-#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
-#define EGL_READS_DONE_TIME_ANDROID 0x3157
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+#define EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
+#define EGL_READS_DONE_TIME_ANDROID 0x315A
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
+EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
+EGLAPI EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint name);
+EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
+EGLAPI EGLBoolean eglGetFrameTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #else
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETNEXTFRAMEIDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #endif
 #endif
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 2782ed7..ef3d7a3 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -27,6 +27,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <android/hardware_buffer.h>
 #include <cutils/atomic.h>
 #include <cutils/compiler.h>
 #include <cutils/memory.h>
@@ -56,8 +57,6 @@
 
 using namespace android;
 
-#define ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS 0
-
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -87,10 +86,9 @@
         "EGL_ANDROID_presentation_time "
         "EGL_KHR_swap_buffers_with_damage "
         "EGL_ANDROID_create_native_client_buffer "
+        "EGL_ANDROID_get_native_client_buffer "
         "EGL_ANDROID_front_buffer_auto_refresh "
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
         "EGL_ANDROID_get_frame_timestamps "
-#endif
         ;
 extern char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
@@ -182,10 +180,14 @@
     { "eglSwapBuffersWithDamageKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
 
-    // EGL_ANDROID_native_client_buffer
+    // EGL_ANDROID_create_native_client_buffer
     { "eglCreateNativeClientBufferANDROID",
             (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
 
+    // EGL_ANDROID_get_native_client_buffer
+    { "eglGetNativeClientBufferANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
+
     // EGL_KHR_partial_update
     { "eglSetDamageRegionKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
@@ -216,10 +218,16 @@
             (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
 
     // EGL_ANDROID_get_frame_timestamps
+    { "eglGetNextFrameIdANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
+    { "eglGetCompositorTimingANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
+    { "eglGetCompositorTimingSupportedANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
     { "eglGetFrameTimestampsANDROID",
             (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
-    { "eglQueryTimestampSupportedANDROID",
-            (__eglMustCastToProperFunctionPointerType)&eglQueryTimestampSupportedANDROID },
+    { "eglGetFrameTimestampSupportedANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
 };
 
 /*
@@ -1240,7 +1248,6 @@
             setError(EGL_BAD_SURFACE, EGL_FALSE);
     }
 
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
     if (attribute == EGL_TIMESTAMPS_ANDROID) {
         if (!s->win.get()) {
             return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1250,7 +1257,6 @@
         return (err == NO_ERROR) ? EGL_TRUE :
             setError(EGL_BAD_SURFACE, EGL_FALSE);
     }
-#endif
 
     if (s->cnx->egl.eglSurfaceAttrib) {
         return s->cnx->egl.eglSurfaceAttrib(
@@ -1980,6 +1986,17 @@
     return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
 }
 
+EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
+    clearError();
+
+    if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+
+    // FIXME: remove this dangerous reinterpret_cast.
+    const GraphicBuffer* graphicBuffer =
+            reinterpret_cast<const GraphicBuffer*>(buffer);
+    return static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+}
+
 // ----------------------------------------------------------------------------
 // NVIDIA extensions
 // ----------------------------------------------------------------------------
@@ -2048,8 +2065,131 @@
     return EGL_FALSE;
 }
 
+EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId) {
+    clearError();
+
+    const egl_display_ptr dp = validate_display(dpy);
+    if (!dp) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    SurfaceRef _s(dp.get(), surface);
+    if (!_s.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (!s->win.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    uint64_t nextFrameId = 0;
+    status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
+
+    if (ret != NO_ERROR) {
+        // This should not happen. Return an error that is not in the spec
+        // so it's obvious something is very wrong.
+        ALOGE("eglGetNextFrameId: Unexpected error.");
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    *frameId = nextFrameId;
+    return EGL_TRUE;
+}
+
+EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
+        EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
+{
+    clearError();
+
+    const egl_display_ptr dp = validate_display(dpy);
+    if (!dp) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    SurfaceRef _s(dp.get(), surface);
+    if (!_s.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    egl_surface_t const * const s = get_surface(surface);
+
+    if (!s->win.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    nsecs_t* compositeDeadline = nullptr;
+    nsecs_t* compositeInterval = nullptr;
+    nsecs_t* compositeToPresentLatency = nullptr;
+
+    for (int i = 0; i < numTimestamps; i++) {
+        switch (names[i]) {
+            case EGL_COMPOSITE_DEADLINE_ANDROID:
+                compositeDeadline = &values[i];
+                break;
+            case EGL_COMPOSITE_INTERVAL_ANDROID:
+                compositeInterval = &values[i];
+                break;
+            case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
+                compositeToPresentLatency = &values[i];
+                break;
+            default:
+                return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+        }
+    }
+
+    status_t ret = native_window_get_compositor_timing(s->win.get(),
+            compositeDeadline, compositeInterval, compositeToPresentLatency);
+
+    switch (ret) {
+      case NO_ERROR:
+        return EGL_TRUE;
+      case INVALID_OPERATION:
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+      default:
+        // This should not happen. Return an error that is not in the spec
+        // so it's obvious something is very wrong.
+        ALOGE("eglGetCompositorTiming: Unexpected error.");
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+}
+
+EGLBoolean eglGetCompositorTimingSupportedANDROID(
+        EGLDisplay dpy, EGLSurface surface, EGLint name)
+{
+    clearError();
+
+    const egl_display_ptr dp = validate_display(dpy);
+    if (!dp) {
+        return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+    }
+
+    SurfaceRef _s(dp.get(), surface);
+    if (!_s.get()) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    egl_surface_t const * const s = get_surface(surface);
+
+    ANativeWindow* window = s->win.get();
+    if (!window) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    switch (name) {
+        case EGL_COMPOSITE_DEADLINE_ANDROID:
+        case EGL_COMPOSITE_INTERVAL_ANDROID:
+        case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
+            return EGL_TRUE;
+        default:
+            return EGL_FALSE;
+    }
+}
+
 EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
-        EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
+        EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
         EGLnsecsANDROID *values)
 {
     clearError();
@@ -2118,7 +2258,7 @@
         }
     }
 
-    status_t ret = native_window_get_frame_timestamps(s->win.get(), framesAgo,
+    status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
             requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
             lastRefreshStartTime, GLCompositionDoneTime, displayPresentTime,
             displayRetireTime, dequeueReadyTime, releaseTime);
@@ -2135,12 +2275,13 @@
       default:
         // This should not happen. Return an error that is not in the spec
         // so it's obvious something is very wrong.
+        ALOGE("eglGetFrameTimestamps: Unexpected error.");
         return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
     }
 }
 
-EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface,
-        EGLint timestamp)
+EGLBoolean eglGetFrameTimestampSupportedANDROID(
+        EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
 {
     clearError();
 
@@ -2162,7 +2303,9 @@
     }
 
     switch (timestamp) {
-#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
+        case EGL_COMPOSITE_DEADLINE_ANDROID:
+        case EGL_COMPOSITE_INTERVAL_ANDROID:
+        case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
         case EGL_REQUESTED_PRESENT_TIME_ANDROID:
         case EGL_RENDERING_COMPLETE_TIME_ANDROID:
         case EGL_COMPOSITION_LATCH_TIME_ANDROID:
@@ -2184,7 +2327,6 @@
                     NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &value);
             return value == 0 ? EGL_FALSE : EGL_TRUE;
         }
-#endif
         default:
             return EGL_FALSE;
     }
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 2b56718..b587a16 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -81,6 +81,7 @@
 EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
 EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
 EGL_ENTRY(EGLClientBuffer, eglCreateNativeClientBufferANDROID, const EGLint *)
+EGL_ENTRY(EGLClientBuffer, eglGetNativeClientBufferANDROID, const AHardwareBuffer *)
 
 /* NVIDIA extensions */
 
diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt
index c8b83f5..89269a0 100644
--- a/opengl/libs/libEGL.map.txt
+++ b/opengl/libs/libEGL.map.txt
@@ -28,6 +28,7 @@
     eglGetCurrentSurface;
     eglGetDisplay;
     eglGetError;
+    eglGetNativeClientBufferANDROID; # introduced=26
     eglGetProcAddress;
     eglGetStreamFileDescriptorKHR; # introduced=23
     eglGetSyncAttribKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 7aa0d30..d0ed8e1 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -8,11 +8,19 @@
 
 Contributors
 
+    Brian Anderson
+    Dan Stoza
     Pablo Ceballos
+    Jesse Hall
+    Fabien Sanglard
 
 Contact
 
+    Brian Anderson, Google Inc. (brianderson 'at' google.com)
+    Dan Stoza, Google Inc. (stoza 'at' google.com)
     Pablo Ceballos, Google Inc. (pceballos 'at' google.com)
+    Jesse Hall, Google Inc. (jessehall 'at' google.com)
+    Fabien Sanglard, Google Inc. (sanglardf 'at' google.com)
 
 Status
 
@@ -20,7 +28,7 @@
 
 Version
 
-    Version 1, May 31, 2016
+    Version 1, January 13, 2017
 
 Number
 
@@ -57,26 +65,36 @@
 
 New Procedures and Functions
 
-    EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
-            EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps,
-            EGLnsecsANDROID *values);
+    EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId);
 
-    EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface
-            surface, EGLint timestamp);
+    EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLint numTimestamps,
+            const EGLint *names, EGLnsecsANDROID *values);
+
+    EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR frameId, EGLint numTimestamps,
+            const EGLint *timestamps, EGLnsecsANDROID *values);
+
+    EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLint timestamp);
 
 New Tokens
 
     EGL_TIMESTAMPS_ANDROID 0x314D
-    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x314E
-    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x314F
-    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3150
-    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3151
-    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3152
-    EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3153
-    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3154
-    EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3155
-    EGL_DEQUEUE_READY_TIME_ANDROID 0x3156
-    EGL_READS_DONE_TIME_ANDROID 0x3157
+    EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+    EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+    EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+    EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+    EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+    EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+    EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+    EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+    EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID 0x3156
+    EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+    EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
+    EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
+    EGL_READS_DONE_TIME_ANDROID 0x315A
 
 Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
 "Surface Attributes", page 43:
@@ -86,7 +104,6 @@
     enables timestamp collection, while a value of EGL_FALSE disables it. The
     initial value is false. If surface is not a window surface this has no
     effect.
-
 Changes to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
 
     Add a new subsection under Section 3,
@@ -95,23 +112,60 @@
 
     The function
 
-        EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface
-            surface, EGLint framesAgo, EGLint numTimestamps,
+        EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
+            EGLuint64KHR *frameId);
+
+    Returns an identifier for the next frame to be swapped. The identifier can
+    be used to correlate a particular eglSwapBuffers with its timestamps in
+    eglGetFrameTimestampsANDROID. If any error is generated, the function will
+    return EGL_FALSE.
+
+    The function
+
+        EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy,
+                EGLSurface surface, EGLint numTimestamps,
+                const EGLint *names, EGLnsecsANDROID *values);
+
+    allows querying anticipated timestamps and durations related to the
+    composition and display of a window surface. The values are not associated
+    with a particular frame and can be retrieved before the first swap.
+
+    The eglGetCompositorTimingANDROID function takes an array of names to
+    query and returns their values in the corresponding indices of the values
+    array. The possible names that can be queried are:
+        - EGL_COMPOSITE_DEADLINE_ANDROID - The timestamp of the next time the
+          compositor will begin composition. This is effectively the deadline
+          for when the compositor must receive a newly queued frame.
+        - EGL_COMPOSITE_INTERVAL_ANDROID - The time delta between subsequent
+          composition events.
+        - EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID - The time delta between
+          the start of composition and the expected present time of that
+          composition. This can be used to estimate the latency of the
+          actual present time.
+
+    The function
+
+        EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLuint64KHR frameId, EGLint numTimestamps,
             const EGLint *timestamps, EGLnsecsANDROID *values);
 
-    allows querying various timestamps related to the composition and display of
-    a window surface.
+    allows querying various timestamps related to the composition and display
+    of specific frames of a window surface.
 
-    The framesAgo parameter indicates how many frames before the last queued
-    frame to query. So a value of zero would indicate that the query is for the
-    last queued frame. Note that the implementation maintains a limited history
-    of timestamp data. If a query is made for a frame whose timestamp history
-    no longer exists then EGL_BAD_ACCESS is generated. If timestamp collection
-    has not been enabled for the surface then EGL_BAD_SURFACE is generated.
-    Timestamps for events that will not occur or have not yet occurred will be
-    zero. Timestamp queries that are not supported will generate an
-    EGL_BAD_PARAMETER error. If any error is generated the function will return
-    EGL_FALSE.
+    The frameId indicates which frame to query. The implementation maintains a
+    limited history of timestamp data. If a query is made for a frame whose
+    timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
+    timestamp collection has not been enabled for the surface then
+    EGL_BAD_SURFACE is generated.  Timestamps for events that will not occur or
+    have not yet occurred will be zero. Timestamp queries that are not
+    supported will generate an EGL_BAD_PARAMETER error. If any error is
+    generated the function will return EGL_FALSE.
+
+    The application can poll for the timestamp of particular events by calling
+    eglGetFrameTimestamps over and over without needing to call any other EGL
+    function between calls. This is true even for the most recently swapped
+    frame. eglGetFrameTimestamps is thread safe and can be called from a
+    different thread than the swapping thread.
 
     The eglGetFrameTimestampsANDROID function takes an array of timestamps to
     query and returns timestamps in the corresponding indices of the values
@@ -151,12 +205,19 @@
           purpose of display/composition were completed for this frame.
 
     Not all implementations may support all of the above timestamp queries. The
-    function
+    functions
 
-        EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface
-            surface, EGLint timestamp);
+        EGLBoolean eglGetCompositorTimingSupportedANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLint name);
 
-    allows querying which timestamps are supported on the implementation."
+    and
+
+        EGLBoolean eglGetFrameTimestampsSupportedANDROID(EGLDisplay dpy,
+            EGLSurface surface, EGLint timestamp);
+
+    allows querying which values are supported by the implementations of
+    eglGetCompositoTimingANDROID and eglGetFrameTimestampsSupportedANDROID
+    respectively."
 
 Issues
 
@@ -164,14 +225,21 @@
 
 Revision History
 
-#1 (Pablo Ceballos, May 31, 2016)
-    - Initial draft.
+#5 (Brian Anderson, January 13, 2017)
+    - Add eglGetCompositorTimingANDROID.
 
-#2 (Brian Anderson, July 22, 2016)
-    - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
-    - Add DISPLAY_PRESENT_TIME_ANDROID.
+#4 (Brian Anderson, January 10, 2017)
+    - Use an absolute frameId rather than a relative framesAgo.
 
 #3 (Brian Anderson, November 30, 2016)
     - Add EGL_COMPOSITION_LATCH_TIME_ANDROID,
       EGL_LAST_COMPOSITION_START_TIME_ANDROID, and
       EGL_DEQUEUE_READY_TIME_ANDROID.
+
+#2 (Brian Anderson, July 22, 2016)
+    - Replace EGL_QUEUE_TIME_ANDROID with EGL_REQUESTED_PRESENT_TIME_ANDROID.
+    - Add DISPLAY_PRESENT_TIME_ANDROID.
+
+#1 (Pablo Ceballos, May 31, 2016)
+    - Initial draft.
+
diff --git a/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt
new file mode 100644
index 0000000..de012a0
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_get_native_client_buffer.txt
@@ -0,0 +1,96 @@
+Name
+
+    ANDROID_get_native_client_buffer
+
+Name Strings
+
+    EGL_ANDROID_get_native_client_buffer
+
+Contributors
+
+    Craig Donner
+
+Contact
+
+    Craig Donner, Google Inc. (cdonner 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1.0, January 27, 2017
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.2.
+
+    EGL_ANDROID_image_native_buffer and EGL_KHR_image_base are required.
+
+    This extension is written against the wording of the EGL 1.2
+    Specification as modified by EGL_KHR_image_base and
+    EGL_ANDROID_image_native_buffer.
+
+Overview
+
+    This extension allows creating an EGLClientBuffer from an Android
+    AHardwareBuffer object which can be later used to create an EGLImage.
+
+New Types
+
+struct AHardwareBuffer
+
+New Procedures and Functions
+
+EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer)
+
+New Tokens
+
+    None
+
+Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
+
+    Add the following to section 2.5.1 "EGLImage Specification" (as modified by
+    the EGL_KHR_image_base and EGL_ANDROID_image_native_buffer specifications),
+    below the description of eglCreateImageKHR:
+
+   "The command
+
+        EGLClientBuffer eglGeteNativeClientBufferANDROID(
+                                AHardwareBuffer *buffer)
+
+    may be used to create an EGLClientBuffer from an AHardwareBuffer object.
+    EGL implementations must guarantee that the lifetime of the returned
+    EGLClientBuffer is at least as long as the EGLImage(s) it is bound to,
+    following the lifetime semantics described below in section 2.5.2; the
+    EGLClientBuffer must be destroyed no earlier than when all of its associated
+    EGLImages are destroyed by eglDestroyImageKHR.
+
+    Errors
+
+        If eglGeteNativeClientBufferANDROID fails, NULL will be returned, no
+        memory will be allocated, and the following error will be generated:
+
+       * If the value of buffer is NULL, the error EGL_BAD_PARAMETER is
+         generated.
+
+Issues
+
+    1. Should this extension define what particular AHardwareBuffer formats EGL
+    implementations are required to support?
+
+    RESOLVED: No.
+
+    The set of valid formats is implementation-specific and may depend on
+    additional EGL extensions. The particular valid combinations for a given
+    Android version and implementation should be documented by that version.
+
+Revision History
+
+#1 (Craig Donner, January 27, 2017)
+    - Initial draft.
diff --git a/opengl/specs/README b/opengl/specs/README
index 8a3a7aa..0c49023 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -1,5 +1,5 @@
 This directory contains OpenGL ES and EGL extension specifications that have
-been or are being defined for Android.  
+been or are being defined for Android.
 
 The table below tracks usage of EGL enumerant values that have been reserved
 for use by Android extensions.
@@ -20,14 +20,17 @@
 0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
 0x314C               EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
 0x314D               EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153               EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155               EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158 - 0x315F      (unused)
+0x314E               EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x314F               EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3150               EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3151               EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3152               EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3153               EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3154               EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3155               EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3156               EGL_FIRST_COMPOSITION_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3157               EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3158               EGL_DISPLAY_RETIRE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3159               EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x315A               EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x315B - 0x315F      (unused)
diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp
index 47edc4b..e8a9c34 100644
--- a/services/audiomanager/IPlayer.cpp
+++ b/services/audiomanager/IPlayer.cpp
@@ -35,6 +35,7 @@
     SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3,
     SET_PAN    = IBinder::FIRST_CALL_TRANSACTION + 4,
     SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5,
+    APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6,
 };
 
 class BpPlayer : public BpInterface<IPlayer>
@@ -88,6 +89,36 @@
         data.writeInt32(delayMs);
         remote()->transact(SET_START_DELAY_MS, data, &reply);
     }
+
+    virtual void applyVolumeShaper(
+            const sp<VolumeShaper::Configuration>& configuration,
+            const sp<VolumeShaper::Operation>& operation) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
+
+        status_t status = configuration.get() == nullptr
+                ? data.writeInt32(0)
+                :  data.writeInt32(1)
+                    ?: configuration->writeToParcel(&data);
+        if (status != NO_ERROR) {
+            ALOGW("applyVolumeShaper failed configuration parceling: %d", status);
+            return; // ignore error
+        }
+
+        status = operation.get() == nullptr
+                ? status = data.writeInt32(0)
+                : data.writeInt32(1)
+                    ?: operation->writeToParcel(&data);
+        if (status != NO_ERROR) {
+            ALOGW("applyVolumeShaper failed operation parceling: %d", status);
+            return; // ignore error
+        }
+
+        status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply);
+
+        ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status);
+        return; // one way transaction, ignore error
+    }
 };
 
 IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer");
@@ -128,6 +159,28 @@
             setStartDelayMs(data.readInt32());
             return NO_ERROR;
         } break;
+        case APPLY_VOLUME_SHAPER: {
+            CHECK_INTERFACE(IPlayer, data, reply);
+            sp<VolumeShaper::Configuration> configuration;
+            sp<VolumeShaper::Operation> operation;
+
+            int32_t present;
+            status_t status = data.readInt32(&present);
+            if (status == NO_ERROR && present != 0) {
+                configuration = new VolumeShaper::Configuration();
+                status = configuration->readFromParcel(data);
+            }
+            status = status ?: data.readInt32(&present);
+            if (status == NO_ERROR && present != 0) {
+                operation = new VolumeShaper::Operation();
+                status = operation->readFromParcel(data);
+            }
+            if (status == NO_ERROR) {
+                // one way transaction, no error returned
+                applyVolumeShaper(configuration, operation);
+            }
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index c41630a..d61f26f 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -10,6 +10,7 @@
     OrientationSensor.cpp \
     RecentEventLogger.cpp \
     RotationVectorSensor.cpp \
+    SensorDevice.cpp \
     SensorDirectConnection.cpp \
     SensorEventConnection.cpp \
     SensorFusion.cpp \
@@ -25,13 +26,6 @@
 
 LOCAL_CFLAGS += -fvisibility=hidden
 
-ifeq ($(ENABLE_TREBLE), true)
-LOCAL_SRC_FILES += SensorDeviceTreble.cpp
-LOCAL_CFLAGS += -DENABLE_TREBLE=1
-else
-LOCAL_SRC_FILES += SensorDevice.cpp
-endif
-
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libhardware \
@@ -42,10 +36,6 @@
     libui \
     libgui \
     libcrypto \
-
-ifeq ($(ENABLE_TREBLE), true)
-
-LOCAL_SHARED_LIBRARIES += \
     libbase \
     libhidlbase \
     libhidltransport \
@@ -55,8 +45,6 @@
 LOCAL_STATIC_LIBRARIES := \
     android.hardware.sensors@1.0-convert
 
-endif  # ENABLE_TREBLE
-
 LOCAL_MODULE:= libsensorservice
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index de0321d..3edd50b 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -14,138 +14,167 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
 
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-
-#include <binder/BinderService.h>
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-#include <cutils/ashmem.h>
-#include <hardware/sensors.h>
+#include <android-base/logging.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
 #include <utils/Singleton.h>
 
-#include <inttypes.h>
-#include <math.h>
-#include <sys/mman.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sstream>
-#include <unistd.h>
+#include "SensorDevice.h"
+#include "SensorService.h"
+
+#include <sensors/convert.h>
+
+using android::hardware::hidl_vec;
+
+using namespace android::hardware::sensors::V1_0;
+using namespace android::hardware::sensors::V1_0::implementation;
 
 namespace android {
 // ---------------------------------------------------------------------------
 
 ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
 
-SensorDevice::SensorDevice()
-    :  mSensorDevice(0),
-       mSensorModule(0) {
-    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
-            (hw_module_t const**)&mSensorModule);
-
-    ALOGE_IF(err, "couldn't load %s module (%s)",
-            SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-    if (mSensorModule) {
-        err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
-
-        ALOGE_IF(err, "couldn't open device for module %s (%s)",
-                SENSORS_HARDWARE_MODULE_ID, strerror(-err));
-
-        if (mSensorDevice) {
-
-            sensor_t const* list;
-            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
-
-            if (mSensorDevice->common.version < SENSORS_DEVICE_API_VERSION_1_3) {
-                ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3, ignoring sensors reported by this device");
-                count = 0;
-            }
-
-            mActivationCount.setCapacity(count);
-            Info model;
-            for (size_t i=0 ; i<size_t(count) ; i++) {
-                mActivationCount.add(list[i].handle, model);
-                mSensorDevice->activate(
-                        reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
-                        list[i].handle, 0);
-            }
-        }
+static status_t StatusFromResult(Result result) {
+    switch (result) {
+        case Result::OK:
+            return OK;
+        case Result::BAD_VALUE:
+            return BAD_VALUE;
+        case Result::PERMISSION_DENIED:
+            return PERMISSION_DENIED;
+        case Result::INVALID_OPERATION:
+            return INVALID_OPERATION;
+        case Result::NO_MEMORY:
+            return NO_MEMORY;
     }
 }
 
+SensorDevice::SensorDevice() {
+    mSensors = ISensors::getService();
+
+    if (mSensors == NULL) {
+        return;
+    }
+
+    mSensors->getSensorsList(
+            [&](const auto &list) {
+                const size_t count = list.size();
+
+                mActivationCount.setCapacity(count);
+                Info model;
+                for (size_t i=0 ; i < count; i++) {
+                    sensor_t sensor;
+                    convertToSensor(list[i], &sensor);
+                    mSensorList.push_back(sensor);
+
+                    mActivationCount.add(list[i].sensorHandle, model);
+
+                    mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
+                }
+            });
+
+    mIsDirectReportSupported =
+           (mSensors->unregisterDirectChannel(-1) != Result::INVALID_OPERATION);
+}
+
 void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
     if (connected) {
         Info model;
         mActivationCount.add(handle, model);
-        mSensorDevice->activate(
-                reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), handle, 0);
+        mSensors->activate(handle, 0 /* enabled */);
     } else {
         mActivationCount.removeItem(handle);
     }
 }
 
 std::string SensorDevice::dump() const {
-    if (!mSensorModule) return "HAL not initialized\n";
+    if (mSensors == NULL) return "HAL not initialized\n";
 
     String8 result;
-    sensor_t const* list;
-    int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+    mSensors->getSensorsList([&](const auto &list) {
+            const size_t count = list.size();
 
-    result.appendFormat("HAL: %s (%s), version %#010x\n",
-                        mSensorModule->common.name,
-                        mSensorModule->common.author,
-                        getHalDeviceVersion());
-    result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size());
+            result.appendFormat(
+                "Total %zu h/w sensors, %zu running:\n",
+                count,
+                mActivationCount.size());
 
-    Mutex::Autolock _l(mLock);
-    for (int i = 0 ; i < count ; i++) {
-        const Info& info = mActivationCount.valueFor(list[i].handle);
-        if (info.batchParams.isEmpty()) continue;
-        result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle,
-                            info.batchParams.size());
+            Mutex::Autolock _l(mLock);
+            for (size_t i = 0 ; i < count ; i++) {
+                const Info& info = mActivationCount.valueFor(
+                    list[i].sensorHandle);
 
-        result.append("sampling_period(ms) = {");
-        for (size_t j = 0; j < info.batchParams.size(); j++) {
-            const BatchParams& params = info.batchParams.valueAt(j);
-            result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
-                                j < info.batchParams.size() - 1 ? ", " : "");
-        }
-        result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
+                if (info.batchParams.isEmpty()) continue;
+                result.appendFormat(
+                    "0x%08x) active-count = %zu; ",
+                    list[i].sensorHandle,
+                    info.batchParams.size());
 
-        result.append("batching_period(ms) = {");
-        for (size_t j = 0; j < info.batchParams.size(); j++) {
-            BatchParams params = info.batchParams.valueAt(j);
-            result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
-                                j < info.batchParams.size() - 1 ? ", " : "");
-        }
-        result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
-    }
+                result.append("sampling_period(ms) = {");
+                for (size_t j = 0; j < info.batchParams.size(); j++) {
+                    const BatchParams& params = info.batchParams.valueAt(j);
+                    result.appendFormat(
+                        "%.1f%s",
+                        params.batchDelay / 1e6f,
+                        j < info.batchParams.size() - 1 ? ", " : "");
+                }
+                result.appendFormat(
+                        "}, selected = %.1f ms; ",
+                        info.bestBatchParams.batchDelay / 1e6f);
+
+                result.append("batching_period(ms) = {");
+                for (size_t j = 0; j < info.batchParams.size(); j++) {
+                    BatchParams params = info.batchParams.valueAt(j);
+
+                    result.appendFormat(
+                            "%.1f%s",
+                            params.batchTimeout / 1e6f,
+                            j < info.batchParams.size() - 1 ? ", " : "");
+                }
+
+                result.appendFormat(
+                        "}, selected = %.1f ms\n",
+                        info.bestBatchParams.batchTimeout / 1e6f);
+            }
+        });
+
     return result.string();
 }
 
 ssize_t SensorDevice::getSensorList(sensor_t const** list) {
-    if (!mSensorModule) return NO_INIT;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list);
-    return count;
+    *list = &mSensorList[0];
+
+    return mSensorList.size();
 }
 
 status_t SensorDevice::initCheck() const {
-    return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
+    return mSensors != NULL ? NO_ERROR : NO_INIT;
 }
 
 ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
-    if (!mSensorDevice) return NO_INIT;
-    ssize_t c;
-    do {
-        c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
-                                buffer, count);
-    } while (c == -EINTR);
-    return c;
+    if (mSensors == NULL) return NO_INIT;
+
+    ssize_t err;
+
+    mSensors->poll(
+            count,
+            [&](auto result,
+                const auto &events,
+                const auto &dynamicSensorsAdded) {
+                if (result == Result::OK) {
+                    convertToSensorEvents(events, dynamicSensorsAdded, buffer);
+                    err = (ssize_t)events.size();
+                } else {
+                    err = StatusFromResult(result);
+                }
+            });
+
+    return err;
 }
 
 void SensorDevice::autoDisable(void *ident, int handle) {
@@ -155,7 +184,8 @@
 }
 
 status_t SensorDevice::activate(void* ident, int handle, int enabled) {
-    if (!mSensorDevice) return NO_INIT;
+    if (mSensors == NULL) return NO_INIT;
+
     status_t err(NO_ERROR);
     bool actuateHardware = false;
 
@@ -187,24 +217,30 @@
     } else {
         ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
 
+        // If a connected dynamic sensor is deactivated, remove it from the
+        // dictionary.
+        auto it = mConnectedDynamicSensors.find(handle);
+        if (it != mConnectedDynamicSensors.end()) {
+            delete it->second;
+            mConnectedDynamicSensors.erase(it);
+        }
+
         if (info.removeBatchParamsForIdent(ident) >= 0) {
             if (info.numActiveClients() == 0) {
                 // This is the last connection, we need to de-activate the underlying h/w sensor.
                 actuateHardware = true;
             } else {
-                const int halVersion = getHalDeviceVersion();
-                if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
-                    // Call batch for this sensor with the previously calculated best effort
-                    // batch_rate and timeout. One of the apps has unregistered for sensor
-                    // events, and the best effort batch parameters might have changed.
-                    ALOGD_IF(DEBUG_CONNECTIONS,
-                             "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
-                             info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                             info.bestBatchParams.batchTimeout);
-                    mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags,
-                                         info.bestBatchParams.batchDelay,
-                                         info.bestBatchParams.batchTimeout);
-                }
+                // Call batch for this sensor with the previously calculated best effort
+                // batch_rate and timeout. One of the apps has unregistered for sensor
+                // events, and the best effort batch parameters might have changed.
+                ALOGD_IF(DEBUG_CONNECTIONS,
+                         "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
+                         info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+                         info.bestBatchParams.batchTimeout);
+                mSensors->batch(
+                        handle,
+                        info.bestBatchParams.batchDelay,
+                        info.bestBatchParams.batchTimeout);
             }
         } else {
             // sensor wasn't enabled for this ident
@@ -218,8 +254,7 @@
     if (actuateHardware) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                  enabled);
-        err = mSensorDevice->activate(
-                reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
+        err = StatusFromResult(mSensors->activate(handle, enabled));
         ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                  strerror(-err));
 
@@ -229,31 +264,21 @@
         }
     }
 
-    // On older devices which do not support batch, call setDelay().
-    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
-                 info.bestBatchParams.batchDelay);
-        mSensorDevice->setDelay(
-                reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
-                handle, info.bestBatchParams.batchDelay);
-    }
     return err;
 }
 
-status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
-                             int64_t maxBatchReportLatencyNs) {
-    if (!mSensorDevice) return NO_INIT;
+status_t SensorDevice::batch(
+        void* ident,
+        int handle,
+        int flags,
+        int64_t samplingPeriodNs,
+        int64_t maxBatchReportLatencyNs) {
+    if (mSensors == NULL) return NO_INIT;
 
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
     }
 
-    const int halVersion = getHalDeviceVersion();
-    if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
-        // Batch is not supported on older devices return invalid operation.
-        return INVALID_OPERATION;
-    }
-
     ALOGD_IF(DEBUG_CONNECTIONS,
              "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
              ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
@@ -282,21 +307,17 @@
     status_t err(NO_ERROR);
     // If the min period or min timeout has changed since the last batch call, call batch.
     if (prevBestBatchParams != info.bestBatchParams) {
-        if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
-                     info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                     info.bestBatchParams.batchTimeout);
-            err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
-                                       info.bestBatchParams.batchDelay,
-                                       info.bestBatchParams.batchTimeout);
-        } else {
-            // For older devices which do not support batch, call setDelay() after activate() is
-            // called. Some older devices may not support calling setDelay before activate(), so
-            // call setDelay in SensorDevice::activate() method.
-        }
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
+                 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+                 info.bestBatchParams.batchTimeout);
+        err = StatusFromResult(
+                mSensors->batch(
+                    handle,
+                    info.bestBatchParams.batchDelay,
+                    info.bestBatchParams.batchTimeout));
         if (err != NO_ERROR) {
             ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
-                  mSensorDevice, handle,
+                  mSensors.get(), handle,
                   info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
                   info.bestBatchParams.batchTimeout, strerror(-err));
             info.removeBatchParamsForIdent(ident);
@@ -306,7 +327,7 @@
 }
 
 status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
-    if (!mSensorDevice) return NO_INIT;
+    if (mSensors == NULL) return NO_INIT;
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
     }
@@ -325,22 +346,20 @@
     BatchParams& params = info.batchParams.editValueAt(index);
     params.batchDelay = samplingPeriodNs;
     info.selectBatchParams();
-    return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
-                                   handle, info.bestBatchParams.batchDelay);
+
+    return StatusFromResult(
+            mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
 }
 
 int SensorDevice::getHalDeviceVersion() const {
-    if (!mSensorDevice) return -1;
-    return mSensorDevice->common.version;
+    if (mSensors == NULL) return -1;
+    return SENSORS_DEVICE_API_VERSION_1_4;
 }
 
 status_t SensorDevice::flush(void* ident, int handle) {
-    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
-        return INVALID_OPERATION;
-    }
     if (isClientDisabled(ident)) return INVALID_OPERATION;
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return mSensorDevice->flush(mSensorDevice, handle);
+    return StatusFromResult(mSensors->flush(handle));
 }
 
 bool SensorDevice::isClientDisabled(void* ident) {
@@ -356,7 +375,6 @@
     Mutex::Autolock _l(mLock);
     mDisabledClients.clear();
     ALOGI("cleared mDisabledClients");
-    const int halVersion = getHalDeviceVersion();
     for (size_t i = 0; i< mActivationCount.size(); ++i) {
         Info& info = mActivationCount.editValueAt(i);
         if (info.batchParams.isEmpty()) continue;
@@ -364,42 +382,32 @@
         const int sensor_handle = mActivationCount.keyAt(i);
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                    sensor_handle);
-        status_t err(NO_ERROR);
-        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
-            err = mSensorDevice->batch(mSensorDevice, sensor_handle,
-                 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                 info.bestBatchParams.batchTimeout);
-            ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
-        }
+        status_t err = StatusFromResult(
+                mSensors->batch(
+                    sensor_handle,
+                    info.bestBatchParams.batchDelay,
+                    info.bestBatchParams.batchTimeout));
+        ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
-            err = mSensorDevice->activate(
-                    reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
-                    sensor_handle, 1);
+            err = StatusFromResult(
+                    mSensors->activate(sensor_handle, 1 /* enabled */));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
-
-        if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
-             err = mSensorDevice->setDelay(
-                    reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
-                    sensor_handle, info.bestBatchParams.batchDelay);
-             ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
-        }
     }
 }
 
 void SensorDevice::disableAllSensors() {
     Mutex::Autolock _l(mLock);
-    for (size_t i = 0; i< mActivationCount.size(); ++i) {
+   for (size_t i = 0; i< mActivationCount.size(); ++i) {
         const Info& info = mActivationCount.valueAt(i);
         // Check if this sensor has been activated previously and disable it.
         if (info.batchParams.size() > 0) {
            const int sensor_handle = mActivationCount.keyAt(i);
            ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
                    sensor_handle);
-           mSensorDevice->activate(
-                   reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
-                   sensor_handle, 0);
+           mSensors->activate(sensor_handle, 0 /* enabled */);
+
            // Add all the connections that were registered for this sensor to the disabled
            // clients list.
            for (size_t j = 0; j < info.batchParams.size(); ++j) {
@@ -410,25 +418,27 @@
     }
 }
 
-status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
-      ALOGD_IF(DEBUG_CONNECTIONS,
-              "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
-               injected_sensor_event->sensor,
-               injected_sensor_event->timestamp, injected_sensor_event->data[0],
-               injected_sensor_event->data[1], injected_sensor_event->data[2],
-               injected_sensor_event->data[3], injected_sensor_event->data[4],
-               injected_sensor_event->data[5]);
-      if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
-          return INVALID_OPERATION;
-      }
-      return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
+status_t SensorDevice::injectSensorData(
+        const sensors_event_t *injected_sensor_event) {
+    ALOGD_IF(DEBUG_CONNECTIONS,
+            "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+            injected_sensor_event->sensor,
+            injected_sensor_event->timestamp, injected_sensor_event->data[0],
+            injected_sensor_event->data[1], injected_sensor_event->data[2],
+            injected_sensor_event->data[3], injected_sensor_event->data[4],
+            injected_sensor_event->data[5]);
+
+    Event ev;
+    convertFromSensorEvent(*injected_sensor_event, &ev);
+
+    return StatusFromResult(mSensors->injectSensorData(ev));
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
-     if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
-          return INVALID_OPERATION;
-     }
-     return mSensorModule->set_operation_mode(mode);
+
+     return StatusFromResult(
+             mSensors->setOperationMode(
+                 static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
 }
 
 // ---------------------------------------------------------------------------
@@ -491,44 +501,139 @@
 }
 
 int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
-
-    if (!isDirectReportSupported()) {
-        return INVALID_OPERATION;
-    }
-
     Mutex::Autolock _l(mLock);
 
-    int32_t channelHandle = mSensorDevice->register_direct_channel(
-            mSensorDevice, memory, -1 /*channel_handle*/);
-    return channelHandle;
+    SharedMemType type;
+    switch (memory->type) {
+        case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+            type = SharedMemType::ASHMEM;
+            break;
+        case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+            type = SharedMemType::GRALLOC;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    SharedMemFormat format;
+    if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+        return BAD_VALUE;
+    }
+    format = SharedMemFormat::SENSORS_EVENT;
+
+    SharedMemInfo mem = {
+        .type = type,
+        .format = format,
+        .size = static_cast<uint32_t>(memory->size),
+        .memoryHandle = memory->handle,
+    };
+
+    int32_t ret;
+    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);
-
-    mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle);
+    mSensors->unregisterDirectChannel(channelHandle);
 }
 
-int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
-        const struct sensors_direct_cfg_t *config) {
-
-    if (!isDirectReportSupported()) {
-        return INVALID_OPERATION;
-    }
-
+int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
+        int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
     Mutex::Autolock _l(mLock);
 
-    int32_t ret = mSensorDevice->config_direct_report(
-            mSensorDevice, sensorHandle, channelHandle, config);
-    ALOGE_IF(ret < 0, "SensorDevice::configureDirectChannel ret %d", ret);
+    RateLevel rate;
+    switch(config->rate_level) {
+        case SENSOR_DIRECT_RATE_STOP:
+            rate = RateLevel::STOP;
+            break;
+        case SENSOR_DIRECT_RATE_NORMAL:
+            rate = RateLevel::NORMAL;
+            break;
+        case SENSOR_DIRECT_RATE_FAST:
+            rate = RateLevel::FAST;
+            break;
+        case SENSOR_DIRECT_RATE_VERY_FAST:
+            rate = RateLevel::VERY_FAST;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    int32_t ret;
+    mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+            [&ret, rate] (auto result, auto token) {
+                if (rate == RateLevel::STOP) {
+                    ret = StatusFromResult(result);
+                } else {
+                    if (result == Result::OK) {
+                        ret = token;
+                    } else {
+                        ret = StatusFromResult(result);
+                    }
+                }
+            });
+
     return ret;
 }
 
 bool SensorDevice::isDirectReportSupported() const {
-    bool ret = mSensorDevice->register_direct_channel != nullptr
-            && mSensorDevice->config_direct_report != nullptr;
-    return ret;
+    return mIsDirectReportSupported;
 }
+
+void SensorDevice::convertToSensorEvent(
+        const Event &src, sensors_event_t *dst) {
+    ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
+            src, dst);
+
+    if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
+        const DynamicSensorInfo &dyn = src.u.dynamic;
+
+        dst->dynamic_sensor_meta.connected = dyn.connected;
+        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
+        if (dyn.connected) {
+            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+            CHECK(it != mConnectedDynamicSensors.end());
+
+            dst->dynamic_sensor_meta.sensor = it->second;
+
+            memcpy(dst->dynamic_sensor_meta.uuid,
+                   dyn.uuid.data(),
+                   sizeof(dst->dynamic_sensor_meta.uuid));
+        }
+    }
+}
+
+void SensorDevice::convertToSensorEvents(
+        const hidl_vec<Event> &src,
+        const hidl_vec<SensorInfo> &dynamicSensorsAdded,
+        sensors_event_t *dst) {
+    // Allocate a sensor_t structure for each dynamic sensor added and insert
+    // it into the dictionary of connected dynamic sensors keyed by handle.
+    for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
+        const SensorInfo &info = dynamicSensorsAdded[i];
+
+        auto it = mConnectedDynamicSensors.find(info.sensorHandle);
+        CHECK(it == mConnectedDynamicSensors.end());
+
+        sensor_t *sensor = new sensor_t;
+        convertToSensor(info, sensor);
+
+        mConnectedDynamicSensors.insert(
+                std::make_pair(sensor->handle, sensor));
+    }
+
+    for (size_t i = 0; i < src.size(); ++i) {
+        convertToSensorEvent(src[i], &dst[i]);
+    }
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
-
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 7dd256a..7f95429 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -20,19 +20,16 @@
 #include "SensorServiceUtils.h"
 
 #include <gui/Sensor.h>
+#include <stdint.h>
+#include <sys/types.h>
 #include <utils/KeyedVector.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 
-#include <stdint.h>
-#include <sys/types.h>
 #include <string>
-
-#ifdef ENABLE_TREBLE
 #include <map>
 
 #include "android/hardware/sensors/1.0/ISensors.h"
-#endif
 
 // ---------------------------------------------------------------------------
 
@@ -76,14 +73,10 @@
     virtual std::string dump() const;
 private:
     friend class Singleton<SensorDevice>;
-#ifdef ENABLE_TREBLE
+
     sp<android::hardware::sensors::V1_0::ISensors> mSensors;
     Vector<sensor_t> mSensorList;
     std::map<int32_t, sensor_t*> mConnectedDynamicSensors;
-#else
-    sensors_poll_device_1_t* mSensorDevice;
-    struct sensors_module_t* mSensorModule;
-#endif
 
     static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
     mutable Mutex mLock; // protect mActivationCount[].batchParams
@@ -138,7 +131,6 @@
     bool isClientDisabled(void* ident);
     bool isClientDisabledLocked(void* ident);
 
-#ifdef ENABLE_TREBLE
     using Event = hardware::sensors::V1_0::Event;
     using SensorInfo = hardware::sensors::V1_0::SensorInfo;
 
@@ -150,7 +142,6 @@
             sensors_event_t *dst);
 
     bool mIsDirectReportSupported;
-#endif  // ENABLE_TREBLE
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp
deleted file mode 100644
index 3edd50b..0000000
--- a/services/sensorservice/SensorDeviceTreble.cpp
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * 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 <android-base/logging.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include "SensorDevice.h"
-#include "SensorService.h"
-
-#include <sensors/convert.h>
-
-using android::hardware::hidl_vec;
-
-using namespace android::hardware::sensors::V1_0;
-using namespace android::hardware::sensors::V1_0::implementation;
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
-
-static status_t StatusFromResult(Result result) {
-    switch (result) {
-        case Result::OK:
-            return OK;
-        case Result::BAD_VALUE:
-            return BAD_VALUE;
-        case Result::PERMISSION_DENIED:
-            return PERMISSION_DENIED;
-        case Result::INVALID_OPERATION:
-            return INVALID_OPERATION;
-        case Result::NO_MEMORY:
-            return NO_MEMORY;
-    }
-}
-
-SensorDevice::SensorDevice() {
-    mSensors = ISensors::getService();
-
-    if (mSensors == NULL) {
-        return;
-    }
-
-    mSensors->getSensorsList(
-            [&](const auto &list) {
-                const size_t count = list.size();
-
-                mActivationCount.setCapacity(count);
-                Info model;
-                for (size_t i=0 ; i < count; i++) {
-                    sensor_t sensor;
-                    convertToSensor(list[i], &sensor);
-                    mSensorList.push_back(sensor);
-
-                    mActivationCount.add(list[i].sensorHandle, model);
-
-                    mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
-                }
-            });
-
-    mIsDirectReportSupported =
-           (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 */);
-    } else {
-        mActivationCount.removeItem(handle);
-    }
-}
-
-std::string SensorDevice::dump() const {
-    if (mSensors == NULL) return "HAL not initialized\n";
-
-    String8 result;
-    mSensors->getSensorsList([&](const auto &list) {
-            const size_t count = list.size();
-
-            result.appendFormat(
-                "Total %zu h/w sensors, %zu running:\n",
-                count,
-                mActivationCount.size());
-
-            Mutex::Autolock _l(mLock);
-            for (size_t i = 0 ; i < count ; i++) {
-                const Info& info = mActivationCount.valueFor(
-                    list[i].sensorHandle);
-
-                if (info.batchParams.isEmpty()) continue;
-                result.appendFormat(
-                    "0x%08x) active-count = %zu; ",
-                    list[i].sensorHandle,
-                    info.batchParams.size());
-
-                result.append("sampling_period(ms) = {");
-                for (size_t j = 0; j < info.batchParams.size(); j++) {
-                    const BatchParams& params = info.batchParams.valueAt(j);
-                    result.appendFormat(
-                        "%.1f%s",
-                        params.batchDelay / 1e6f,
-                        j < info.batchParams.size() - 1 ? ", " : "");
-                }
-                result.appendFormat(
-                        "}, selected = %.1f ms; ",
-                        info.bestBatchParams.batchDelay / 1e6f);
-
-                result.append("batching_period(ms) = {");
-                for (size_t j = 0; j < info.batchParams.size(); j++) {
-                    BatchParams params = info.batchParams.valueAt(j);
-
-                    result.appendFormat(
-                            "%.1f%s",
-                            params.batchTimeout / 1e6f,
-                            j < info.batchParams.size() - 1 ? ", " : "");
-                }
-
-                result.appendFormat(
-                        "}, selected = %.1f ms\n",
-                        info.bestBatchParams.batchTimeout / 1e6f);
-            }
-        });
-
-    return result.string();
-}
-
-ssize_t SensorDevice::getSensorList(sensor_t const** list) {
-    *list = &mSensorList[0];
-
-    return mSensorList.size();
-}
-
-status_t SensorDevice::initCheck() const {
-    return mSensors != NULL ? NO_ERROR : NO_INIT;
-}
-
-ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
-    if (mSensors == NULL) return NO_INIT;
-
-    ssize_t err;
-
-    mSensors->poll(
-            count,
-            [&](auto result,
-                const auto &events,
-                const auto &dynamicSensorsAdded) {
-                if (result == Result::OK) {
-                    convertToSensorEvents(events, dynamicSensorsAdded, buffer);
-                    err = (ssize_t)events.size();
-                } else {
-                    err = StatusFromResult(result);
-                }
-            });
-
-    return err;
-}
-
-void SensorDevice::autoDisable(void *ident, int handle) {
-    Info& info( mActivationCount.editValueFor(handle) );
-    Mutex::Autolock _l(mLock);
-    info.removeBatchParamsForIdent(ident);
-}
-
-status_t SensorDevice::activate(void* ident, int handle, int enabled) {
-    if (mSensors == NULL) return NO_INIT;
-
-    status_t err(NO_ERROR);
-    bool actuateHardware = false;
-
-    Mutex::Autolock _l(mLock);
-    Info& info( mActivationCount.editValueFor(handle) );
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
-             ident, handle, enabled, info.batchParams.size());
-
-    if (enabled) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
-
-        if (isClientDisabledLocked(ident)) {
-            ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
-                    ident, handle);
-            return INVALID_OPERATION;
-        }
-
-        if (info.batchParams.indexOfKey(ident) >= 0) {
-          if (info.numActiveClients() == 1) {
-              // This is the first connection, we need to activate the underlying h/w sensor.
-              actuateHardware = true;
-          }
-        } else {
-            // Log error. Every activate call should be preceded by a batch() call.
-            ALOGE("\t >>>ERROR: activate called without batch");
-        }
-    } else {
-        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
-
-        // If a connected dynamic sensor is deactivated, remove it from the
-        // dictionary.
-        auto it = mConnectedDynamicSensors.find(handle);
-        if (it != mConnectedDynamicSensors.end()) {
-            delete it->second;
-            mConnectedDynamicSensors.erase(it);
-        }
-
-        if (info.removeBatchParamsForIdent(ident) >= 0) {
-            if (info.numActiveClients() == 0) {
-                // This is the last connection, we need to de-activate the underlying h/w sensor.
-                actuateHardware = true;
-            } else {
-                // Call batch for this sensor with the previously calculated best effort
-                // batch_rate and timeout. One of the apps has unregistered for sensor
-                // events, and the best effort batch parameters might have changed.
-                ALOGD_IF(DEBUG_CONNECTIONS,
-                         "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
-                         info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                         info.bestBatchParams.batchTimeout);
-                mSensors->batch(
-                        handle,
-                        info.bestBatchParams.batchDelay,
-                        info.bestBatchParams.batchTimeout);
-            }
-        } else {
-            // sensor wasn't enabled for this ident
-        }
-
-        if (isClientDisabledLocked(ident)) {
-            return NO_ERROR;
-        }
-    }
-
-    if (actuateHardware) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
-                 enabled);
-        err = StatusFromResult(mSensors->activate(handle, enabled));
-        ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
-                 strerror(-err));
-
-        if (err != NO_ERROR && enabled) {
-            // Failure when enabling the sensor. Clean up on failure.
-            info.removeBatchParamsForIdent(ident);
-        }
-    }
-
-    return err;
-}
-
-status_t SensorDevice::batch(
-        void* ident,
-        int handle,
-        int flags,
-        int64_t samplingPeriodNs,
-        int64_t maxBatchReportLatencyNs) {
-    if (mSensors == NULL) return NO_INIT;
-
-    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
-        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
-    }
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
-             ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
-
-    Mutex::Autolock _l(mLock);
-    Info& info(mActivationCount.editValueFor(handle));
-
-    if (info.batchParams.indexOfKey(ident) < 0) {
-        BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
-        info.batchParams.add(ident, params);
-    } else {
-        // A batch has already been called with this ident. Update the batch parameters.
-        info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
-    }
-
-    BatchParams prevBestBatchParams = info.bestBatchParams;
-    // Find the minimum of all timeouts and batch_rates for this sensor.
-    info.selectBatchParams();
-
-    ALOGD_IF(DEBUG_CONNECTIONS,
-             "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
-             " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
-             prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
-             prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
-
-    status_t err(NO_ERROR);
-    // If the min period or min timeout has changed since the last batch call, call batch.
-    if (prevBestBatchParams != info.bestBatchParams) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
-                 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                 info.bestBatchParams.batchTimeout);
-        err = StatusFromResult(
-                mSensors->batch(
-                    handle,
-                    info.bestBatchParams.batchDelay,
-                    info.bestBatchParams.batchTimeout));
-        if (err != NO_ERROR) {
-            ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
-                  mSensors.get(), handle,
-                  info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
-                  info.bestBatchParams.batchTimeout, strerror(-err));
-            info.removeBatchParamsForIdent(ident);
-        }
-    }
-    return err;
-}
-
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
-    if (mSensors == NULL) return NO_INIT;
-    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
-        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
-    }
-    Mutex::Autolock _l(mLock);
-    if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
-    Info& info( mActivationCount.editValueFor(handle) );
-    // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
-    // Calling setDelay() in batch mode is an invalid operation.
-    if (info.bestBatchParams.batchTimeout != 0) {
-      return INVALID_OPERATION;
-    }
-    ssize_t index = info.batchParams.indexOfKey(ident);
-    if (index < 0) {
-        return BAD_INDEX;
-    }
-    BatchParams& params = info.batchParams.editValueAt(index);
-    params.batchDelay = samplingPeriodNs;
-    info.selectBatchParams();
-
-    return StatusFromResult(
-            mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
-}
-
-int SensorDevice::getHalDeviceVersion() const {
-    if (mSensors == NULL) return -1;
-    return SENSORS_DEVICE_API_VERSION_1_4;
-}
-
-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));
-}
-
-bool SensorDevice::isClientDisabled(void* ident) {
-    Mutex::Autolock _l(mLock);
-    return isClientDisabledLocked(ident);
-}
-
-bool SensorDevice::isClientDisabledLocked(void* ident) {
-    return mDisabledClients.indexOf(ident) >= 0;
-}
-
-void SensorDevice::enableAllSensors() {
-    Mutex::Autolock _l(mLock);
-    mDisabledClients.clear();
-    ALOGI("cleared mDisabledClients");
-    for (size_t i = 0; i< mActivationCount.size(); ++i) {
-        Info& info = mActivationCount.editValueAt(i);
-        if (info.batchParams.isEmpty()) continue;
-        info.selectBatchParams();
-        const int sensor_handle = mActivationCount.keyAt(i);
-        ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
-                   sensor_handle);
-        status_t err = StatusFromResult(
-                mSensors->batch(
-                    sensor_handle,
-                    info.bestBatchParams.batchDelay,
-                    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 */));
-            ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
-        }
-    }
-}
-
-void SensorDevice::disableAllSensors() {
-    Mutex::Autolock _l(mLock);
-   for (size_t i = 0; i< mActivationCount.size(); ++i) {
-        const Info& info = mActivationCount.valueAt(i);
-        // Check if this sensor has been activated previously and disable it.
-        if (info.batchParams.size() > 0) {
-           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 */);
-
-           // Add all the connections that were registered for this sensor to the disabled
-           // clients list.
-           for (size_t j = 0; j < info.batchParams.size(); ++j) {
-               mDisabledClients.add(info.batchParams.keyAt(j));
-               ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
-           }
-        }
-    }
-}
-
-status_t SensorDevice::injectSensorData(
-        const sensors_event_t *injected_sensor_event) {
-    ALOGD_IF(DEBUG_CONNECTIONS,
-            "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
-            injected_sensor_event->sensor,
-            injected_sensor_event->timestamp, injected_sensor_event->data[0],
-            injected_sensor_event->data[1], injected_sensor_event->data[2],
-            injected_sensor_event->data[3], injected_sensor_event->data[4],
-            injected_sensor_event->data[5]);
-
-    Event ev;
-    convertFromSensorEvent(*injected_sensor_event, &ev);
-
-    return StatusFromResult(mSensors->injectSensorData(ev));
-}
-
-status_t SensorDevice::setMode(uint32_t mode) {
-
-     return StatusFromResult(
-             mSensors->setOperationMode(
-                 static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
-}
-
-// ---------------------------------------------------------------------------
-
-int SensorDevice::Info::numActiveClients() {
-    SensorDevice& device(SensorDevice::getInstance());
-    int num = 0;
-    for (size_t i = 0; i < batchParams.size(); ++i) {
-        if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
-            ++num;
-        }
-    }
-    return num;
-}
-
-status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
-                                                    int64_t samplingPeriodNs,
-                                                    int64_t maxBatchReportLatencyNs) {
-    ssize_t index = batchParams.indexOfKey(ident);
-    if (index < 0) {
-        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
-              ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
-        return BAD_INDEX;
-    }
-    BatchParams& params = batchParams.editValueAt(index);
-    params.flags = flags;
-    params.batchDelay = samplingPeriodNs;
-    params.batchTimeout = maxBatchReportLatencyNs;
-    return NO_ERROR;
-}
-
-void SensorDevice::Info::selectBatchParams() {
-    BatchParams bestParams(0, -1, -1);
-    SensorDevice& device(SensorDevice::getInstance());
-
-    for (size_t i = 0; i < batchParams.size(); ++i) {
-        if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
-        BatchParams params = batchParams.valueAt(i);
-        if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
-            bestParams.batchDelay = params.batchDelay;
-        }
-        if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
-            bestParams.batchTimeout = params.batchTimeout;
-        }
-    }
-    bestBatchParams = bestParams;
-}
-
-ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
-    ssize_t idx = batchParams.removeItem(ident);
-    if (idx >= 0) {
-        selectBatchParams();
-    }
-    return idx;
-}
-
-void SensorDevice::notifyConnectionDestroyed(void* ident) {
-    Mutex::Autolock _l(mLock);
-    mDisabledClients.remove(ident);
-}
-
-int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
-    Mutex::Autolock _l(mLock);
-
-    SharedMemType type;
-    switch (memory->type) {
-        case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
-            type = SharedMemType::ASHMEM;
-            break;
-        case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
-            type = SharedMemType::GRALLOC;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-
-    SharedMemFormat format;
-    if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
-        return BAD_VALUE;
-    }
-    format = SharedMemFormat::SENSORS_EVENT;
-
-    SharedMemInfo mem = {
-        .type = type,
-        .format = format,
-        .size = static_cast<uint32_t>(memory->size),
-        .memoryHandle = memory->handle,
-    };
-
-    int32_t ret;
-    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);
-}
-
-int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle,
-        int32_t channelHandle, const struct sensors_direct_cfg_t *config) {
-    Mutex::Autolock _l(mLock);
-
-    RateLevel rate;
-    switch(config->rate_level) {
-        case SENSOR_DIRECT_RATE_STOP:
-            rate = RateLevel::STOP;
-            break;
-        case SENSOR_DIRECT_RATE_NORMAL:
-            rate = RateLevel::NORMAL;
-            break;
-        case SENSOR_DIRECT_RATE_FAST:
-            rate = RateLevel::FAST;
-            break;
-        case SENSOR_DIRECT_RATE_VERY_FAST:
-            rate = RateLevel::VERY_FAST;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-
-    int32_t ret;
-    mSensors->configDirectReport(sensorHandle, channelHandle, rate,
-            [&ret, rate] (auto result, auto token) {
-                if (rate == RateLevel::STOP) {
-                    ret = StatusFromResult(result);
-                } else {
-                    if (result == Result::OK) {
-                        ret = token;
-                    } else {
-                        ret = StatusFromResult(result);
-                    }
-                }
-            });
-
-    return ret;
-}
-
-bool SensorDevice::isDirectReportSupported() const {
-    return mIsDirectReportSupported;
-}
-
-void SensorDevice::convertToSensorEvent(
-        const Event &src, sensors_event_t *dst) {
-    ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
-            src, dst);
-
-    if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
-        const DynamicSensorInfo &dyn = src.u.dynamic;
-
-        dst->dynamic_sensor_meta.connected = dyn.connected;
-        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
-        if (dyn.connected) {
-            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
-            CHECK(it != mConnectedDynamicSensors.end());
-
-            dst->dynamic_sensor_meta.sensor = it->second;
-
-            memcpy(dst->dynamic_sensor_meta.uuid,
-                   dyn.uuid.data(),
-                   sizeof(dst->dynamic_sensor_meta.uuid));
-        }
-    }
-}
-
-void SensorDevice::convertToSensorEvents(
-        const hidl_vec<Event> &src,
-        const hidl_vec<SensorInfo> &dynamicSensorsAdded,
-        sensors_event_t *dst) {
-    // Allocate a sensor_t structure for each dynamic sensor added and insert
-    // it into the dictionary of connected dynamic sensors keyed by handle.
-    for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
-        const SensorInfo &info = dynamicSensorsAdded[i];
-
-        auto it = mConnectedDynamicSensors.find(info.sensorHandle);
-        CHECK(it == mConnectedDynamicSensors.end());
-
-        sensor_t *sensor = new sensor_t;
-        convertToSensor(info, sensor);
-
-        mConnectedDynamicSensors.insert(
-                std::make_pair(sensor->handle, sensor));
-    }
-
-    for (size_t i = 0; i < src.size(); ++i) {
-        convertToSensorEvent(src[i], &dst[i]);
-    }
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
index 1996a00..34cd8dd 100644
--- a/services/sensorservice/SensorServiceUtils.cpp
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -54,6 +54,7 @@
         case SENSOR_TYPE_STATIONARY_DETECT:
         case SENSOR_TYPE_MOTION_DETECT:
         case SENSOR_TYPE_HEART_BEAT:
+        case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT:
             return 1;
 
         default:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index aa8f189..9e81a8c 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -133,6 +133,7 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libhwcomposer-command-buffer \
+    android.hardware.configstore-utils \
     libtrace_proto \
     libvkjson \
     libvr_manager \
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6c18ef7..9af4402 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -47,6 +47,9 @@
 #include "SurfaceFlinger.h"
 #include "Layer.h"
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
 // ----------------------------------------------------------------------------
 using namespace android;
 // ----------------------------------------------------------------------------
@@ -57,6 +60,14 @@
 static constexpr bool kEGLAndroidSwapRectangle = false;
 #endif
 
+// retrieve triple buffer setting from configstore
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
+static bool useTripleFramebuffer = getBool<
+        ISurfaceFlingerConfigs,
+        &ISurfaceFlingerConfigs::useTripleFramebuffer>(false);
+
 #if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
 // Dummy implementation in case it is missing.
 inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
@@ -165,9 +176,9 @@
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
 
-#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
-    surface->allocateBuffers();
-#endif
+    if (useTripleFramebuffer) {
+        surface->allocateBuffers();
+    }
 }
 
 DisplayDevice::~DisplayDevice() {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 2b603cc..a6171f5 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -2010,7 +2010,8 @@
     mZ(0),
     mReleaseFence(),
     mHwc1Id(0),
-    mHasUnsupportedPlaneAlpha(false) {}
+    mHasUnsupportedPlaneAlpha(false),
+    mHasUnsupportedBackgroundColor(false) {}
 
 bool HWC2On1Adapter::SortLayersByZ::operator()(
         const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs)
@@ -2466,7 +2467,7 @@
         }
     }
 
-    if (mHwc1DisplayMap.count(0) == 0) {
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) {
         ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
         return false;
     }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1c99036..4a281d4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -60,9 +60,8 @@
 
 // ---------------------------------------------------------------------------
 
-HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer)
-    : mFlinger(flinger),
-      mAdapter(),
+HWComposer::HWComposer(bool useVrComposer)
+    : mAdapter(),
       mHwcDevice(),
       mDisplayData(2),
       mFreeDisplaySlots(),
@@ -211,7 +210,7 @@
 }
 
 void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
-    mFlinger->repaintEverything();
+    mEventHandler->onInvalidateReceived(this);
 }
 
 void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
@@ -257,7 +256,7 @@
     snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
     ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
 
-    mEventHandler->onVSyncReceived(disp, timestamp);
+    mEventHandler->onVSyncReceived(this, disp, timestamp);
 }
 
 status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -915,6 +914,10 @@
         const sp<GraphicBuffer>& buffer,
         uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
 {
+#ifdef BYPASS_IHWC
+    *outSlot = slot;
+    *outBuffer = buffer;
+#else
     if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
         // default to slot 0
         slot = 0;
@@ -935,6 +938,7 @@
         // update cache
         mBuffers[slot] = buffer;
     }
+#endif
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7b61e0e..0713709 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -64,15 +64,16 @@
 class NativeHandle;
 class Region;
 class String8;
-class SurfaceFlinger;
 
 class HWComposer
 {
 public:
     class EventHandler {
         friend class HWComposer;
-        virtual void onVSyncReceived(int32_t disp, nsecs_t timestamp) = 0;
+        virtual void onVSyncReceived(
+            HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
         virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
+        virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
     };
@@ -80,7 +81,7 @@
     // useVrComposer is passed to the composer HAL. When true, the composer HAL
     // will use the vr composer service, otherwise it uses the real hardware
     // composer.
-    HWComposer(const sp<SurfaceFlinger>& flinger, bool useVrComposer);
+    HWComposer(bool useVrComposer);
 
     ~HWComposer();
 
@@ -211,7 +212,6 @@
         HWC2::Vsync vsyncEnabled;
     };
 
-    sp<SurfaceFlinger>              mFlinger;
     std::unique_ptr<HWC2On1Adapter> mAdapter;
     std::unique_ptr<HWC2::Device>   mHwcDevice;
     std::vector<DisplayData>        mDisplayData;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index e0946a7..bb815cc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -277,7 +277,7 @@
 }
 
 void HWComposer::invalidate() {
-    mFlinger->repaintEverything();
+    mEventHandler.onInvalidateReceived(this);
 }
 
 void HWComposer::vsync(int disp, int64_t timestamp) {
@@ -302,7 +302,7 @@
         snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
         ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
 
-        mEventHandler.onVSyncReceived(disp, timestamp);
+        mEventHandler.onVSyncReceived(this, disp, timestamp);
     }
 }
 
@@ -1319,7 +1319,7 @@
     } while (err<0 && errno == EINTR);
 
     if (err == 0) {
-        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
+        mHwc.mEventHandler.onVSyncReceived(&mHwc, 0, next_vsync);
     }
 
     return true;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index bca25ac..a94bc1e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -62,8 +62,10 @@
 public:
     class EventHandler {
         friend class HWComposer;
-        virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
+        virtual void onVSyncReceived(
+            HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
         virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onInvalidateReceived(HWComposer* composer) = 0;
     protected:
         virtual ~EventHandler() {}
     };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index bb1fca6..0eef708 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -155,6 +155,10 @@
             flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
 #endif
     mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
+
+    CompositorTiming compositorTiming;
+    flinger->getCompositorTiming(&compositorTiming);
+    mFrameEventHistory.initializeCompositorTiming(compositorTiming);
 }
 
 void Layer::onFirstRef() {
@@ -427,7 +431,9 @@
     Rect bounds = win;
     const auto& p = getParent();
     if (p != nullptr) {
-        bounds = p->computeScreenBounds();
+        // Look in computeScreenBounds recursive call for explanation of
+        // why we pass false here.
+        bounds = p->computeScreenBounds(false /* reduceTransparentRegion */);
     }
 
     Transform t = getTransform();
@@ -1881,10 +1887,10 @@
     return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
 }
 
-bool Layer::onPostComposition(
-        const std::shared_ptr<FenceTime>& glDoneFence,
+bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
         const std::shared_ptr<FenceTime>& presentFence,
-        const std::shared_ptr<FenceTime>& retireFence) {
+        const std::shared_ptr<FenceTime>& retireFence,
+        const CompositorTiming& compositorTiming) {
     mAcquireTimeline.updateSignalTimes();
     mReleaseTimeline.updateSignalTimes();
 
@@ -1897,7 +1903,7 @@
     {
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
-                glDoneFence, presentFence);
+                glDoneFence, presentFence, compositorTiming);
         mFrameEventHistory.addRetire(mPreviousFrameNumber,
                 retireFence);
     }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 12166a8..8227dae 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -296,10 +296,10 @@
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
-    bool onPostComposition(
-            const std::shared_ptr<FenceTime>& glDoneFence,
+    bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
             const std::shared_ptr<FenceTime>& presentFence,
-            const std::shared_ptr<FenceTime>& retireFence);
+            const std::shared_ptr<FenceTime>& retireFence,
+            const CompositorTiming& compositorTiming);
 
 #ifdef USE_HWC2
     // If a buffer was replaced this frame, release the former buffer
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8af0357..462e5a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -87,6 +87,7 @@
 #include <cutils/compiler.h>
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
 
 #define DISPLAY_COUNT       1
 
@@ -100,22 +101,9 @@
 
 namespace android {
 
+using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 
-static sp<ISurfaceFlingerConfigs> getConfigs() {
-    static sp<ISurfaceFlingerConfigs> configs
-            = ISurfaceFlingerConfigs::getService();
-    return configs;
-}
-
-static int64_t getVsyncEventPhaseOffsetNs() {
-    int64_t ret = 1000000; // default value
-    getConfigs()->vsyncEventPhaseOffsetNs([&](OptionalInt64 value) {
-          if (value.specified) ret = value.value;
-    });
-    return ret;
-}
-
 // This is the phase offset in nanoseconds of the software vsync event
 // relative to the vsync event reported by HWComposer.  The software vsync
 // event is when SurfaceFlinger and Choreographer-based applications run each
@@ -136,10 +124,12 @@
 // the latency will end up being an additional vsync period, and animations
 // will hiccup.  Therefore, this latency should be tuned somewhat
 // conservatively (or at least with awareness of the trade-off being made).
-static int64_t vsyncPhaseOffsetNs = getVsyncEventPhaseOffsetNs();
+static int64_t vsyncPhaseOffsetNs = getInt64<
+        ISurfaceFlingerConfigs,
+        &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
 
 // This is the phase offset at which SurfaceFlinger's composition runs.
-static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
+static constexpr int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
 
 // ---------------------------------------------------------------------------
 
@@ -219,8 +209,8 @@
     mUseHwcVirtualDisplays = atoi(value);
     ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
 
-    property_get("ro.sf.disable_triple_buffer", value, "0");
-    mLayerTripleBufferingDisabled = !atoi(value);
+    property_get("ro.sf.disable_triple_buffer", value, "1");
+    mLayerTripleBufferingDisabled = atoi(value);
     ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
 }
 
@@ -579,7 +569,7 @@
     // the lock because on creation, it will call back into SurfaceFlinger to
     // initialize the primary display.
     LOG_ALWAYS_FATAL_IF(mEnterVrMode, "Starting in vr mode is not currently supported.");
-    mRealHwc = new HWComposer(this, false);
+    mRealHwc = new HWComposer(false);
     mHwc = mRealHwc;
     mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
 
@@ -1102,7 +1092,14 @@
     }
 }
 
-void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) {
+void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
+                                     nsecs_t timestamp) {
+    Mutex::Autolock lock(mStateLock);
+    // Ignore any vsyncs from the non-active hardware composer.
+    if (composer != mHwc) {
+        return;
+    }
+
     bool needsHwVsync = false;
 
     { // Scope for the lock
@@ -1119,6 +1116,11 @@
     }
 }
 
+void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
+    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+    *compositorTiming = mCompositorTiming;
+}
+
 void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
     ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
     if (disp == DisplayDevice::DISPLAY_PRIMARY) {
@@ -1163,6 +1165,20 @@
     }
 }
 
+void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) {
+    Mutex::Autolock lock(mStateLock);
+    if (composer == mHwc) {
+        repaintEverything();
+    } else {
+        // This isn't from our current hardware composer. If it's a callback
+        // from the real composer, forward the refresh request to vr
+        // flinger. Otherwise ignore it.
+        if (!composer->isUsingVrComposer()) {
+            mVrFlinger->OnHardwareComposerRefresh();
+        }
+    }
+}
+
 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
     ATRACE_CALL();
     getHwComposer().setVsyncEnabled(disp,
@@ -1209,7 +1225,7 @@
             }
 
             if (!mVrHwc) {
-                mVrHwc = new HWComposer(this, true);
+                mVrHwc = new HWComposer(true);
                 ALOGV("Vr HWC created");
             }
 
@@ -1240,11 +1256,13 @@
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
-            updateVrMode();
+            // TODO(eieio): Disabled until SELinux issues are resolved.
+            //updateVrMode();
 
             bool frameMissed = !mHadClientComposition &&
                     mPreviousPresentFence != Fence::NO_FENCE &&
-                    mPreviousPresentFence->getSignalTime() == INT64_MAX;
+                    (mPreviousPresentFence->getSignalTime() ==
+                            Fence::SIGNAL_TIME_PENDING);
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
             if (mPropagateBackpressure && frameMissed) {
                 signalLayerUpdate();
@@ -1293,7 +1311,7 @@
     setUpHWComposer();
     doDebugFlashRegions();
     doComposition();
-    postComposition();
+    postComposition(refreshStartTime);
 
     mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
 
@@ -1368,7 +1386,61 @@
     }
 }
 
-void SurfaceFlinger::postComposition()
+void SurfaceFlinger::updateCompositorTiming(
+        nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+        std::shared_ptr<FenceTime>& presentFenceTime) {
+    // Update queue of past composite+present times and determine the
+    // most recently known composite to present latency.
+    mCompositePresentTimes.push({compositeTime, presentFenceTime});
+    nsecs_t compositeToPresentLatency = -1;
+    while (!mCompositePresentTimes.empty()) {
+        CompositePresentTime& cpt = mCompositePresentTimes.front();
+        // Cached values should have been updated before calling this method,
+        // which helps avoid duplicate syscalls.
+        nsecs_t displayTime = cpt.display->getCachedSignalTime();
+        if (displayTime == Fence::SIGNAL_TIME_PENDING) {
+            break;
+        }
+        compositeToPresentLatency = displayTime - cpt.composite;
+        mCompositePresentTimes.pop();
+    }
+
+    // Don't let mCompositePresentTimes grow unbounded, just in case.
+    while (mCompositePresentTimes.size() > 16) {
+        mCompositePresentTimes.pop();
+    }
+
+    // Integer division and modulo round toward 0 not -inf, so we need to
+    // treat negative and positive offsets differently.
+    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
+            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+
+    // Snap the latency to a value that removes scheduling jitter from the
+    // composition and present times, which often have >1ms of jitter.
+    // Reducing jitter is important if an app attempts to extrapolate
+    // something (such as user input) to an accurate diasplay time.
+    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+    // with (presentLatency % interval).
+    nsecs_t snappedCompositeToPresentLatency = -1;
+    if (compositeToPresentLatency >= 0) {
+        nsecs_t bias = vsyncInterval / 2;
+        int64_t extraVsyncs =
+                (compositeToPresentLatency - idealLatency + bias) /
+                vsyncInterval;
+        nsecs_t extraLatency = extraVsyncs * vsyncInterval;
+        snappedCompositeToPresentLatency = idealLatency + extraLatency;
+    }
+
+    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+    mCompositorTiming.deadline = vsyncPhase - idealLatency;
+    mCompositorTiming.interval = vsyncInterval;
+    if (snappedCompositeToPresentLatency >= 0) {
+        mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
+    }
+}
+
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
 {
     ATRACE_CALL();
     ALOGV("postComposition");
@@ -1403,9 +1475,19 @@
     } else {
         retireFenceTime = &displayFenceTime;
     }
+
+    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
+    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
+
+    // We use the refreshStartTime which might be sampled a little later than
+    // when we started doing work for this frame, but that should be okay
+    // since updateCompositorTiming has snapping logic.
+    updateCompositorTiming(
+        vsyncPhase, vsyncInterval, refreshStartTime, displayFenceTime);
+
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
-                *presentFenceTime, *retireFenceTime);
+                *presentFenceTime, *retireFenceTime, mCompositorTiming);
         if (frameLatched) {
             recordBufferingStats(layer->getName().string(),
                     layer->getOccupancyHistory(false));
@@ -1450,9 +1532,8 @@
     if (mHasPoweredOff) {
         mHasPoweredOff = false;
     } else {
-        nsecs_t period = mPrimaryDispSync.getPeriod();
         nsecs_t elapsedTime = currentTime - mLastSwapTime;
-        size_t numPeriods = static_cast<size_t>(elapsedTime / period);
+        size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncInterval);
         if (numPeriods < NUM_BUCKETS - 1) {
             mFrameBuckets[numPeriods] += elapsedTime;
         } else {
@@ -2855,6 +2936,11 @@
     const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
     const nsecs_t period = activeConfig->getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(period);
+
+    {
+        std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+        mCompositorTiming.interval = period;
+    }
 }
 
 void SurfaceFlinger::initializeDisplays() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6dfdf08..f52bd2d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -42,6 +42,7 @@
 #include <ui/PixelFormat.h>
 #include <ui/mat4.h>
 
+#include <gui/FrameTimestamps.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/OccupancyTracker.h>
@@ -65,7 +66,10 @@
 #include "Effects/Daltonizer.h"
 
 #include <map>
+#include <mutex>
+#include <queue>
 #include <string>
+#include <utility>
 
 namespace android {
 
@@ -247,8 +251,9 @@
     /* ------------------------------------------------------------------------
      * HWComposer::EventHandler interface
      */
-    virtual void onVSyncReceived(int type, nsecs_t timestamp);
+    virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
     virtual void onHotplugReceived(int disp, bool connected);
+    virtual void onInvalidateReceived(HWComposer* composer);
 
     /* ------------------------------------------------------------------------
      * Message handling
@@ -412,7 +417,10 @@
             Region& dirtyRegion, Region& opaqueRegion);
 
     void preComposition(nsecs_t refreshStartTime);
-    void postComposition();
+    void postComposition(nsecs_t refreshStartTime);
+    void updateCompositorTiming(
+            nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+            std::shared_ptr<FenceTime>& presentFenceTime);
     void rebuildLayerStacks();
     void setUpHWComposer();
     void doComposition();
@@ -433,12 +441,13 @@
     /* ------------------------------------------------------------------------
      * VSync
      */
-     void enableHardwareVsync();
-     void resyncToHardwareVsync(bool makeAvailable);
-     void disableHardwareVsync(bool makeUnavailable);
+    void enableHardwareVsync();
+    void resyncToHardwareVsync(bool makeAvailable);
+    void disableHardwareVsync(bool makeUnavailable);
 
 public:
-     void resyncWithRateLimit();
+    void resyncWithRateLimit();
+    void getCompositorTiming(CompositorTiming* compositorTiming);
 private:
 
     /* ------------------------------------------------------------------------
@@ -580,6 +589,17 @@
     bool mPrimaryHWVsyncEnabled;
     bool mHWVsyncAvailable;
 
+    // protected by mCompositorTimingLock;
+    mutable std::mutex mCompositeTimingLock;
+    CompositorTiming mCompositorTiming;
+
+    // Only accessed from the main thread.
+    struct CompositePresentTime {
+        nsecs_t composite { -1 };
+        std::shared_ptr<FenceTime> display { FenceTime::NO_FENCE };
+    };
+    std::queue<CompositePresentTime> mCompositePresentTimes;
+
     /* ------------------------------------------------------------------------
      * Feature prototyping
      */
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index faa68e8..477eb27 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -192,8 +192,8 @@
     mUseHwcVirtualDisplays = atoi(value);
     ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
 
-    property_get("ro.sf.disable_triple_buffer", value, "0");
-    mLayerTripleBufferingDisabled = !atoi(value);
+    property_get("ro.sf.disable_triple_buffer", value, "1");
+    mLayerTripleBufferingDisabled = atoi(value);
     ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
 }
 
@@ -1018,7 +1018,8 @@
     }
 }
 
-void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
+void SurfaceFlinger::onVSyncReceived(HWComposer* /*composer*/, int type,
+                                     nsecs_t timestamp) {
     bool needsHwVsync = false;
 
     { // Scope for the lock
@@ -1035,6 +1036,11 @@
     }
 }
 
+void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
+    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+    *compositorTiming = mCompositorTiming;
+}
+
 void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
     if (mEventThread == NULL) {
         // This is a temporary workaround for b/7145521.  A non-null pointer
@@ -1058,6 +1064,10 @@
     }
 }
 
+void SurfaceFlinger::onInvalidateReceived(HWComposer* /*composer*/) {
+    repaintEverything();
+}
+
 void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
     ATRACE_CALL();
     getHwComposer().eventControl(disp, event, enabled);
@@ -1109,7 +1119,7 @@
     setUpHWComposer();
     doDebugFlashRegions();
     doComposition();
-    postComposition();
+    postComposition(refreshStartTime);
 }
 
 void SurfaceFlinger::doDebugFlashRegions()
@@ -1166,7 +1176,61 @@
     }
 }
 
-void SurfaceFlinger::postComposition()
+void SurfaceFlinger::updateCompositorTiming(
+        nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
+        std::shared_ptr<FenceTime>& presentFenceTime) {
+    // Update queue of past composite+present times and determine the
+    // most recently known composite to present latency.
+    mCompositePresentTimes.push({compositeTime, presentFenceTime});
+    nsecs_t compositeToPresentLatency = -1;
+    while (!mCompositePresentTimes.empty()) {
+        CompositePresentTime& cpt = mCompositePresentTimes.front();
+        // Cached values should have been updated before calling this method,
+        // which helps avoid duplicate syscalls.
+        nsecs_t displayTime = cpt.display->getCachedSignalTime();
+        if (displayTime == Fence::SIGNAL_TIME_PENDING) {
+            break;
+        }
+        compositeToPresentLatency = displayTime - cpt.composite;
+        mCompositePresentTimes.pop();
+    }
+
+    // Don't let mCompositePresentTimes grow unbounded, just in case.
+    while (mCompositePresentTimes.size() > 16) {
+        mCompositePresentTimes.pop();
+    }
+
+    // Integer division and modulo round toward 0 not -inf, so we need to
+    // treat negative and positive offsets differently.
+    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
+            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+
+    // Snap the latency to a value that removes scheduling jitter from the
+    // composition and present times, which often have >1ms of jitter.
+    // Reducing jitter is important if an app attempts to extrapolate
+    // something (such as user input) to an accurate diasplay time.
+    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+    // with (presentLatency % interval).
+    nsecs_t snappedCompositeToPresentLatency = -1;
+    if (compositeToPresentLatency >= 0) {
+        nsecs_t bias = vsyncInterval / 2;
+        int64_t extraVsyncs =
+                (compositeToPresentLatency - idealLatency + bias) /
+                vsyncInterval;
+        nsecs_t extraLatency = extraVsyncs * vsyncInterval;
+        snappedCompositeToPresentLatency = idealLatency + extraLatency;
+    }
+
+    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+    mCompositorTiming.deadline = vsyncPhase - idealLatency;
+    mCompositorTiming.interval = vsyncInterval;
+    if (snappedCompositeToPresentLatency >= 0) {
+        mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
+    }
+}
+
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
 {
     const HWComposer& hwc = getHwComposer();
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
@@ -1187,10 +1251,18 @@
     mDisplayTimeline.push(retireFenceTime);
     mDisplayTimeline.updateSignalTimes();
 
+    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
+    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
+
+    // We use the refreshStartTime which might be sampled a little later than
+    // when we started doing work for this frame, but that should be okay
+    // since updateCompositorTiming has snapping logic.
+    updateCompositorTiming(
+        vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
+
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
-                presentFenceTime, retireFenceTime);
-
+                presentFenceTime, retireFenceTime, mCompositorTiming);
         if (frameLatched) {
             recordBufferingStats(layer->getName().string(),
                     layer->getOccupancyHistory(false));
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index 36d8400..e213bd6 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -46,21 +46,10 @@
 cFlags := -DLOG_TAG=\"sensord\" \
           -DTRACE=0
 
-ifeq ($(TARGET_USES_QCOM_BSP), true)
-ifneq ($(TARGET_QCOM_DISPLAY_VARIANT),)
-    platform := .
-else
-    platform := $(TARGET_BOARD_PLATFORM)
-endif
-    cFlags += -DQCOM_B_FAMILY \
-              -DQCOM_BSP
-endif
-
 include $(CLEAR_VARS)
 # Don't strip symbols so we see stack traces in logcat.
 LOCAL_STRIP_MODULE := false
 LOCAL_SRC_FILES := $(sourceFiles)
-PLATFORM := $(platform)
 LOCAL_CFLAGS := $(cFlags)
 LOCAL_STATIC_LIBRARIES := $(staticLibraries)
 LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
diff --git a/services/vr/sensord/sensord.rc b/services/vr/sensord/sensord.rc
index 0311474..d868a7e 100644
--- a/services/vr/sensord/sensord.rc
+++ b/services/vr/sensord/sensord.rc
@@ -1,3 +1,7 @@
+on init
+  mkdir /dev/socket/pdx/system/vr/pose 0775 system system
+  mkdir /dev/socket/pdx/system/vr/sensors 0775 system system
+
 service sensord /system/bin/sensord
   class core
   user system
diff --git a/services/vr/vr_window_manager/Android.mk b/services/vr/vr_window_manager/Android.mk
index 47d9dcc..e9552bc 100644
--- a/services/vr/vr_window_manager/Android.mk
+++ b/services/vr/vr_window_manager/Android.mk
@@ -37,33 +37,18 @@
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_STATIC_LIBRARY)
 
-
 native_src := \
   application.cpp \
   controller_mesh.cpp \
   elbow_model.cpp \
   hwc_callback.cpp \
   reticle.cpp \
-  render_thread.cpp \
   shell_view.cpp \
   surface_flinger_view.cpp \
   texture.cpp \
   vr_window_manager.cpp \
   ../virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl \
 
-src := \
-  vr_window_manager_jni.cpp \
-  application.cpp \
-  controller_mesh.cpp \
-  elbow_model.cpp \
-  hwc_callback.cpp \
-  reticle.cpp \
-  render_thread.cpp \
-  shell_view.cpp \
-  surface_flinger_view.cpp \
-  texture.cpp \
-  ../virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl \
-
 static_libs := \
   libdisplay \
   libbufferhub \
@@ -86,6 +71,7 @@
   libbinder \
   libinput \
   libhardware \
+  libhwbinder \
   libsync \
   libutils \
   libgui \
@@ -97,29 +83,10 @@
   libhidlbase \
   libhidltransport
 
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(src)
-LOCAL_STATIC_LIBRARIES := $(static_libs)
-LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_SHARED_LIBRARIES += libgvr
-LOCAL_STATIC_LIBRARIES += libgvr_ext
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
-LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\"
-LOCAL_LDLIBS := -llog
-LOCAL_MODULE := libvr_window_manager_jni
-LOCAL_MODULE_TAGS := optional
-LOCAL_MULTILIB := 64
-LOCAL_CXX_STL := libc++_static
-include $(BUILD_SHARED_LIBRARY)
-
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(native_src)
 LOCAL_STATIC_LIBRARIES := $(static_libs) libvrwm_binder
 LOCAL_SHARED_LIBRARIES := $(shared_libs)
-LOCAL_SHARED_LIBRARIES += libgvr
-LOCAL_STATIC_LIBRARIES += libgvr_ext
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
 LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -DLOG_TAG=\"VrWindowManager\"
@@ -129,27 +96,6 @@
 LOCAL_INIT_RC := vr_wm.rc
 include $(BUILD_EXECUTABLE)
 
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := VrWindowManager
-
-# We need to be priveleged to run as the system user, which is necessary for
-# getting hmd input events and doing input injection.
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-LOCAL_JNI_SHARED_LIBRARIES := libvr_window_manager_jni
-LOCAL_STATIC_JAVA_AAR_LIBRARIES := gvr_common_library_aar
-# gvr_common_library_aar depends on nano version of libprotobuf
-LOCAL_STATIC_JAVA_LIBRARIES := libprotobuf-java-nano
-# Make sure that libgvr's resources are loaded
-LOCAL_AAPT_FLAGS += --auto-add-overlay
-LOCAL_AAPT_FLAGS += --extra-packages com.google.vr.cardboard
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-include $(BUILD_PACKAGE)
-
-
 cmd_src := \
   vr_wm_ctl.cpp \
   aidl/android/service/vr/IVrWindowManager.aidl
diff --git a/services/vr/vr_window_manager/AndroidManifest.xml b/services/vr/vr_window_manager/AndroidManifest.xml
deleted file mode 100644
index d5008a3..0000000
--- a/services/vr/vr_window_manager/AndroidManifest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.google.vr.windowmanager"
-          coreApp="true"
-          android:sharedUserId="android.uid.system"
-          android:versionCode="1"
-          android:versionName="1.0" >
-
-  <!-- The GVR SDK requires API 19+ and OpenGL ES 2+. -->
-  <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="24" />
-  <uses-feature android:glEsVersion="0x00020000" android:required="true" />
-
-  <!-- We need the DIAGNOSTIC permission to read HMD button events. DIAGNOSTIC
-       ensures our process runs with the "input" group, so we can access
-       /dev/input. See frameworks/base/data/etc/platform.xml for the permission
-       to group mappings.
-
-       TODO(steventhomas): We shouldn't use this DIAGNOSTIC permission. Figure
-       out the correct way to get access to the HMD buttons.
-       Bug: b/33253485. -->
-  <uses-permission android:name="android.permission.DIAGNOSTIC"/>
-  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-
-  <application
-      android:label="vr_window_manager"
-      android:theme="@style/AppStyle">
-    <service android:name=".VrWindowManagerService" />
-    <receiver android:name="com.google.vr.windowmanager.BootCompletedReceiver">
-      <intent-filter>
-        <!-- action android:name="android.intent.action.BOOT_COMPLETED" / -->
-      </intent-filter>
-    </receiver>
-  </application>
-</manifest>
diff --git a/services/vr/vr_window_manager/application.cpp b/services/vr/vr_window_manager/application.cpp
index 895f25f..33cd499 100644
--- a/services/vr/vr_window_manager/application.cpp
+++ b/services/vr/vr_window_manager/application.cpp
@@ -16,25 +16,18 @@
 namespace android {
 namespace dvr {
 
-Application::Application()
-    : controller_api_status_logged_(false),
-      controller_connection_state_logged_(false) {}
+Application::Application() {}
 
 Application::~Application() {
 }
 
-int Application::Initialize(JNIEnv* env, jobject app_context,
-                            jobject class_loader) {
+int Application::Initialize() {
   dvrSetCpuPartition(0, "/application/performance");
 
   bool is_right_handed = true;  // TODO: retrieve setting from system
   elbow_model_.Enable(ElbowModel::kDefaultNeckPosition, is_right_handed);
   last_frame_time_ = std::chrono::system_clock::now();
 
-  java_env_ = env;
-  app_context_ = app_context;
-  class_loader_ = class_loader;
-
   return 0;
 }
 
@@ -100,42 +93,10 @@
   fov_[1] = FieldOfView(lens_info.right_fov[0], lens_info.right_fov[1],
                         lens_info.right_fov[2], lens_info.right_fov[3]);
 
-  if (java_env_) {
-    int ret = InitializeController();
-    if (ret)
-      return ret;
-  }
-
-  return 0;
-}
-
-int Application::InitializeController() {
-  gvr_context_ = gvr::GvrApi::Create(java_env_, app_context_, class_loader_);
-  if (gvr_context_ == nullptr) {
-    ALOGE("Gvr context creation failed");
-    return 1;
-  }
-
-  int32_t options = gvr_controller_get_default_options();
-  options |= GVR_CONTROLLER_ENABLE_GYRO | GVR_CONTROLLER_ENABLE_ACCEL;
-
-  controller_.reset(new gvr::ControllerApi);
-  if (!controller_->Init(java_env_, app_context_, class_loader_, options,
-                         gvr_context_->cobj())) {
-    ALOGE("Gvr controller init failed");
-    return 1;
-  }
-
-  controller_state_.reset(new gvr::ControllerState);
-
   return 0;
 }
 
 void Application::DeallocateResources() {
-  gvr_context_.reset();
-  controller_.reset();
-  controller_state_.reset();
-
   if (graphics_context_)
     dvrGraphicsContextDestroy(graphics_context_);
 
@@ -162,8 +123,8 @@
         break;
       case MainThreadTask::EnteringVrMode:
         if (!initialized_) {
-          if (AllocateResources())
-            ALOGE("Failed to allocate resources");
+          LOG_ALWAYS_FATAL_IF(AllocateResources(),
+                              "Failed to allocate resources");
         }
         break;
       case MainThreadTask::ExitingVrMode:
@@ -309,47 +270,6 @@
       return;
     }
   }
-
-  if (!controller_)
-    return;
-
-  controller_state_->Update(*controller_);
-  gvr::ControllerApiStatus new_api_status = controller_state_->GetApiStatus();
-  gvr::ControllerConnectionState new_connection_state =
-      controller_state_->GetConnectionState();
-
-  if (!controller_api_status_logged_) {
-    controller_api_status_logged_ = true;
-    ALOGI("Controller api status: %s",
-          gvr::ControllerApi::ToString(new_api_status));
-  } else if (new_api_status != controller_api_status_) {
-    ALOGI("Controller api status changed: %s --> %s",
-          gvr::ControllerApi::ToString(controller_api_status_),
-          gvr::ControllerApi::ToString(new_api_status));
-  }
-
-  if (new_api_status == gvr::kControllerApiOk) {
-    if (!controller_connection_state_logged_) {
-      controller_connection_state_logged_ = true;
-      ALOGI("Controller connection state: %s",
-            gvr::ControllerApi::ToString(new_connection_state));
-    } else if (new_connection_state != controller_connection_state_) {
-      ALOGI("Controller connection state changed: %s --> %s",
-            gvr::ControllerApi::ToString(controller_connection_state_),
-            gvr::ControllerApi::ToString(new_connection_state));
-    }
-  } else {
-    controller_connection_state_logged_ = false;
-  }
-
-  if (new_api_status == gvr::kControllerApiOk) {
-    gvr_quatf orientation = controller_state_->GetOrientation();
-    controller_orientation_ =
-        quat(orientation.qw, orientation.qx, orientation.qy, orientation.qz);
-  }
-
-  controller_api_status_ = new_api_status;
-  controller_connection_state_ = new_connection_state;
 }
 
 void Application::SetVisibility(bool visible) {
@@ -357,12 +277,6 @@
   if (changed) {
     is_visible_ = visible;
     dvrGraphicsSurfaceSetVisible(graphics_context_, is_visible_);
-    if (controller_) {
-      if (is_visible_)
-        controller_->Resume();
-      else
-        controller_->Pause();
-    }
     OnVisibilityChanged(is_visible_);
   }
 }
diff --git a/services/vr/vr_window_manager/application.h b/services/vr/vr_window_manager/application.h
index 0c6385f..c7aa4dd 100644
--- a/services/vr/vr_window_manager/application.h
+++ b/services/vr/vr_window_manager/application.h
@@ -1,15 +1,13 @@
 #ifndef VR_WINDOW_MANAGER_APPLICATION_H_
 #define VR_WINDOW_MANAGER_APPLICATION_H_
 
-#include <jni.h>
 #include <memory>
 #include <private/dvr/types.h>
 #include <stdint.h>
-#include <vr/gvr/capi/include/gvr.h>
-#include <vr/gvr/capi/include/gvr_controller.h>
 
 #include <chrono>
 #include <mutex>
+#include <vector>
 
 #include "controller_data_provider.h"
 #include "elbow_model.h"
@@ -25,8 +23,7 @@
   Application();
   virtual ~Application();
 
-  virtual int Initialize(JNIEnv* env, jobject app_context,
-                         jobject class_loader);
+  virtual int Initialize();
 
   virtual int AllocateResources();
   virtual void DeallocateResources();
@@ -59,8 +56,6 @@
 
   void QueueTask(MainThreadTask task);
 
-  int InitializeController();
-
   DvrGraphicsContext* graphics_context_ = nullptr;
   DvrPose* pose_client_ = nullptr;
 
@@ -69,15 +64,8 @@
   FieldOfView fov_[2];
   Posef last_pose_;
 
-  std::unique_ptr<gvr::GvrApi> gvr_context_;
-  std::unique_ptr<gvr::ControllerApi> controller_;
-  std::unique_ptr<gvr::ControllerState> controller_state_;
-  gvr::ControllerApiStatus controller_api_status_;
-  gvr::ControllerConnectionState controller_connection_state_;
   quat controller_orientation_;
   bool shmem_controller_active_ = false;
-  bool controller_api_status_logged_;
-  bool controller_connection_state_logged_;
   uint64_t shmem_controller_buttons_;
 
   bool is_visible_ = false;
@@ -95,11 +83,6 @@
   bool initialized_ = false;
   std::vector<MainThreadTask> main_thread_tasks_;
 
-  // Java Resources.
-  JNIEnv* java_env_;
-  jobject app_context_;
-  jobject class_loader_;
-
   // Controller data provider from shared memory buffer.
   ControllerDataProvider* controller_data_provider_ = nullptr;
 
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp
index 5f8168d..1096a37 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_view.cpp
@@ -3,7 +3,9 @@
 namespace android {
 namespace dvr {
 
-VrComposerView::VrComposerView() : composer_view_(nullptr) {}
+VrComposerView::VrComposerView(
+    std::unique_ptr<VrComposerView::Callback> callback)
+    : composer_view_(nullptr), callback_(std::move(callback)) {}
 
 VrComposerView::~VrComposerView() {
   composer_view_->UnregisterObserver(this);
@@ -14,66 +16,19 @@
   composer_view_->RegisterObserver(this);
 }
 
-Return<void> VrComposerView::registerCallback(
-    const sp<IVrComposerCallback>& callback) {
-  callback_ = callback;
-  return Void();
-}
-
-Return<void> VrComposerView::releaseFrame() {
+void VrComposerView::ReleaseFrame() {
+  LOG_ALWAYS_FATAL_IF(!composer_view_, "VrComposerView not initialized");
   composer_view_->ReleaseFrame();
-  return Void();
 }
 
 void VrComposerView::OnNewFrame(const ComposerView::Frame& frame) {
+  std::lock_guard<std::mutex> guard(mutex_);
   if (!callback_.get()) {
-    releaseFrame();
+    ReleaseFrame();
     return;
   }
 
-  std::vector<IVrComposerCallback::Layer> layers;
-  std::vector<native_handle_t*> fences;
-  for (size_t i = 0; i < frame.size(); ++i) {
-    native_handle_t* fence;
-    if (frame[i].fence->isValid()) {
-      fence = native_handle_create(1, 0);
-      fence->data[0] = frame[i].fence->dup();
-    } else {
-      fence = native_handle_create(0, 0);
-    }
-    fences.push_back(fence);
-
-    layers.push_back(IVrComposerCallback::Layer{
-      .buffer = hidl_handle(frame[i].buffer->getNativeBuffer()->handle),
-      .fence = hidl_handle(fence),
-      .display_frame = frame[i].display_frame,
-      .crop = frame[i].crop,
-      .blend_mode= frame[i].blend_mode,
-      .alpha = frame[i].alpha,
-      .type = frame[i].type,
-      .app_id = frame[i].app_id,
-    });
-  }
-
-  auto status =
-      callback_->onNewFrame(hidl_vec<IVrComposerCallback::Layer>(layers));
-  if (!status.isOk()) {
-    ALOGE("Failed to send onNewFrame: %s", status.description().c_str());
-    releaseFrame();
-  }
-
-  for (size_t i = 0; i < fences.size(); ++i) {
-    native_handle_close(fences[i]);
-    native_handle_delete(fences[i]);
-  }
-}
-
-VrComposerView* GetVrComposerViewFromIVrComposerView(IVrComposerView* view) {
-  return static_cast<VrComposerView*>(view);
-}
-
-IVrComposerView* HIDL_FETCH_IVrComposerView(const char* name) {
-  return new VrComposerView();
+  callback_->OnNewFrame(frame);
 }
 
 }  // namespace dvr
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h b/services/vr/vr_window_manager/composer/impl/vr_composer_view.h
index 133bbc8..5a938e9 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_view.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_view.h
@@ -1,41 +1,37 @@
 #ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_
 #define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_VIEW_H_
 
-#include <android/dvr/composer/1.0/IVrComposerCallback.h>
-#include <android/dvr/composer/1.0/IVrComposerView.h>
+#include <memory>
 
 #include "vr_hwc.h"
 
 namespace android {
 namespace dvr {
 
-using composer::V1_0::IVrComposerView;
-using composer::V1_0::IVrComposerCallback;
-
-class VrComposerView : public IVrComposerView, public ComposerView::Observer {
+class VrComposerView : public ComposerView::Observer {
  public:
-  VrComposerView();
+  class Callback {
+   public:
+    virtual ~Callback() = default;
+    virtual void OnNewFrame(const ComposerView::Frame& frame) = 0;
+  };
+
+  VrComposerView(std::unique_ptr<Callback> callback);
   ~VrComposerView() override;
 
   void Initialize(ComposerView* composer_view);
 
-  // IVrComposerView
-  Return<void> registerCallback(const sp<IVrComposerCallback>& callback)
-      override;
-  Return<void> releaseFrame() override;
+  void ReleaseFrame();
 
   // ComposerView::Observer
   void OnNewFrame(const ComposerView::Frame& frame) override;
 
  private:
   ComposerView* composer_view_;
-  sp<IVrComposerCallback> callback_;
+  std::unique_ptr<Callback> callback_;
+  std::mutex mutex_;
 };
 
-VrComposerView* GetVrComposerViewFromIVrComposerView(IVrComposerView* view);
-
-IVrComposerView* HIDL_FETCH_IVrComposerView(const char* name);
-
 }  // namespace dvr
 }  // namespace android
 
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
index 12a76d8..b29d175 100644
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ b/services/vr/vr_window_manager/hwc_callback.cpp
@@ -12,11 +12,16 @@
 namespace {
 
 sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
+  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+  if (mapper.registerBuffer(handle) != OK) {
+    ALOGE("Failed to register buffer");
+    return nullptr;
+  }
+
   uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
   uint64_t producer_usage = 0, consumer_usage = 0;
   int32_t format = 0;
 
-  GraphicBufferMapper& mapper = GraphicBufferMapper::get();
   if (mapper.getDimensions(handle, &width, &height) ||
       mapper.getStride(handle, &stride) ||
       mapper.getFormat(handle, &format) ||
@@ -33,10 +38,6 @@
   sp<GraphicBuffer> buffer = new GraphicBuffer(
       width, height, format, layer_count, producer_usage, consumer_usage,
       stride, native_handle_clone(handle), true);
-  if (mapper.registerBuffer(buffer.get()) != OK) {
-    ALOGE("Failed to register buffer");
-    return nullptr;
-  }
 
   return buffer;
 }
@@ -62,27 +63,18 @@
 
 }  // namespace
 
-HwcCallback::HwcCallback(IVrComposerView* composer_view, Client* client)
-    : composer_view_(composer_view),
-      client_(client) {
-  composer_view_->registerCallback(this);
+HwcCallback::HwcCallback(Client* client) : client_(client) {
 }
 
 HwcCallback::~HwcCallback() {
-  composer_view_->registerCallback(nullptr);
 }
 
-Return<void> HwcCallback::onNewFrame(
-    const hidl_vec<IVrComposerCallback::Layer>& frame) {
-
+void HwcCallback::OnNewFrame(const ComposerView::Frame& frame) {
   std::vector<HwcLayer> hwc_frame(frame.size());
   for (size_t i = 0; i < frame.size(); ++i) {
-    int fence = frame[i].fence.getNativeHandle()->numFds ?
-        dup(frame[i].fence.getNativeHandle()->data[0]) : -1;
-
     hwc_frame[i] = HwcLayer{
-      .fence = new Fence(fence),
-      .buffer = GetBufferFromHandle(frame[i].buffer.getNativeHandle()),
+      .fence = frame[i].fence,
+      .buffer = frame[i].buffer,
       .crop = frame[i].crop,
       .display_frame = frame[i].display_frame,
       .blending = static_cast<int32_t>(frame[i].blend_mode),
@@ -92,10 +84,7 @@
     };
   }
 
-  std::lock_guard<std::mutex> guard(mutex_);
   client_->OnFrame(std::make_unique<Frame>(std::move(hwc_frame)));
-
-  return Void();
 }
 
 HwcCallback::Frame::Frame(std::vector<HwcLayer>&& layers)
diff --git a/services/vr/vr_window_manager/hwc_callback.h b/services/vr/vr_window_manager/hwc_callback.h
index 05a889b..d4d6e66 100644
--- a/services/vr/vr_window_manager/hwc_callback.h
+++ b/services/vr/vr_window_manager/hwc_callback.h
@@ -6,8 +6,7 @@
 #include <mutex>
 #include <vector>
 
-#include <android/dvr/composer/1.0/IVrComposerCallback.h>
-#include <android/dvr/composer/1.0/IVrComposerView.h>
+#include <impl/vr_composer_view.h>
 #include <impl/vr_hwc.h>
 
 namespace android {
@@ -20,10 +19,7 @@
 using Recti = ComposerView::ComposerLayer::Recti;
 using Rectf = ComposerView::ComposerLayer::Rectf;
 
-using composer::V1_0::IVrComposerCallback;
-using composer::V1_0::IVrComposerView;
-
-class HwcCallback : public IVrComposerCallback {
+class HwcCallback : public VrComposerView::Callback {
  public:
   struct HwcLayer {
     enum LayerType : uint32_t {
@@ -86,19 +82,12 @@
     virtual void OnFrame(std::unique_ptr<Frame>) = 0;
   };
 
-  explicit HwcCallback(IVrComposerView* composer_view, Client* client);
+  explicit HwcCallback(Client* client);
   ~HwcCallback() override;
 
  private:
-  // This is the only method called on the binder thread. Everything else is
-  // called on the render thread.
-  Return<void> onNewFrame(const hidl_vec<IVrComposerCallback::Layer>& frame)
-      override;
-
-  IVrComposerView* composer_view_;
+  void OnNewFrame(const ComposerView::Frame& frame) override;
   Client *client_;
-  std::mutex mutex_;
-
 
   HwcCallback(const HwcCallback&) = delete;
   void operator=(const HwcCallback&) = delete;
diff --git a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java b/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java
deleted file mode 100644
index 01d1bdb..0000000
--- a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/BootCompletedReceiver.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.google.vr.windowmanager;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-public class BootCompletedReceiver extends BroadcastReceiver {
-  private static final String TAG = BootCompletedReceiver.class.getSimpleName();
-
-  @Override
-  public void onReceive(Context context, Intent intent) {
-    Log.i(TAG, "Starting VRWindowManager");
-    Intent vrWindowManagerIntent = new Intent(context, VrWindowManagerService.class);
-    context.startService(vrWindowManagerIntent);
-  }
-}
diff --git a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java b/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java
deleted file mode 100644
index 1d815ca..0000000
--- a/services/vr/vr_window_manager/java/com/google/vr/windowmanager/VrWindowManagerService.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.google.vr.windowmanager;
-
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.Log;
-
-public class VrWindowManagerService extends Service {
-  private static final String TAG = VrWindowManagerService.class.getSimpleName();
-  private long nativeVrWindowManager;
-
-  // This is a temporary debugging tool for development only.
-  // It allows us to show VrWindowManager in debug mode via command line.
-  private final BroadcastReceiver debugReceiver = new BroadcastReceiver() {
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      String action = intent.getAction();
-      if (action.equals("com.google.vr.windowmanager.intent.SHOW")) {
-        nativeEnableDebug(nativeVrWindowManager);
-      } else if (action.equals("com.google.vr.windowmanager.intent.HIDE")) {
-        nativeDisableDebug(nativeVrWindowManager);
-      } else if (action.equals("com.google.vr.windowmanager.intent.ENTER_VR")) {
-        nativeEnterVrMode(nativeVrWindowManager);
-      } else if (action.equals("com.google.vr.windowmanager.intent.EXIT_VR")) {
-        nativeExitVrMode(nativeVrWindowManager);
-      }
-    }
-  };
-
-  static {
-    System.loadLibrary("vr_window_manager_jni");
-  }
-
-  @Override
-  public void onCreate() {
-    super.onCreate();
-    destroyRenderer();
-    nativeVrWindowManager = nativeCreate(getClass().getClassLoader(), getApplicationContext());
-    if (nativeVrWindowManager == 0) {
-      Log.e(TAG, "Failed to create native renderer");
-    }
-
-    // For development, testing and debugging.
-    IntentFilter filter = new IntentFilter();
-    filter.addAction("com.google.vr.windowmanager.intent.SHOW");
-    filter.addAction("com.google.vr.windowmanager.intent.HIDE");
-    filter.addAction("com.google.vr.windowmanager.intent.ENTER_VR");
-    filter.addAction("com.google.vr.windowmanager.intent.EXIT_VR");
-    registerReceiver(debugReceiver, filter);
-  }
-
-  @Override
-  public int onStartCommand(Intent intent, int flags, int startId) {
-    return START_STICKY;
-  }
-
-  @Override
-  public IBinder onBind(Intent intent) {
-    Log.i(TAG, "Ignoring bind request");
-    return null;
-  }
-
-  @Override
-  public void onDestroy() {
-    super.onDestroy();
-    unregisterReceiver(debugReceiver);
-    destroyRenderer();
-  }
-
-  private void destroyRenderer() {
-    if (nativeVrWindowManager != 0) {
-      nativeDestroy(nativeVrWindowManager);
-      nativeVrWindowManager = 0;
-    }
-  }
-
-  private native long nativeCreate(ClassLoader appClassLoader, Context context);
-  private native void nativeDestroy(long nativeVrWindowManager);
-  private native void nativeEnableDebug(long nativeVrWindowManager);
-  private native void nativeDisableDebug(long nativeVrWindowManager);
-  private native void nativeEnterVrMode(long nativeVrWindowManager);
-  private native void nativeExitVrMode(long nativeVrWindowManager);
-}
diff --git a/services/vr/vr_window_manager/render_thread.cpp b/services/vr/vr_window_manager/render_thread.cpp
deleted file mode 100644
index b67a051..0000000
--- a/services/vr/vr_window_manager/render_thread.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include <jni.h>
-#include <log/log.h>
-#include <future>
-
-#include "render_thread.h"
-#include "shell_view.h"
-
-namespace android {
-namespace dvr {
-
-RenderThread::RenderThread(JNIEnv* env, jobject class_loader,
-                           jobject android_context)
-    : jvm_(nullptr),
-      class_loader_global_ref_(0),
-      android_context_global_ref_(0),
-      quit_(false) {
-  env->GetJavaVM(&jvm_);
-
-  // Create global references so we can access these objects on the render
-  // thread
-  class_loader_global_ref_ = env->NewGlobalRef(class_loader);
-  android_context_global_ref_ = env->NewGlobalRef(android_context);
-
-  std::promise<int> render_thread_init_result_promise;
-  thread_ = std::thread([this, &render_thread_init_result_promise] {
-    JNIEnv* render_thread_jni_env = nullptr;
-    jvm_->AttachCurrentThread(&render_thread_jni_env, nullptr);
-    RunRenderLoop(&render_thread_init_result_promise);
-    jvm_->DetachCurrentThread();
-  });
-
-  // Wait to see if the render thread started successfully. If not bail.
-  int render_thread_init_result =
-      render_thread_init_result_promise.get_future().get();
-  LOG_ALWAYS_FATAL_IF(render_thread_init_result != 0,
-                      "Failed initializing render thread. result=%d",
-                      render_thread_init_result);
-}
-
-RenderThread::~RenderThread() { Quit(); }
-
-void RenderThread::Quit() {
-  if (thread_.joinable()) {
-    quit_ = true;
-    thread_.join();
-  }
-
-  JNIEnv* env = GetJniEnv();
-  if (class_loader_global_ref_ != 0) {
-    env->DeleteGlobalRef(class_loader_global_ref_);
-    class_loader_global_ref_ = 0;
-  }
-  if (android_context_global_ref_ != 0) {
-    env->DeleteGlobalRef(android_context_global_ref_);
-    android_context_global_ref_ = 0;
-  }
-}
-
-void RenderThread::EnableDebug(bool debug) { shell_view_.EnableDebug(debug); }
-
-void RenderThread::VrMode(bool mode) { shell_view_.VrMode(mode); }
-
-JNIEnv* RenderThread::GetJniEnv() {
-  JNIEnv* env;
-  jvm_->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
-  return env;
-}
-
-void RenderThread::RunRenderLoop(
-    std::promise<int>* init_result_promise) {
-  // TODO(steventhomas): Create local refs to work around b/33251144. Remove
-  // once that bug is fixed.
-  JNIEnv* env = GetJniEnv();
-  jobject class_loader = env->NewLocalRef(class_loader_global_ref_);
-  jobject android_context = env->NewLocalRef(android_context_global_ref_);
-
-  int init_result = shell_view_.Initialize(env, android_context, class_loader);
-  init_result_promise->set_value(init_result);
-  if (init_result == 0) {
-    while (!quit_)
-      shell_view_.DrawFrame();
-  } else {
-    ALOGE("Failed to initialize ShellView");
-  }
-
-  env->DeleteLocalRef(class_loader);
-  env->DeleteLocalRef(android_context);
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/vr_window_manager/render_thread.h b/services/vr/vr_window_manager/render_thread.h
deleted file mode 100644
index e193643..0000000
--- a/services/vr/vr_window_manager/render_thread.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef VR_WINDOW_MANAGER_RENDER_THREAD_H_
-#define VR_WINDOW_MANAGER_RENDER_THREAD_H_
-
-#include <atomic>
-#include <future>
-#include <jni.h>
-#include <thread>
-
-#include "shell_view.h"
-
-namespace android {
-namespace dvr {
-
-class RenderThread {
- public:
-  RenderThread(JNIEnv* env, jobject class_loader, jobject android_context);
-  ~RenderThread();
-  void Quit();
-  void EnableDebug(bool debug);
-  void VrMode(bool mode);
-
-  RenderThread(const RenderThread&) = delete;
-  void operator=(const RenderThread&) = delete;
-
- private:
-  // Called by both the main thread and render thread. Will return the correct
-  // JNIEnv for the current thread.
-  JNIEnv* GetJniEnv();
-
-  void RunRenderLoop(std::promise<int>* init_result_promise);
-
-  // Accessed only by the main thread.
-  std::thread thread_;
-
-  // The vars below are accessed by both the main thread and the render thread.
-  JavaVM* jvm_;
-  jobject class_loader_global_ref_;
-  jobject android_context_global_ref_;
-  std::atomic_bool quit_;
-
-  ShellView shell_view_;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // VR_WINDOW_MANAGER_RENDER_THREAD_H_
diff --git a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png b/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png
deleted file mode 100644
index 06f896d..0000000
--- a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon.png
+++ /dev/null
Binary files differ
diff --git a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png b/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png
deleted file mode 100644
index d336da3..0000000
--- a/services/vr/vr_window_manager/res/drawable-nodpi/vr_icon_background.png
+++ /dev/null
Binary files differ
diff --git a/services/vr/vr_window_manager/res/values/styles.xml b/services/vr/vr_window_manager/res/values/styles.xml
deleted file mode 100644
index 8a1a74b..0000000
--- a/services/vr/vr_window_manager/res/values/styles.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-<add-resource type="style" name="AppStyle"></add-resource>
-<style name="AppStyle"
-    parent="@android:style/Theme.Holo.NoActionBar.Fullscreen">
-  <item name="android:windowDisablePreview">true</item>
-</style>
-</resources>
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 29ade64..84b8467 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -238,9 +238,8 @@
 
 ShellView::~ShellView() {}
 
-int ShellView::Initialize(JNIEnv* env, jobject app_context,
-                          jobject class_loader) {
-  int ret = Application::Initialize(env, app_context, class_loader);
+int ShellView::Initialize() {
+  int ret = Application::Initialize();
   if (ret)
     return ret;
 
@@ -604,10 +603,7 @@
   vec3 pointer_location = last_pose_.GetPosition();
   quat view_quaternion = last_pose_.GetRotation();
 
-  bool gvr_api_active =
-      controller_ && controller_api_status_ == gvr::kControllerApiOk;
-
-  if (gvr_api_active || shmem_controller_active_) {
+  if (shmem_controller_active_) {
     view_quaternion = controller_orientation_;
     vec4 controller_location = controller_translate_ * vec4(0, 0, 0, 1);
     pointer_location = vec3(controller_location.x(), controller_location.y(),
@@ -635,18 +631,6 @@
         }
         buttons >>= 4;
       }
-    } else if (controller_) {
-      if (controller_state_->GetButtonDown(gvr::kControllerButtonClick))
-        OnClick(true);
-
-      if (controller_state_->GetButtonUp(gvr::kControllerButtonClick))
-        OnClick(false);
-
-      if (controller_state_->GetButtonDown(gvr::kControllerButtonApp))
-        OnTouchpadButton(true, AMOTION_EVENT_BUTTON_BACK);
-
-      if (controller_state_->GetButtonUp(gvr::kControllerButtonApp))
-        OnTouchpadButton(false, AMOTION_EVENT_BUTTON_BACK);
     }
   }
 
@@ -676,7 +660,7 @@
 
 void ShellView::DrawController(const mat4& perspective, const mat4& eye_matrix,
                                const mat4& head_matrix) {
-  if (!controller_ && !shmem_controller_active_)
+  if (!shmem_controller_active_)
     return;
 
   controller_program_->Use();
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index 14ad0f3..39b5451 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -28,8 +28,7 @@
   ShellView();
   virtual ~ShellView();
 
-  int Initialize(JNIEnv* env, jobject app_context,
-                 jobject class_loader) override;
+  int Initialize() override;
 
   int AllocateResources() override;
   void DeallocateResources() override;
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index b15d262..d42d3ff 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -1,6 +1,5 @@
 #include "surface_flinger_view.h"
 
-#include <binder/IServiceManager.h>
 #include <impl/vr_composer_view.h>
 #include <private/dvr/native_buffer.h>
 
@@ -15,23 +14,33 @@
 SurfaceFlingerView::~SurfaceFlingerView() {}
 
 bool SurfaceFlingerView::Initialize(HwcCallback::Client *client) {
-  const char instance[] = "DaydreamDisplay";
-  composer_service_ = IVrComposerView::getService(instance);
-  if (composer_service_ == nullptr) {
-    ALOGE("Failed to initialize composer service");
+  const char vr_hwcomposer_name[] = "vr_hwcomposer";
+  vr_hwcomposer_ = HIDL_FETCH_IComposer(vr_hwcomposer_name);
+  if (!vr_hwcomposer_.get()) {
+    ALOGE("Failed to get vr_hwcomposer");
     return false;
   }
 
-  if (!composer_service_->isRemote()) {
-    ALOGE("Composer service is not remote");
+  if (vr_hwcomposer_->isRemote()) {
+    ALOGE("vr_hwcomposer service is remote");
     return false;
   }
 
+  const android::status_t vr_hwcomposer_status =
+      vr_hwcomposer_->registerAsService(vr_hwcomposer_name);
+  if (vr_hwcomposer_status != OK) {
+    ALOGE("Failed to register vr_hwcomposer service");
+    return false;
+  }
+
+  vr_composer_view_ =
+      std::make_unique<VrComposerView>(std::make_unique<HwcCallback>(client));
+  vr_composer_view_->Initialize(GetComposerViewFromIComposer(
+      vr_hwcomposer_.get()));
+
   // TODO(dnicoara): Query this from the composer service.
   width_ = 1920;
   height_ = 1080;
-
-  composer_observer_.reset(new HwcCallback(composer_service_.get(), client));
   return true;
 }
 
@@ -76,7 +85,7 @@
 }
 
 void SurfaceFlingerView::ReleaseFrame() {
-  composer_service_->releaseFrame();
+  vr_composer_view_->ReleaseFrame();
 }
 
 }  // namespace dvr
diff --git a/services/vr/vr_window_manager/surface_flinger_view.h b/services/vr/vr_window_manager/surface_flinger_view.h
index 2e36ec1..9c16192 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.h
+++ b/services/vr/vr_window_manager/surface_flinger_view.h
@@ -1,10 +1,10 @@
 #ifndef APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_
 #define APPLICATIONS_EXPERIMENTS_SURFACE_FLINGER_DEMO_SURFACE_FLINGER_VIEW_H_
 
-#include <utils/StrongPointer.h>
-
 #include <memory>
 
+#include <impl/vr_composer_view.h>
+
 #include "hwc_callback.h"
 
 namespace android {
@@ -39,9 +39,8 @@
   void ReleaseFrame();
 
  private:
-  sp<IVrComposerView> composer_service_;
-  std::unique_ptr<HwcCallback> composer_observer_;
-
+  sp<IComposer> vr_hwcomposer_;
+  std::unique_ptr<VrComposerView> vr_composer_view_;
   int width_ = 0;
   int height_ = 0;
 
diff --git a/services/vr/vr_window_manager/vr_window_manager.cpp b/services/vr/vr_window_manager/vr_window_manager.cpp
index c51ddee..6636dc5 100644
--- a/services/vr/vr_window_manager/vr_window_manager.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager.cpp
@@ -1,33 +1,48 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <hwbinder/IPCThreadState.h>
+#include <impl/vr_composer_view.h>
+#include <impl/vr_hwc.h>
 
 #include "shell_view.h"
 #include "vr_window_manager_binder.h"
 
+using namespace android;
+using namespace android::dvr;
+
 int main(int /* argc */, char** /* argv */) {
-  android::dvr::ShellView app;
-  const int app_status = app.Initialize(nullptr, nullptr, nullptr);
-  LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status);
-
-  android::service::vr::VrWindowManagerBinder service(app);
-  const int status = service.Initialize();
-  LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
-
   android::ProcessState::self()->startThreadPool();
 
+  // ShellView needs to be created after vr_hwcomposer.
+  android::dvr::ShellView app;
+  const int app_status = app.Initialize();
+  LOG_ALWAYS_FATAL_IF(app_status != 0, "failed to initialize: %d", app_status);
+
+  // Create vr_wm_binder.
+  android::service::vr::VrWindowManagerBinder vr_wm_binder(app);
+  const int status = vr_wm_binder.Initialize();
+  LOG_ALWAYS_FATAL_IF(status != 0, "initialization failed: %d", status);
+
   android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-  const android::status_t service_status = sm->addService(
-      android::service::vr::VrWindowManagerBinder::SERVICE_NAME(), &service,
-      false /*allowIsolated*/);
-  LOG_ALWAYS_FATAL_IF(service_status != android::OK, "service not added: %d",
-                      static_cast<int>(service_status));
+  const android::status_t vr_wm_binder_status =
+      sm->addService(
+          android::service::vr::VrWindowManagerBinder::SERVICE_NAME(),
+          &vr_wm_binder, false /*allowIsolated*/);
+  LOG_ALWAYS_FATAL_IF(vr_wm_binder_status != android::OK,
+                      "vr_wm_binder service not added: %d",
+                      static_cast<int>(vr_wm_binder_status));
 
-  app.SetControllerDataProvider(&service);
+  app.SetControllerDataProvider(&vr_wm_binder);
 
-  while (true)
+  android::hardware::ProcessState::self()->startThreadPool();
+
+  while (true) {
     app.DrawFrame();
+  }
 
+  android::hardware::IPCThreadState::self()->joinThreadPool();
   android::IPCThreadState::self()->joinThreadPool();
+
   return 0;
 }
diff --git a/services/vr/vr_window_manager/vr_window_manager_jni.cpp b/services/vr/vr_window_manager/vr_window_manager_jni.cpp
deleted file mode 100644
index 49eaba1..0000000
--- a/services/vr/vr_window_manager/vr_window_manager_jni.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <jni.h>
-#include <log/log.h>
-
-#include <memory>
-
-#include "render_thread.h"
-
-#define JNI_METHOD(return_type, method_name) \
-  JNIEXPORT return_type JNICALL              \
-      Java_com_google_vr_windowmanager_VrWindowManagerService_##method_name
-
-namespace {
-
-inline jlong jptr(android::dvr::RenderThread* native_vr_window_manager) {
-  return reinterpret_cast<intptr_t>(native_vr_window_manager);
-}
-
-inline android::dvr::RenderThread* native(jlong ptr) {
-  return reinterpret_cast<android::dvr::RenderThread*>(ptr);
-}
-
-}  // namespace
-
-extern "C" {
-
-JNI_METHOD(jlong, nativeCreate)(JNIEnv* env, jclass /*clazz*/,
-                                jobject class_loader,
-                                jobject android_context) {
-  return jptr(new android::dvr::RenderThread(
-      env, class_loader, android_context));
-}
-
-JNI_METHOD(void, nativeDestroy)
-(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) {
-  delete native(native_render_thread);
-}
-
-JNI_METHOD(void, nativeEnableDebug)
-(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) {
-  native(native_render_thread)->EnableDebug(true);
-}
-
-JNI_METHOD(void, nativeDisableDebug)
-(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) {
-  native(native_render_thread)->EnableDebug(false);
-}
-
-JNI_METHOD(void, nativeEnterVrMode)
-(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) {
-  native(native_render_thread)->VrMode(true);
-}
-
-JNI_METHOD(void, nativeExitVrMode)
-(JNIEnv* /*env*/, jclass /*clazz*/, jlong native_render_thread) {
-  native(native_render_thread)->VrMode(false);
-}
-
-}  // extern "C"
diff --git a/services/vr/vr_window_manager/vr_wm.rc b/services/vr/vr_window_manager/vr_wm.rc
index 143b916..951515b 100644
--- a/services/vr/vr_window_manager/vr_wm.rc
+++ b/services/vr/vr_window_manager/vr_wm.rc
@@ -3,7 +3,3 @@
   user system
   group system graphics input
   cpuset /system
-  disabled
-
-on property:persist.daydream.vr_wm=1
-  enable vr_wm
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 5a67d36..eed44ad 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -153,6 +153,8 @@
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
 @extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
 
+@extension("VK_EXT_HDR_METADATA_SPEC_VERSION") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
+@extension("VK_EXT_HDR_METADATA_EXTENSION_NAME") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
 
 
 /////////////
@@ -2908,14 +2910,20 @@
     platform.HWND                               hwnd
 }
 
+@internal class Gralloc1Usage {
+    u64                                         consumer
+    u64                                         producer
+}
+
 @extension("VK_ANDROID_native_buffer")
 class VkNativeBufferANDROID {
     VkStructureType                             sType
     const void*                                 pNext
     platform.buffer_handle_t                    handle
-    int                                         stride
-    int                                         format
-    int                                         usage
+    s32                                         stride
+    s32                                         format
+    s32                                         usage
+    Gralloc1Usage                               usage2
 }
 
 @extension("VK_ANDROID_native_buffer")
@@ -3297,6 +3305,24 @@
     VkShaderStageFlags                          stageFlags
 }
 
+@extension("VK_EXT_hdr_metadata")
+class VkXYColorEXT {
+    f32    x
+    f32    y
+}
+
+@extension("VK_EXT_hdr_metadata")
+class VkHdrMetadataEXT {
+    VkXYColorEXT    displayPrimaryRed
+    VkXYColorEXT    displayPrimaryGreen
+    VkXYColorEXT    displayPrimaryBlue
+    VkXYColorEXT    whitePoint
+    f32             maxLuminance
+    f32             minLuminance
+    f32             maxContentLightLevel
+    f32             maxFrameAverageLightLevel
+}
+
 
 
 ////////////////
@@ -5833,21 +5859,24 @@
 }
 
 @extension("VK_ANDROID_native_buffer")
+@optional
 cmd VkResult vkGetSwapchainGrallocUsageANDROID(
         VkDevice                                device,
         VkFormat                                format,
         VkImageUsageFlags                       imageUsage,
-        int*                                    grallocUsage) {
+        s32*                                    grallocUsage) {
     return ?
 }
 
 @extension("VK_ANDROID_native_buffer")
+@optional
 cmd VkResult vkGetSwapchainGrallocUsage2ANDROID(
         VkDevice                                device,
         VkFormat                                format,
         VkImageUsageFlags                       imageUsage,
         VkSwapchainImageUsageFlagsANDROID       swapchainImageUsage,
-        int*                                    grallocUsage) {
+        u64*                                    grallocConsumerUsage,
+        u64*                                    grallocProducerUsage) {
     return ?
 }
 
@@ -6138,6 +6167,14 @@
     return ?
 }
 
+@extension("VK_EXT_hdr_metadata")
+cmd void  vkSetHdrMetadataEXT(
+    VkDevice                                        device,
+    u32                                             swapchainCount,
+    const VkSwapchainKHR*                           pSwapchains,
+    const VkHdrMetadataEXT*                         pMetadata) {
+}
+
 
 ////////////////
 // Validation //
diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
index 009472a..24af950 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.adoc
+++ b/vulkan/doc/implementors_guide/implementors_guide.adoc
@@ -47,19 +47,7 @@
 
 The +vk_wsi_swapchin+ and +vk_wsi_device_swapchain+ extensions are primarily be implemented by the platform and live in +libvulkan.so+. The +VkSwapchain+ object and all interaction with +ANativeWindow+ will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver's +vkGetDeviceProcAddr+ functions, after passing through any enabled layers.
 
-Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling
-[source,c]
-----
-VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
-    VkDevice            device,
-    VkFormat            format,
-    VkImageUsageFlags   imageUsage,
-    int*                grallocUsage
-);
-----
-The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
-
-Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The additional usage bits are defined as
+Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The swapchain usage bits are defined as
 [source,c]
 ----
 typedef enum VkSwapchainImageUsageFlagBitsANDROID {
@@ -69,7 +57,7 @@
 typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
 ----
 
-If the driver provides the +vkGetSwapchainGrallocUsage2ANDROID+ function, the platform will use it in preference to +vkGetSwapchainGrallocUsageANDROID+ when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. +vkGetSwapchainGrallocUsage2ANDROID+ behaves in the same way as +vkGetSwapchainGrallocUsageANDROID+, and is declared as
+Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling
 [source,c]
 ----
 VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
@@ -77,6 +65,19 @@
     VkFormat            format,
     VkImageUsageFlags   imageUsage,
     VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+    uint64_t*           grallocConsumerUsage,
+    uint64_t*           grallocProducerUsage,
+);
+----
+The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocConsumerUsage+ and +*grallocProducerUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
+
+An older version of this function is deprecated but still supported for backwards compatibility; it will be used if +vkGetSwapchainGrallocUsage2ANDROID+ is not supported:
+[source,c]
+----
+VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
     int*                grallocUsage
 );
 ----
@@ -95,7 +96,11 @@
 
     // Gralloc format and usage requested when the buffer was allocated.
     int                         format;
-    int                         usage;
+    int                         usage; // deprecated
+    struct {
+        uint64_t                consumer;
+        uint64_t                producer;
+    } usage2;
 } VkNativeBufferANDROID;
 ----
 
@@ -200,3 +205,5 @@
    * Added VkSwapchainImageUsageFlagBitsANDROID
    * Added vkGetSwapchainGrallocUsage2ANDROID
    * Added VkSwapchainImageCreateInfoANDROID
+. *2017-02-09*
+   * Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields.
\ No newline at end of file
diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
index 4e74a78..9fecce5 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.html
+++ b/vulkan/doc/implementors_guide/implementors_guide.html
@@ -730,7 +730,7 @@
 /*]]>*/
 </script>
 </head>
-<body class="article">
+<body class="book">
 <div id="header">
 <h1>Vulkan on Android Implementor&#8217;s Guide</h1>
 <span id="revnumber">version 5</span>
@@ -793,20 +793,7 @@
 <h2 id="_window_system_integration">2. Window System Integration</h2>
 <div class="sectionbody">
 <div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions are primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver&#8217;s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
-<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.6
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
-    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
-    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
-    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
-    <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
-<span style="color: #990000">);</span></tt></pre></div></div>
-<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
-<div class="paragraph"><p>Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The additional usage bits are defined as</p></div>
+<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The swapchain usage bits are defined as</p></div>
 <div class="listingblock">
 <div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
@@ -817,7 +804,7 @@
     VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM <span style="color: #990000">=</span> <span style="color: #993399">0x7FFFFFFF</span>
 <span style="color: #FF0000">}</span> VkSwapchainImageUsageFlagBitsANDROID<span style="color: #990000">;</span>
 <span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="color: #008080">VkFlags</span> VkSwapchainImageUsageFlagsANDROID<span style="color: #990000">;</span></tt></pre></div></div>
-<div class="paragraph"><p>If the driver provides the <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> function, the platform will use it in preference to <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span> when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> behaves in the same way as <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span>, and is declared as</p></div>
+<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
 <div class="listingblock">
 <div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
@@ -828,6 +815,20 @@
     <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
     <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
     <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> swapchainImageUsage<span style="color: #990000">,</span>
+    uint64_t<span style="color: #990000">*</span>           grallocConsumerUsage<span style="color: #990000">,</span>
+    uint64_t<span style="color: #990000">*</span>           grallocProducerUsage<span style="color: #990000">,</span>
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocConsumerUsage</span> and <span class="monospaced">*grallocProducerUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
+<div class="paragraph"><p>An older version of this function is deprecated but still supported for backwards compatibility; it will be used if <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> is not supported:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
+    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
     <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
 <span style="color: #990000">);</span></tt></pre></div></div>
 <div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
@@ -846,7 +847,11 @@
 
     <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span>
     <span style="color: #009900">int</span>                         format<span style="color: #990000">;</span>
-    <span style="color: #009900">int</span>                         usage<span style="color: #990000">;</span>
+    <span style="color: #009900">int</span>                         usage<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// deprecated</span></span>
+    <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
+        <span style="color: #008080">uint64_t</span>                consumer<span style="color: #990000">;</span>
+        <span style="color: #008080">uint64_t</span>                producer<span style="color: #990000">;</span>
+    <span style="color: #FF0000">}</span> usage2<span style="color: #990000">;</span>
 <span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
 <div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
 <div class="listingblock">
@@ -1044,6 +1049,18 @@
 </li>
 </ul></div>
 </li>
+<li>
+<p>
+<strong>2017-02-09</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Extended vkGetSwapchainGrallocUsage2ANDROID and VkNativeBufferANDROID to use gralloc1-style usage bitfields.
+</p>
+</li>
+</ul></div>
+</li>
 </ol></div>
 </div>
 </div>
@@ -1052,7 +1069,7 @@
 <div id="footer">
 <div id="footer-text">
 Version 5<br>
-Last updated 2017-01-12 14:25:30 NZDT
+Last updated 2017-02-09 22:40:30 PST
 </div>
 </div>
 </body>
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index db23e79..d7c5a07 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -27,6 +27,16 @@
 #define VK_ANDROID_native_buffer 1
 
 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11
+/* NOTE ON VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6
+ *
+ * This version of the extension transitions from gralloc0 to gralloc1 usage
+ * flags (int -> 2x uint64_t). The WSI implementation will temporarily continue
+ * to fill out deprecated fields in VkNativeBufferANDROID, and will call the
+ * deprecated vkGetSwapchainGrallocUsageANDROID if the new
+ * vkGetSwapchainGrallocUsage2ANDROID is not supported. This transitionary
+ * backwards-compatibility support is temporary, and will likely be removed in
+ * (along with all gralloc0 support) in a future release.
+ */
 #define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     6
 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME   "VK_ANDROID_native_buffer"
 
@@ -50,7 +60,12 @@
 
     // Gralloc format and usage requested when the buffer was allocated.
     int                         format;
-    int                         usage;
+    int                         usage; // DEPRECATED in SPEC_VERSION 6
+    // -- Added in SPEC_VERSION 6 --
+    struct {
+        uint64_t                consumer;
+        uint64_t                producer;
+    } usage2;
 } VkNativeBufferANDROID;
 
 typedef struct {
@@ -60,24 +75,30 @@
     VkSwapchainImageUsageFlagsANDROID      usage;
 } VkSwapchainImageCreateInfoANDROID;
 
+// -- DEPRECATED in SPEC_VERSION 6 --
 typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, int* grallocUsage);
+// -- ADDED in SPEC_VERSION 6 --
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 
 #ifndef VK_NO_PROTOTYPES
+
+// -- DEPRECATED in SPEC_VERSION 6 --
 VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageANDROID(
     VkDevice            device,
     VkFormat            format,
     VkImageUsageFlags   imageUsage,
     int*                grallocUsage
 );
+// -- ADDED in SPEC_VERSION 6 --
 VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
     VkDevice            device,
     VkFormat            format,
     VkImageUsageFlags   imageUsage,
     VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
-    int*                grallocUsage
+    uint64_t*           grallocConsumerUsage,
+    uint64_t*           grallocProducerUsage
 );
 VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(
     VkDevice            device,
@@ -93,17 +114,6 @@
     VkImage             image,
     int*                pNativeFenceFd
 );
-// -- DEPRECATED --
-VKAPI_ATTR VkResult VKAPI_CALL vkImportNativeFenceANDROID(
-    VkDevice            device,
-    VkSemaphore         semaphore,
-    int                 nativeFenceFd
-);
-VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalNativeFenceANDROID(
-    VkQueue             queue,
-    int*                pNativeFenceFd
-);
-// ----------------
 #endif
 
 #ifdef __cplusplus
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 8d24aa7..16f43e5 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2015-2016 The Khronos Group Inc.
+** Copyright (c) 2015-2017 The Khronos Group Inc.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -4608,6 +4608,39 @@
     VkDeviceGeneratedCommandsLimitsNVX*         pLimits);
 #endif
 
+#define VK_EXT_hdr_metadata 1
+#define VK_EXT_HDR_METADATA_SPEC_VERSION  0
+#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
+
+typedef struct VkXYColorEXT {
+    float    x;
+    float    y;
+} VkXYColorEXT;
+
+typedef struct VkHdrMetadataEXT {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkXYColorEXT       displayPrimaryRed;
+    VkXYColorEXT       displayPrimaryGreen;
+    VkXYColorEXT       displayPrimaryBlue;
+    VkXYColorEXT       whitePoint;
+    float              maxLuminance;
+    float              minLuminance;
+    float              maxContentLightLevel;
+    float              maxFrameAverageLightLevel;
+} VkHdrMetadataEXT;
+
+
+typedef void (VKAPI_PTR *PFN_vkSetHdrMetadataEXT)(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkSetHdrMetadataEXT(
+    VkDevice                                    device,
+    uint32_t                                    swapchainCount,
+    const VkSwapchainKHR*                       pSwapchains,
+    const VkHdrMetadataEXT*                     pMetadata);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 501877c..caf38bc 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -413,13 +413,14 @@
   {{AssertType $ "Function"}}
 
   {{$ext := GetAnnotation $ "extension"}}
-  {{$required := (Macro "IsRequiredFunction" $)}}
   {{if $ext}}
-    INIT_PROC_EXT({{Macro "BaseName" $ext}}, {{$required}}, §
+    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
   {{else}}
-    INIT_PROC({{$required}}, §
+    INIT_PROC(§
   {{end}}
 
+  {{if GetAnnotation $ "optional"}}false{{else}}true{{end}}, §
+
   {{if (Macro "IsInstanceDispatched" $)}}
     instance, §
   {{else}}
@@ -432,25 +433,6 @@
 
 {{/*
 ------------------------------------------------------------------------------
-  Emits true if a function /must/ be resolved. The only time this is not
-  the case is for extension-added functions added in a later revision of the
-  extension, and where we have to cope with drivers written against an older
-  revision.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsRequiredFunction"}}
-  {{AssertType $ "Function"}}
-
-  {{if eq $.Name "vkGetSwapchainGrallocUsage2ANDROID"}}
-    false
-  {{else}}
-    true
-  {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
   Emits true if a function is exported and instance-dispatched.
 ------------------------------------------------------------------------------
 */}}
@@ -700,11 +682,12 @@
 {{define "driver.InterceptedExtensions"}}
 VK_ANDROID_native_buffer
 VK_EXT_debug_report
+VK_EXT_hdr_metadata
+VK_GOOGLE_display_timing
 VK_KHR_android_surface
 VK_KHR_incremental_present
 VK_KHR_surface
 VK_KHR_swapchain
-VK_GOOGLE_display_timing
 VK_KHR_shared_presentable_image
 {{end}}
 
@@ -981,6 +964,8 @@
     {{else if eq $.Name "vkCreateImage"}}true
     {{else if eq $.Name "vkDestroyImage"}}true
 
+    {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
+
     {{end}}
 
     {{$ext := GetAnnotation $ "extension"}}
@@ -1143,8 +1128,9 @@
 
 {{/*
 ------------------------------------------------------------------------------
-  Reports whether an extension is implemented entirely by the loader,
-  so drivers should not enumerate it.
+  Reports whether an extension has functions exported by the loader.
+  E.g. applications can directly link to an extension function.
+  Currently only support WSI extensions this way.
 ------------------------------------------------------------------------------
 */}}
 {{define "IsExtensionExported"}}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 991c3ed..71bfecf 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -472,6 +472,9 @@
                 hook_extensions_.set(ext_bit);
                 // return now as these extensions do not require HAL support
                 return;
+            case ProcHook::EXT_hdr_metadata:
+                hook_extensions_.set(ext_bit);
+                break;
             case ProcHook::EXTENSION_UNKNOWN:
                 // HAL's extensions
                 break;
@@ -737,12 +740,14 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
     const InstanceData& data = GetData(physicalDevice);
-    static const std::array<VkExtensionProperties, 2> loader_extensions = {{
+    static const std::array<VkExtensionProperties, 3> loader_extensions = {{
         // WSI extensions
         {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
          VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
         {VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
          VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION},
+        {VK_EXT_HDR_METADATA_EXTENSION_NAME,
+         VK_EXT_HDR_METADATA_SPEC_VERSION},
     }};
 
     // enumerate our extensions first
@@ -899,7 +904,29 @@
 
         return VK_ERROR_INCOMPATIBLE_DRIVER;
     }
+
+    // sanity check ANDROID_native_buffer implementation, whose set of
+    // entrypoints varies according to the spec version.
+    if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
+        !data->driver.GetSwapchainGrallocUsageANDROID &&
+        !data->driver.GetSwapchainGrallocUsage2ANDROID) {
+        ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
+              " must expose at least one of "
+              "vkGetSwapchainGrallocUsageANDROID or "
+              "vkGetSwapchainGrallocUsage2ANDROID");
+
+        data->driver.DestroyDevice(dev, pAllocator);
+        FreeDeviceData(data, data_allocator);
+
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+    VkPhysicalDeviceProperties properties;
+    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+                                                     &properties);
+
     data->driver_device = dev;
+    data->driver_version = properties.driverVersion;
 
     *pDevice = dev;
 
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index e058439..5383f59 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -102,6 +102,7 @@
 
     VkDevice driver_device;
     DeviceDriverTable driver;
+    uint32_t driver_version;
 };
 
 bool Debuggable();
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 689a228..59964fb 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -102,6 +102,14 @@
     }
 }
 
+VKAPI_ATTR void checkedSetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pMetadata) {
+    if (GetData(device).hook_extensions[ProcHook::EXT_hdr_metadata]) {
+        SetHdrMetadataEXT(device, swapchainCount, pSwapchains, pMetadata);
+    } else {
+        Logger(device).Err(device, "VK_EXT_hdr_metadata not enabled. vkSetHdrMetadataEXT not executed.");
+    }
+}
+
 // clang-format on
 
 const ProcHook g_proc_hooks[] = {
@@ -330,6 +338,13 @@
         nullptr,
         nullptr,
     },
+    {
+        "vkSetHdrMetadataEXT",
+        ProcHook::DEVICE,
+        ProcHook::EXT_hdr_metadata,
+        reinterpret_cast<PFN_vkVoidFunction>(SetHdrMetadataEXT),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedSetHdrMetadataEXT),
+    },
     // clang-format on
 };
 
@@ -349,11 +364,12 @@
     // clang-format off
     if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer;
     if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report;
+    if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata;
+    if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
     if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
     if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
     if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
     if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
-    if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
     if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
     // clang-format on
     return ProcHook::EXTENSION_UNKNOWN;
@@ -387,6 +403,7 @@
     INIT_PROC(true, instance, DestroyInstance);
     INIT_PROC(true, instance, EnumeratePhysicalDevices);
     INIT_PROC(true, instance, GetInstanceProcAddr);
+    INIT_PROC(true, instance, GetPhysicalDeviceProperties);
     INIT_PROC(true, instance, CreateDevice);
     INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
     INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
@@ -410,7 +427,7 @@
     INIT_PROC(true, dev, CreateImage);
     INIT_PROC(true, dev, DestroyImage);
     INIT_PROC(true, dev, AllocateCommandBuffers);
-    INIT_PROC_EXT(ANDROID_native_buffer, true, dev, GetSwapchainGrallocUsageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsageANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID);
     INIT_PROC_EXT(ANDROID_native_buffer, true, dev, QueueSignalReleaseImageANDROID);
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 9f3b705..273e796 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -35,11 +35,12 @@
     enum Extension {
         ANDROID_native_buffer,
         EXT_debug_report,
+        EXT_hdr_metadata,
+        GOOGLE_display_timing,
         KHR_android_surface,
         KHR_incremental_present,
         KHR_surface,
         KHR_swapchain,
-        GOOGLE_display_timing,
         KHR_shared_presentable_image,
 
         EXTENSION_CORE,  // valid bit
@@ -60,6 +61,7 @@
     PFN_vkDestroyInstance DestroyInstance;
     PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
     PFN_vkCreateDevice CreateDevice;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index f4ee375..b1e3d61 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -20,7 +20,7 @@
 #include <gui/BufferQueue.h>
 #include <sync/sync.h>
 #include <utils/StrongPointer.h>
-#include <utils/SortedVector.h>
+#include <utils/Vector.h>
 
 #include "driver.h"
 
@@ -108,19 +108,11 @@
 
 class TimingInfo {
    public:
-    TimingInfo()
-        : vals_{0, 0, 0, 0, 0},
-          timestamp_desired_present_time_(0),
-          timestamp_actual_present_time_(0),
-          timestamp_render_complete_time_(0),
-          timestamp_composition_latch_time_(0) {}
-    TimingInfo(const VkPresentTimeGOOGLE* qp)
+    TimingInfo() = default;
+    TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
         : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
-          timestamp_desired_present_time_(0),
-          timestamp_actual_present_time_(0),
-          timestamp_render_complete_time_(0),
-          timestamp_composition_latch_time_(0) {}
-    bool ready() {
+          native_frame_id_(nativeFrameId) {}
+    bool ready() const {
         return (timestamp_desired_present_time_ &&
                 timestamp_actual_present_time_ &&
                 timestamp_render_complete_time_ &&
@@ -148,27 +140,20 @@
         vals_.earliestPresentTime = early_time;
         vals_.presentMargin = margin;
     }
-    void get_values(VkPastPresentationTimingGOOGLE* values) { *values = vals_; }
+    void get_values(VkPastPresentationTimingGOOGLE* values) const {
+        *values = vals_;
+    }
 
    public:
-    VkPastPresentationTimingGOOGLE vals_;
+    VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
 
-    uint64_t timestamp_desired_present_time_;
-    uint64_t timestamp_actual_present_time_;
-    uint64_t timestamp_render_complete_time_;
-    uint64_t timestamp_composition_latch_time_;
+    uint64_t native_frame_id_ { 0 };
+    uint64_t timestamp_desired_present_time_ { 0 };
+    uint64_t timestamp_actual_present_time_ { 0 };
+    uint64_t timestamp_render_complete_time_ { 0 };
+    uint64_t timestamp_composition_latch_time_ { 0 };
 };
 
-static inline int compare_type(const TimingInfo& lhs, const TimingInfo& rhs) {
-    // TODO(ianelliott): Change this from presentID to the frame ID once
-    // brianderson lands the appropriate patch:
-    if (lhs.vals_.presentID < rhs.vals_.presentID)
-        return -1;
-    if (lhs.vals_.presentID > rhs.vals_.presentID)
-        return 1;
-    return 0;
-}
-
 // ----------------------------------------------------------------------------
 
 struct Surface {
@@ -191,11 +176,13 @@
 enum { MIN_NUM_FRAMES_AGO = 5 };
 
 struct Swapchain {
-    Swapchain(Surface& surface_, uint32_t num_images_)
+    Swapchain(Surface& surface_,
+              uint32_t num_images_,
+              VkPresentModeKHR present_mode)
         : surface(surface_),
           num_images(num_images_),
+          mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
           frame_timestamps_enabled(false) {
-        timing.clear();
         ANativeWindow* window = surface.window.get();
         int64_t rdur;
         native_window_get_refresh_cycle_duration(
@@ -206,6 +193,7 @@
 
     Surface& surface;
     uint32_t num_images;
+    bool mailbox_mode;
     bool frame_timestamps_enabled;
     uint64_t refresh_duration;
 
@@ -221,7 +209,7 @@
         bool dequeued;
     } images[android::BufferQueue::NUM_BUFFER_SLOTS];
 
-    android::SortedVector<TimingInfo> timing;
+    android::Vector<TimingInfo> timing;
 };
 
 VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
@@ -293,73 +281,64 @@
 }
 
 uint32_t get_num_ready_timings(Swapchain& swapchain) {
-    uint32_t num_ready = 0;
-    uint32_t num_timings = static_cast<uint32_t>(swapchain.timing.size());
-    uint32_t frames_ago = num_timings;
-    for (uint32_t i = 0; i < num_timings; i++) {
-        TimingInfo* ti = &swapchain.timing.editItemAt(i);
-        if (ti) {
-            if (ti->ready()) {
-                // This TimingInfo is ready to be reported to the user.  Add it
-                // to the num_ready.
-                num_ready++;
-            } else {
-                // This TimingInfo is not yet ready to be reported to the user,
-                // and so we should look for any available timestamps that
-                // might make it ready.
-                int64_t desired_present_time = 0;
-                int64_t render_complete_time = 0;
-                int64_t composition_latch_time = 0;
-                int64_t actual_present_time = 0;
-                for (uint32_t f = MIN_NUM_FRAMES_AGO; f < frames_ago; f++) {
-                    // Obtain timestamps:
-                    int ret = native_window_get_frame_timestamps(
-                        swapchain.surface.window.get(), f,
-                        &desired_present_time, &render_complete_time,
-                        &composition_latch_time,
-                        NULL,  //&first_composition_start_time,
-                        NULL,  //&last_composition_start_time,
-                        NULL,  //&composition_finish_time,
-                        // TODO(ianelliott): Maybe ask if this one is
-                        // supported, at startup time (since it may not be
-                        // supported):
-                        &actual_present_time,
-                        NULL,  //&display_retire_time,
-                        NULL,  //&dequeue_ready_time,
-                        NULL /*&reads_done_time*/);
-                    if (ret) {
-                        break;
-                    } else if (!ret) {
-                        // We obtained at least one valid timestamp.  See if it
-                        // is for the present represented by this TimingInfo:
-                        if (static_cast<uint64_t>(desired_present_time) ==
-                            ti->vals_.desiredPresentTime) {
-                            // Record the timestamp(s) we received, and then
-                            // see if this TimingInfo is ready to be reported
-                            // to the user:
-                            ti->timestamp_desired_present_time_ =
-                                static_cast<uint64_t>(desired_present_time);
-                            ti->timestamp_actual_present_time_ =
-                                static_cast<uint64_t>(actual_present_time);
-                            ti->timestamp_render_complete_time_ =
-                                static_cast<uint64_t>(render_complete_time);
-                            ti->timestamp_composition_latch_time_ =
-                                static_cast<uint64_t>(composition_latch_time);
+    if (swapchain.timing.size() < MIN_NUM_FRAMES_AGO) {
+        return 0;
+    }
 
-                            if (ti->ready()) {
-                                // The TimingInfo has received enough
-                                // timestamps, and should now use those
-                                // timestamps to calculate the info that should
-                                // be reported to the user:
-                                //
-                                ti->calculate(swapchain.refresh_duration);
-                                num_ready++;
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
+    uint32_t num_ready = 0;
+    const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1;
+    for (uint32_t i = 0; i < num_timings; i++) {
+        TimingInfo& ti = swapchain.timing.editItemAt(i);
+        if (ti.ready()) {
+            // This TimingInfo is ready to be reported to the user.  Add it
+            // to the num_ready.
+            num_ready++;
+            continue;
+        }
+        // This TimingInfo is not yet ready to be reported to the user,
+        // and so we should look for any available timestamps that
+        // might make it ready.
+        int64_t desired_present_time = 0;
+        int64_t render_complete_time = 0;
+        int64_t composition_latch_time = 0;
+        int64_t actual_present_time = 0;
+        // Obtain timestamps:
+        int ret = native_window_get_frame_timestamps(
+            swapchain.surface.window.get(), ti.native_frame_id_,
+            &desired_present_time, &render_complete_time,
+            &composition_latch_time,
+            NULL,  //&first_composition_start_time,
+            NULL,  //&last_composition_start_time,
+            NULL,  //&composition_finish_time,
+            // TODO(ianelliott): Maybe ask if this one is
+            // supported, at startup time (since it may not be
+            // supported):
+            &actual_present_time,
+            NULL,  //&display_retire_time,
+            NULL,  //&dequeue_ready_time,
+            NULL /*&reads_done_time*/);
+
+        if (ret != android::NO_ERROR) {
+            continue;
+        }
+
+        // Record the timestamp(s) we received, and then see if this TimingInfo
+        // is ready to be reported to the user:
+        ti.timestamp_desired_present_time_ =
+            static_cast<uint64_t>(desired_present_time);
+        ti.timestamp_actual_present_time_ =
+            static_cast<uint64_t>(actual_present_time);
+        ti.timestamp_render_complete_time_ =
+            static_cast<uint64_t>(render_complete_time);
+        ti.timestamp_composition_latch_time_ =
+               static_cast<uint64_t>(composition_latch_time);
+
+        if (ti.ready()) {
+            // The TimingInfo has received enough timestamps, and should now
+            // use those timestamps to calculate the info that should be
+            // reported to the user:
+            ti.calculate(swapchain.refresh_duration);
+            num_ready++;
         }
     }
     return num_ready;
@@ -369,29 +348,35 @@
 void copy_ready_timings(Swapchain& swapchain,
                         uint32_t* count,
                         VkPastPresentationTimingGOOGLE* timings) {
-    uint32_t num_copied = 0;
-    uint32_t num_timings = static_cast<uint32_t>(swapchain.timing.size());
-    if (*count < num_timings) {
-        num_timings = *count;
+    if (swapchain.timing.empty()) {
+        *count = 0;
+        return;
     }
-    for (uint32_t i = 0; i < num_timings; i++) {
-        TimingInfo* ti = &swapchain.timing.editItemAt(i);
-        if (ti && ti->ready()) {
-            ti->get_values(&timings[num_copied]);
-            num_copied++;
-            // We only report the values for a given present once, so remove
-            // them from swapchain.timing:
-            //
-            // TODO(ianelliott): SEE WHAT HAPPENS TO THE LOOP WHEN THE
-            // FOLLOWING IS DONE:
-            swapchain.timing.removeAt(i);
-            i--;
-            num_timings--;
-            if (*count == num_copied) {
-                break;
-            }
+
+    size_t last_ready = swapchain.timing.size() - 1;
+    while (!swapchain.timing[last_ready].ready()) {
+        if (last_ready == 0) {
+            *count = 0;
+            return;
         }
+        last_ready--;
     }
+
+    uint32_t num_copied = 0;
+    size_t num_to_remove = 0;
+    for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) {
+        const TimingInfo& ti = swapchain.timing[i];
+        if (ti.ready()) {
+            ti.get_values(&timings[num_copied]);
+            num_copied++;
+        }
+        num_to_remove++;
+    }
+
+    // Discard old frames that aren't ready if newer frames are ready.
+    // We don't expect to get the timing info for those old frames.
+    swapchain.timing.removeItemsAt(0, num_to_remove);
+
     *count = num_copied;
 }
 
@@ -812,13 +797,35 @@
 
     int gralloc_usage = 0;
     if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
-        result = dispatch.GetSwapchainGrallocUsage2ANDROID(
-            device, create_info->imageFormat, create_info->imageUsage,
-            swapchain_image_usage, &gralloc_usage);
+        uint64_t consumer_usage, producer_usage;
+        if (GetData(device).driver_version == 256587285) {
+            // HACK workaround for loader/driver mismatch during transition to
+            // vkGetSwapchainGrallocUsage2ANDROID.
+            typedef VkResult(VKAPI_PTR *
+                             PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK)(
+                VkDevice device, VkFormat format, VkImageUsageFlags imageUsage,
+                uint64_t * grallocConsumerUsage,
+                uint64_t * grallocProducerUsage);
+            auto get_swapchain_gralloc_usage =
+                reinterpret_cast<PFN_vkGetSwapchainGrallocUsage2ANDROID_HACK>(
+                    dispatch.GetSwapchainGrallocUsage2ANDROID);
+            result = get_swapchain_gralloc_usage(
+                device, create_info->imageFormat, create_info->imageUsage,
+                &consumer_usage, &producer_usage);
+        } else {
+            result = dispatch.GetSwapchainGrallocUsage2ANDROID(
+                device, create_info->imageFormat, create_info->imageUsage,
+                swapchain_image_usage, &consumer_usage, &producer_usage);
+        }
         if (result != VK_SUCCESS) {
             ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
             return VK_ERROR_INITIALIZATION_FAILED;
         }
+        // TODO: This is the same translation done by Gralloc1On0Adapter.
+        // Remove it once ANativeWindow has been updated to take gralloc1-style
+        // usages.
+        gralloc_usage =
+            static_cast<int>(consumer_usage) | static_cast<int>(producer_usage);
     } else if (dispatch.GetSwapchainGrallocUsageANDROID) {
         result = dispatch.GetSwapchainGrallocUsageANDROID(
             device, create_info->imageFormat, create_info->imageUsage,
@@ -827,8 +834,6 @@
             ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
             return VK_ERROR_INITIALIZATION_FAILED;
         }
-    } else {
-        gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
     }
     err = native_window_set_usage(surface.window.get(), gralloc_usage);
     if (err != 0) {
@@ -857,7 +862,8 @@
                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
     if (!mem)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
-    Swapchain* swapchain = new (mem) Swapchain(surface, num_images);
+    Swapchain* swapchain =
+        new (mem) Swapchain(surface, num_images, create_info->presentMode);
 
     // -- Dequeue all buffers and create a VkImage for each --
     // Any failures during or after this must cancel the dequeued buffers.
@@ -918,6 +924,12 @@
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
         image_native_buffer.usage = img.buffer->usage;
+        // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
+        // For now, this is the same translation Gralloc1On0Adapter does.
+        image_native_buffer.usage2.consumer =
+            static_cast<uint64_t>(img.buffer->usage);
+        image_native_buffer.usage2.producer =
+            static_cast<uint64_t>(img.buffer->usage);
 
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);
@@ -1153,7 +1165,8 @@
             *SwapchainFromHandle(present_info->pSwapchains[sc]);
         uint32_t image_idx = present_info->pImageIndices[sc];
         Swapchain::Image& img = swapchain.images[image_idx];
-        const VkPresentRegionKHR* region = (regions) ? &regions[sc] : nullptr;
+        const VkPresentRegionKHR* region =
+            (regions && !swapchain.mailbox_mode) ? &regions[sc] : nullptr;
         const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
         VkResult swapchain_result = VK_SUCCESS;
         VkResult result;
@@ -1219,13 +1232,20 @@
                         native_window_enable_frame_timestamps(window, true);
                         swapchain.frame_timestamps_enabled = true;
                     }
-                    // Record this presentID and desiredPresentTime so it can
-                    // be later correlated to this present.
-                    TimingInfo timing_record(time);
-                    swapchain.timing.add(timing_record);
-                    uint32_t num_timings =
-                        static_cast<uint32_t>(swapchain.timing.size());
-                    if (num_timings > MAX_TIMING_INFOS) {
+
+                    // Record the nativeFrameId so it can be later correlated to
+                    // this present.
+                    uint64_t nativeFrameId = 0;
+                    err = native_window_get_next_frame_id(
+                            window, &nativeFrameId);
+                    if (err != android::NO_ERROR) {
+                        ALOGE("Failed to get next native frame ID.");
+                    }
+
+                    // Add a new timing record with the user's presentID and
+                    // the nativeFrameId.
+                    swapchain.timing.push_back(TimingInfo(time, nativeFrameId));
+                    while (swapchain.timing.size() > MAX_TIMING_INFOS) {
                         swapchain.timing.removeAt(0);
                     }
                     if (time->desiredPresentTime) {
@@ -1331,5 +1351,18 @@
     return result;
 }
 
+VKAPI_ATTR void SetHdrMetadataEXT(
+    VkDevice device,
+    uint32_t swapchainCount,
+    const VkSwapchainKHR* pSwapchains,
+    const VkHdrMetadataEXT* pHdrMetadataEXTs) {
+    // TODO: courtneygo: implement actual function
+    (void)device;
+    (void)swapchainCount;
+    (void)pSwapchains;
+    (void)pHdrMetadataEXTs;
+    return;
+}
+
 }  // namespace driver
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index 91d7219..4d9f18f 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -37,6 +37,7 @@
 VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
 VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
 VKAPI_ATTR VkResult GetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain);
+VKAPI_ATTR void SetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount, const VkSwapchainKHR* pSwapchains, const VkHdrMetadataEXT* pHdrMetadataEXTs);
 // clang-format on
 
 }  // namespace driver
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 55f7f19..e03ee0a 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -906,9 +906,11 @@
                                           VkFormat,
                                           VkImageUsageFlags,
                                           VkSwapchainImageUsageFlagsANDROID,
-                                          int* grallocUsage) {
+                                          uint64_t* grallocConsumerUsage,
+                                          uint64_t* grallocProducerUsage) {
     // The null driver never reads or writes the gralloc buffer
-    *grallocUsage = 0;
+    *grallocConsumerUsage = 0;
+    *grallocProducerUsage = 0;
     return VK_SUCCESS;
 }
 
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index cfc14dd..d73bf14 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -165,8 +165,8 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int32_t* grallocUsage);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);