Merge "Mark libGLESv2.so and libEGL.so as VNDK libs." into oc-mr1-dev
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 5984093..f908cbf 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -42,6 +42,9 @@
     name: "libdumpstateutil",
     defaults: ["dumpstate_defaults"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     header_libs: ["dumpstate_headers"],
     export_header_lib_headers: ["dumpstate_headers"],
     srcs: [
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index fbfa7a8..f0b6203 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -18,6 +18,8 @@
 
 #include "DumpstateInternal.h"
 
+#include <grp.h>
+#include <pwd.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -33,7 +35,6 @@
 
 #include <android-base/file.h>
 #include <log/log.h>
-#include <private/android_filesystem_config.h>
 
 uint64_t Nanotime() {
     timespec ts;
@@ -43,7 +44,17 @@
 
 // Switches to non-root user and group.
 bool DropRootUser() {
-    if (getgid() == AID_SHELL && getuid() == AID_SHELL) {
+    struct group* grp = getgrnam("shell");
+    gid_t shell_gid = grp != nullptr ? grp->gr_gid : 0;
+    struct passwd* pwd = getpwnam("shell");
+    uid_t shell_uid = pwd != nullptr ? pwd->pw_uid : 0;
+
+    if (!shell_gid || !shell_uid) {
+        MYLOGE("Unable to get AID_SHELL: %s\n", strerror(errno));
+        return false;
+    }
+
+    if (getgid() == shell_gid && getuid() == shell_uid) {
         MYLOGD("drop_root_user(): already running as Shell\n");
         return true;
     }
@@ -53,17 +64,28 @@
         return false;
     }
 
-    gid_t groups[] = {AID_LOG,  AID_SDCARD_R,     AID_SDCARD_RW, AID_MOUNT,
-                      AID_INET, AID_NET_BW_STATS, AID_READPROC,  AID_BLUETOOTH};
-    if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) {
+    static const std::vector<std::string> group_names{
+        "log", "sdcard_r", "sdcard_rw", "mount", "inet", "net_bw_stats", "readproc", "bluetooth"};
+    std::vector<gid_t> groups(group_names.size(), 0);
+    for (size_t i = 0; i < group_names.size(); ++i) {
+        grp = getgrnam(group_names[i].c_str());
+        groups[i] = grp != nullptr ? grp->gr_gid : 0;
+        if (groups[i] == 0) {
+            MYLOGE("Unable to get required gid '%s': %s\n", group_names[i].c_str(),
+                   strerror(errno));
+            return false;
+        }
+    }
+
+    if (setgroups(groups.size(), groups.data()) != 0) {
         MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
         return false;
     }
-    if (setgid(AID_SHELL) != 0) {
+    if (setgid(shell_gid) != 0) {
         MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
         return false;
     }
-    if (setuid(AID_SHELL) != 0) {
+    if (setuid(shell_uid) != 0) {
         MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
         return false;
     }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4161bd7..657323d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -126,8 +126,7 @@
 static const std::string kDumpstateBoardPath = "/bugreports/";
 static const std::string kDumpstateBoardFiles[] = {
     "dumpstate_board.txt",
-    // TODO: rename to dumpstate_board.bin once vendors can handle it
-    "modem_log_all.tar"
+    "dumpstate_board.bin"
 };
 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
 
@@ -930,8 +929,10 @@
                  "VM TRACES AT LAST ANR", add_to_zip);
 
         if (anr_data->size() > 1) {
+            // NOTE: Historical ANRs are always added as separate entries in the
+            // bugreport zip file.
             AddDumps(anr_data->begin() + 1, anr_data->end(),
-                     "HISTORICAL ANR", add_to_zip);
+                     "HISTORICAL ANR", true /* add_to_zip */);
         }
     } else {
         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 202fdd1..a711813 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -320,7 +320,8 @@
         }
 
         dq.dqb_valid = QIF_LIMITS;
-        dq.dqb_bhardlimit = (((stat.f_blocks * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
+        dq.dqb_bhardlimit =
+            (((static_cast<uint64_t>(stat.f_blocks) * stat.f_frsize) / 10) * 9) / QIF_DQBLKSIZE;
         dq.dqb_ihardlimit = (stat.f_files / 2);
         if (quotactl(QCMD(Q_SETQUOTA, USRQUOTA), device.c_str(), uid,
                 reinterpret_cast<char*>(&dq)) != 0) {
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index d534830..2b2725f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1829,6 +1829,11 @@
         result = unlink_if_exists(current_profile) && result;
         result = unlink_if_exists(reference_profile) && result;
 
+        // We upgraded once the location of current profile for secondary dex files.
+        // Check for any previous left-overs and remove them as well.
+        std::string old_current_profile = dex_path + ".prof";
+        result = unlink_if_exists(old_current_profile);
+
         // Try removing the directories as well, they might be empty.
         result = rmdir_if_empty(oat_isa_dir) && result;
         result = rmdir_if_empty(oat_dir) && result;
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index dab3236..46ed85f 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -38,16 +38,6 @@
 
 #define TEST_PROFILE_DIR "/data/misc/profiles"
 
-#define REALLY_LONG_APP_NAME "com.example." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-
-#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
-
 namespace android {
 namespace installd {
 
@@ -88,6 +78,14 @@
     virtual void TearDown() {
         free(android_system_dirs.dirs);
     }
+
+    std::string create_too_long_path(const std::string& seed) {
+        std::string result = seed;
+        for (size_t i = seed.size(); i < PKG_PATH_MAX; i++) {
+            result += "a";
+        }
+        return result;
+    }
 };
 
 TEST_F(UtilsTest, IsValidApkPath_BadPrefix) {
@@ -388,17 +386,18 @@
             << "Primary user package directory should be created correctly";
 }
 
+
 TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
     char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
+    std::string really_long_app_name = create_too_long_path("com.example");
+    EXPECT_EQ(-1, create_move_path(path, really_long_app_name.c_str(), "shared_prefs", 0))
             << "Should fail to create move path for primary user";
 }
 
 TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
     char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
+    std::string really_long_leaf_name = create_too_long_path("leaf_");
+    EXPECT_EQ(-1, create_move_path(path, "com.android.test", really_long_leaf_name.c_str(), 0))
             << "Should fail to create move path for primary user";
 }
 
@@ -560,7 +559,7 @@
 }
 
 TEST_F(UtilsTest, CreateSecondaryCurrentProfile) {
-    EXPECT_EQ("/data/user/0/com.example/secondary.dex.prof",
+    EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.cur.prof",
             create_current_profile_path(/*user*/0,
                     "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
 }
@@ -571,5 +570,88 @@
                     "/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
 }
 
+static void pass_secondary_dex_validation(const std::string& package_name,
+        const std::string& dex_path, int uid, int storage_flag) {
+    EXPECT_TRUE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+            storage_flag))
+            << dex_path << " should be allowed as a valid secondary dex path";
+}
+
+static void fail_secondary_dex_validation(const std::string& package_name,
+        const std::string& dex_path, int uid, int storage_flag) {
+    EXPECT_FALSE(validate_secondary_dex_path(package_name, dex_path, /*volume_uuid*/ nullptr, uid,
+            storage_flag))
+            << dex_path << " should not be allowed as a valid secondary dex path";
+}
+
+TEST_F(UtilsTest, ValidateSecondaryDexFilesPath) {
+    std::string package_name = "com.test.app";
+    std::string app_dir_ce_user_0 = "/data/data/" + package_name;
+    std::string app_dir_ce_user_10 = "/data/user/10/" + package_name;
+
+    std::string app_dir_de_user_0 = "/data/user_de/0/" + package_name;
+    std::string app_dir_de_user_10 = "/data/user_de/10/" + package_name;
+
+    EXPECT_EQ(app_dir_ce_user_0,
+            create_data_user_ce_package_path(nullptr, 0, package_name.c_str()));
+    EXPECT_EQ(app_dir_ce_user_10,
+            create_data_user_ce_package_path(nullptr, 10, package_name.c_str()));
+
+    EXPECT_EQ(app_dir_de_user_0,
+            create_data_user_de_package_path(nullptr, 0, package_name.c_str()));
+    EXPECT_EQ(app_dir_de_user_10,
+            create_data_user_de_package_path(nullptr, 10, package_name.c_str()));
+
+    uid_t app_uid_for_user_0 = multiuser_get_uid(/*user_id*/0, /*app_id*/ 1234);
+    uid_t app_uid_for_user_10 = multiuser_get_uid(/*user_id*/10, /*app_id*/ 1234);
+
+    // Standard path for user 0 on CE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/ce0.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+    // Standard path for user 10 on CE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_ce_user_10 + "/ce10.dex", app_uid_for_user_10, FLAG_STORAGE_CE);
+
+    // Standard path for user 0 on DE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_de_user_0 + "/de0.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+    // Standard path for user 10 on DE storage.
+    pass_secondary_dex_validation(
+        package_name, app_dir_de_user_10 + "/de0.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+    // Dex path for user 0 accessed from user 10.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/path0_from10.dex",
+        app_uid_for_user_10, FLAG_STORAGE_CE);
+
+    // Dex path for CE storage accessed with DE.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/ce_from_de.dex", app_uid_for_user_0, FLAG_STORAGE_DE);
+
+    // Dex path for DE storage accessed with CE.
+    fail_secondary_dex_validation(
+        package_name, app_dir_de_user_0 + "/de_from_ce.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+    // Location which does not start with '/'.
+    fail_secondary_dex_validation(
+        package_name, "without_slash.dex", app_uid_for_user_10, FLAG_STORAGE_DE);
+
+    // The dex file is not in the specified package directory.
+    fail_secondary_dex_validation(
+        "another.package", app_dir_ce_user_0 + "/for_another_package.dex",
+        app_uid_for_user_0, FLAG_STORAGE_DE);
+
+    // The dex path contains indirect directories.
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/1/../foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_0 + "/1/./foo.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+
+    // Super long path.
+    std::string too_long = create_too_long_path("too_long_");
+    fail_secondary_dex_validation(
+        package_name, app_dir_ce_user_10 + "/" + too_long, app_uid_for_user_10, FLAG_STORAGE_CE);
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 7c05417..0faddf0 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -238,13 +238,38 @@
 
 // Keep profile paths in sync with ActivityThread and LoadedApk.
 const std::string PROFILE_EXT = ".prof";
+const std::string CURRENT_PROFILE_EXT = ".cur";
 const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
 
+// Gets the parent directory and the file name for the given secondary dex path.
+// Returns true on success, false on failure (if the dex_path does not have the expected
+// structure).
+static bool get_secondary_dex_location(const std::string& dex_path,
+        std::string* out_dir_name, std::string* out_file_name) {
+   size_t dirIndex = dex_path.rfind('/');
+   if (dirIndex == std::string::npos) {
+        return false;
+   }
+   if (dirIndex == dex_path.size() - 1) {
+        return false;
+   }
+   *out_dir_name = dex_path.substr(0, dirIndex);
+   *out_file_name = dex_path.substr(dirIndex + 1);
+
+   return true;
+}
+
 std::string create_current_profile_path(userid_t user, const std::string& location,
         bool is_secondary_dex) {
     if (is_secondary_dex) {
-        // Secondary dex profiles are stored next to the dex files using .prof extension.
-        return StringPrintf("%s%s", location.c_str(), PROFILE_EXT.c_str());
+        // Secondary dex current profiles are stored next to the dex files under the oat folder.
+        std::string dex_dir;
+        std::string dex_name;
+        CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
+                << "Unexpected dir structure for secondary dex " << location;
+        return StringPrintf("%s/oat/%s%s%s",
+                dex_dir.c_str(), dex_name.c_str(), CURRENT_PROFILE_EXT.c_str(),
+                PROFILE_EXT.c_str());
     } else {
         // Profiles for primary apks are under /data/misc/profiles/cur.
         std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
@@ -255,12 +280,10 @@
 std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
     if (is_secondary_dex) {
         // Secondary dex reference profiles are stored next to the dex files under the oat folder.
-        size_t dirIndex = location.rfind('/');
-        CHECK(dirIndex != std::string::npos)
+        std::string dex_dir;
+        std::string dex_name;
+        CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
                 << "Unexpected dir structure for secondary dex " << location;
-
-        std::string dex_dir = location.substr(0, dirIndex);
-        std::string dex_name = location.substr(dirIndex +1);
         return StringPrintf("%s/oat/%s%s",
                 dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
     } else {
@@ -781,21 +804,30 @@
         const char* volume_uuid, int uid, int storage_flag) {
     CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
 
+    // Empty paths are not allowed.
+    if (dex_path.empty()) { return false; }
+    // First character should always be '/'. No relative paths.
+    if (dex_path[0] != '/') { return false; }
+    // The last character should not be '/'.
+    if (dex_path[dex_path.size() - 1] == '/') { return false; }
+    // There should be no '.' after the directory marker.
+    if (dex_path.find("/.") != std::string::npos) { return false; }
+    // The path should be at most PKG_PATH_MAX long.
+    if (dex_path.size() > PKG_PATH_MAX) { return false; }
+
+    // The dex_path should be under the app data directory.
     std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
         ? create_data_user_ce_package_path(
                 volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
         : create_data_user_de_package_path(
                 volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
-    dir_rec_t dir;
-    if (get_path_from_string(&dir, app_private_dir.c_str()) != 0) {
-        LOG(WARNING) << "Could not get dir rec for " << app_private_dir;
+
+    if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
         return false;
     }
-    // Usually secondary dex files have a nested directory structure.
-    // Pick at most 10 subdirectories when validating (arbitrary value).
-    // If the secondary dex file is >10 directory nested then validation will
-    // fail and the file will not be compiled.
-    return validate_path(&dir, dex_path.c_str(), /*max_subdirs*/ 10) == 0;
+
+    // If we got here we have a valid path.
+    return true;
 }
 
 /**
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index d5cfcaf..31cd0cb 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -8,10 +8,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <cutils/android_filesystem_config.h>
 #include <cutils/multiuser.h>
 
-#include <private/android_filesystem_config.h>
-
 #include <selinux/android.h>
 #include <selinux/avc.h>
 
diff --git a/headers/Android.bp b/headers/Android.bp
index bcbbbc3..82bc8a1 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -1,7 +1,10 @@
 cc_library_headers {
     name: "media_plugin_headers",
     vendor_available: true,
-    export_include_dirs: ["media_plugin"],
+    export_include_dirs: [
+        "media_plugin",
+        "media_plugin/media/openmax",
+    ],
     header_libs: [
         "libstagefright_headers",
         "libcutils_headers",
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index 128dd2d..79ddb76 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -290,6 +290,8 @@
     OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
     OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
     OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+    OMX_VIDEO_DolbyVisionProfileDvheSt  = 0x100,
+    OMX_VIDEO_DolbyVisionProfileDvavSe  = 0x200,
     OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
 } OMX_VIDEO_DOLBYVISIONPROFILETYPE;
 
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index f31bcea..efa1ffb 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -65,6 +65,7 @@
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
+            int32_t displayId;
             int32_t action;
             int32_t flags;
             int32_t keyCode;
@@ -83,6 +84,7 @@
             nsecs_t eventTime __attribute__((aligned(8)));
             int32_t deviceId;
             int32_t source;
+            int32_t displayId;
             int32_t action;
             int32_t actionButton;
             int32_t flags;
@@ -232,6 +234,7 @@
             uint32_t seq,
             int32_t deviceId,
             int32_t source,
+            int32_t displayId,
             int32_t action,
             int32_t actionButton,
             int32_t flags,
@@ -303,7 +306,7 @@
      * Other errors probably indicate that the channel is broken.
      */
     status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
-            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
 
     /* Sends a finished signal to the publisher to inform it that the message
      * with the specified sequence number has finished being process and whether
@@ -424,9 +427,10 @@
     Vector<SeqChain> mSeqChains;
 
     status_t consumeBatch(InputEventFactoryInterface* factory,
-            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
     status_t consumeSamples(InputEventFactoryInterface* factory,
-            Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
+            Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
+            int32_t* displayId);
 
     void updateTouchState(InputMessage* msg);
     void rewriteMessage(const TouchState& state, InputMessage* msg);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 748105c..83b8021 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -33,6 +33,9 @@
 
     // for vndbinder
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     srcs: [
         "AppOpsManager.cpp",
@@ -66,8 +69,13 @@
         "TextOutput.cpp",
         "IpPrefix.cpp",
         "Value.cpp",
+        "aidl/android/content/pm/IPackageManagerNative.aidl",
     ],
 
+    aidl: {
+        export_aidl_headers: true,
+    },
+
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
new file mode 100644
index 0000000..6b7254c
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 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.
+*/
+
+package android.content.pm;
+
+/**
+ * Parallel implementation of certain {@link PackageManager} APIs that need to
+ * be exposed to native code.
+ * <p>These APIs are a parallel definition to the APIs in PackageManager, so,
+ * they can technically diverge. However, it's good practice to keep these
+ * APIs in sync with each other.
+ * <p>Because these APIs are exposed to native code, it's possible they will
+ * be exposed to privileged components [such as UID 0]. Care should be taken
+ * to avoid exposing potential security holes for methods where permission
+ * checks are bypassed based upon UID alone.
+ *
+ * @hide
+ */
+interface IPackageManagerNative {
+    /**
+     * Returns a set of names for the given UIDs.
+     * IMPORTANT: Unlike the Java version of this API, unknown UIDs are
+     * not represented by 'null's. Instead, they are represented by empty
+     * strings.
+     */
+    @utf8InCpp String[] getNamesForUids(in int[] uids);
+}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4558fe8..3996305 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -20,6 +20,9 @@
 cc_library_shared {
     name: "libgui",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     clang: true,
     cppflags: [
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 168d355..17cf677 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -15,6 +15,8 @@
  */
 
 #include <inttypes.h>
+#include <pwd.h>
+#include <sys/types.h>
 
 #define LOG_TAG "BufferQueueConsumer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -34,7 +36,6 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/PermissionCache.h>
-#include <private/android_filesystem_config.h>
 
 #include <system/window.h>
 
@@ -747,12 +748,19 @@
 }
 
 status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
+    struct passwd* pwd = getpwnam("shell");
+    uid_t shellUid = pwd ? pwd->pw_uid : 0;
+    if (!shellUid) {
+        int savedErrno = errno;
+        BQ_LOGE("Cannot get AID_SHELL");
+        return savedErrno ? -savedErrno : UNKNOWN_ERROR;
+    }
+
     const IPCThreadState* ipc = IPCThreadState::self();
     const pid_t pid = ipc->getCallingPid();
     const uid_t uid = ipc->getCallingUid();
-    if ((uid != AID_SHELL)
-            && !PermissionCache::checkPermission(String16(
-            "android.permission.DUMP"), pid, uid)) {
+    if ((uid != shellUid) &&
+        !PermissionCache::checkPermission(String16("android.permission.DUMP"), pid, uid)) {
         outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
                 "from pid=%d, uid=%d\n", pid, uid);
         android_errorWriteWithInfoLog(0x534e4554, "27046057",
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 3d94a02..3424012 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -347,10 +347,10 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
-        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
-        PixelFormat format, uint64_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
+status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
+                                            uint32_t width, uint32_t height, PixelFormat format,
+                                            uint64_t usage, uint64_t* outBufferAge,
+                                            FrameEventHistoryDelta* outTimestamps) {
     ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
@@ -558,6 +558,9 @@
             mSlots[*outSlot].mFrameNumber,
             mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
 
+    if (outBufferAge) {
+        *outBufferAge = mCore->mBufferAge;
+    }
     addAndGetFrameTimestamps(nullptr, outTimestamps);
 
     return returnFlags;
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 1b0fe06..8406a52 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -124,9 +124,9 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
-            uint32_t height, PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta* outTimestamps) {
+    virtual status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) {
         Parcel data, reply;
         bool getFrameTimestamps = (outTimestamps != nullptr);
 
@@ -149,6 +149,17 @@
             fence->clear();
             return result;
         }
+        if (outBufferAge) {
+            result = reply.readUint64(outBufferAge);
+        } else {
+            // Read the value even if outBufferAge is nullptr:
+            uint64_t bufferAge;
+            result = reply.readUint64(&bufferAge);
+        }
+        if (result != NO_ERROR) {
+            ALOGE("IGBP::dequeueBuffer failed to read buffer age: %d", result);
+            return result;
+        }
         if (getFrameTimestamps) {
             result = reply.read(*outTimestamps);
             if (result != NO_ERROR) {
@@ -516,11 +527,10 @@
         return mBase->setAsyncMode(async);
     }
 
-    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
-            PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta* outTimestamps) override {
-        return mBase->dequeueBuffer(
-                slot, fence, w, h, format, usage, outTimestamps);
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
+                           uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        return mBase->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
     }
 
     status_t detachBuffer(int slot) override {
@@ -655,16 +665,18 @@
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint64_t usage = data.readUint64();
+            uint64_t bufferAge = 0;
             bool getTimestamps = data.readBool();
 
             int buf = 0;
             sp<Fence> fence = Fence::NO_FENCE;
             FrameEventHistoryDelta frameTimestamps;
-            int result = dequeueBuffer(&buf, &fence, width, height, format,
-                    usage, getTimestamps ? &frameTimestamps : nullptr);
+            int result = dequeueBuffer(&buf, &fence, width, height, format, usage, &bufferAge,
+                                       getTimestamps ? &frameTimestamps : nullptr);
 
             reply->writeInt32(buf);
             reply->write(*fence);
+            reply->writeUint64(bufferAge);
             if (getTimestamps) {
                 reply->write(frameTimestamps);
             }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 409a3cb..78eb69d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -44,21 +44,19 @@
 
 namespace android {
 
-Surface::Surface(
-        const sp<IGraphicBufferProducer>& bufferProducer,
-        bool controlledByApp)
-    : mGraphicBufferProducer(bufferProducer),
-      mCrop(Rect::EMPTY_RECT),
-      mGenerationNumber(0),
-      mSharedBufferMode(false),
-      mAutoRefresh(false),
-      mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
-      mSharedBufferHasBeenQueued(false),
-      mQueriedSupportedTimestamps(false),
-      mFrameTimestampsSupportsPresent(false),
-      mEnableFrameTimestamps(false),
-      mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
-{
+Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
+      : mGraphicBufferProducer(bufferProducer),
+        mCrop(Rect::EMPTY_RECT),
+        mBufferAge(0),
+        mGenerationNumber(0),
+        mSharedBufferMode(false),
+        mAutoRefresh(false),
+        mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
+        mSharedBufferHasBeenQueued(false),
+        mQueriedSupportedTimestamps(false),
+        mFrameTimestampsSupportsPresent(false),
+        mEnableFrameTimestamps(false),
+        mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
@@ -506,9 +504,10 @@
     nsecs_t startTime = systemTime();
 
     FrameEventHistoryDelta frameTimestamps;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
-            reqWidth, reqHeight, reqFormat, reqUsage,
-            enableFrameTimestamps ? &frameTimestamps : nullptr);
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
+                                                            reqFormat, reqUsage, &mBufferAge,
+                                                            enableFrameTimestamps ? &frameTimestamps
+                                                                                  : nullptr);
     mLastDequeueDuration = systemTime() - startTime;
 
     if (result < 0) {
@@ -845,6 +844,14 @@
                 }
                 return err;
             }
+            case NATIVE_WINDOW_BUFFER_AGE: {
+                if (mBufferAge > INT32_MAX) {
+                    *value = 0;
+                } else {
+                    *value = static_cast<int32_t>(mBufferAge);
+                }
+                return NO_ERROR;
+            }
             case NATIVE_WINDOW_LAST_DEQUEUE_DURATION: {
                 int64_t durationUs = mLastDequeueDuration / 1000;
                 *value = durationUs > std::numeric_limits<int>::max() ?
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index 7c0552e..4a023a6 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -989,10 +989,10 @@
 }
 
 // FIXME: usage bits truncated -- needs a 64-bits usage version
-status_t H2BGraphicBufferProducer::dequeueBuffer(
-        int* slot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, ::android::PixelFormat format,
-        uint64_t usage, FrameEventHistoryDelta* outTimestamps) {
+status_t H2BGraphicBufferProducer::dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+                                                 uint32_t h, ::android::PixelFormat format,
+                                                 uint64_t usage, uint64_t* outBufferAge,
+                                                 FrameEventHistoryDelta* outTimestamps) {
     *fence = new Fence();
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->dequeueBuffer(
@@ -1016,6 +1016,10 @@
                     fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
                 }
             }));
+    if (outBufferAge) {
+        // Since the HAL version doesn't return the buffer age, set it to 0:
+        *outBufferAge = 0;
+    }
     return transStatus == NO_ERROR ? fnStatus : transStatus;
 }
 
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 0f8917a..d6f215e 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -80,9 +80,10 @@
     //
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
-    virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
-            uint32_t width, uint32_t height, PixelFormat format,
-            uint64_t usage, FrameEventHistoryDelta* outTimestamps) override;
+    virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width,
+                                   uint32_t height, PixelFormat format, uint64_t usage,
+                                   uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) override;
 
     // See IGraphicBufferProducer::detachBuffer
     virtual status_t detachBuffer(int slot);
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 6d16e74..f231f95 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -194,9 +194,9 @@
     //
     // All other negative values are an unknown error returned downstream
     // from the graphics allocator (typically errno).
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta* outTimestamps) = 0;
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
     // slot from the buffer queue. If this call succeeds, the slot will be
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 0f7e12a..60eac0c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -403,6 +403,10 @@
     // (the change since the previous frame) passed in by the producer.
     Region mDirtyRegion;
 
+    // mBufferAge tracks the age of the contents of the most recently dequeued
+    // buffer as the number of frames that have elapsed since it was last queued
+    uint64_t mBufferAge;
+
     // Stores the current generation number. See setGenerationNumber and
     // IGraphicBufferProducer::setGenerationNumber for more information.
     uint32_t mGenerationNumber;
diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index c3a9d44..c1c3ae7 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -64,9 +64,9 @@
     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
     status_t setAsyncMode(bool async) override;
-    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, ::android::PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta* outTimestamps) override;
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                           ::android::PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override;
     status_t detachBuffer(int slot) override;
     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence)
             override;
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index d64e530..b87cbbd 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -76,8 +76,8 @@
 
         int slot;
         sp<Fence> outFence;
-        status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth,
-                                                kHeight, 0, 0, nullptr);
+        status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth, kHeight, 0, 0,
+                                                nullptr, nullptr);
         ASSERT_GE(ret, 0);
 
         ALOGV("dequeueBuffer: slot=%d", slot);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 4220aaf..9a20859 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -144,8 +144,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -188,16 +188,16 @@
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
 
@@ -239,8 +239,8 @@
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
     for (int i = 0; i < 3; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                    GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -275,8 +275,8 @@
     BufferItem item;
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-            GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -285,8 +285,8 @@
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
-                GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
+                  mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+                                           nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -335,8 +335,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -384,8 +384,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
@@ -420,8 +420,8 @@
             EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataOut;
@@ -443,8 +443,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -492,22 +492,24 @@
     sp<GraphicBuffer> buffer;
     // This should return an error since it would require an allocation
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
-            0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(WOULD_BLOCK,
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
 
     // This should succeed, now that we've lifted the prohibition
     ASSERT_EQ(OK, mProducer->allowAllocation(true));
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       nullptr, nullptr));
 
     // Release the previous buffer back to the BufferQueue
     mProducer->cancelBuffer(slot, fence);
 
     // This should fail since we're requesting a different size
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
-            WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(WOULD_BLOCK,
+              mProducer->dequeueBuffer(&slot, &fence, WIDTH * 2, HEIGHT * 2, 0,
+                                       GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr, nullptr));
 }
 
 TEST_F(BufferQueueTest, TestGenerationNumbers) {
@@ -524,7 +526,7 @@
     int slot;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
 
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -567,7 +569,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Queue the buffer
@@ -581,8 +583,7 @@
     // always the same one and because async mode gets enabled.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -619,7 +620,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Queue the buffer
@@ -646,8 +647,7 @@
     // always return the same one.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -686,7 +686,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
 
     // Enable shared buffer mode
@@ -703,8 +703,7 @@
     // always the same one and because async mode gets enabled.
     int slot;
     for (int i = 0; i < 5; i++) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(sharedSlot, slot);
         ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
     }
@@ -739,8 +738,7 @@
     for (int i = 0; i < 5; ++i) {
         int slot = BufferQueue::INVALID_BUFFER_SLOT;
         sp<Fence> fence = Fence::NO_FENCE;
-        auto result = mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr);
+        auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
         if (i < 2) {
             ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
                     result);
@@ -767,8 +765,7 @@
     for (int i = 0; i < 2; ++i) {
         int slot = BufferQueue::INVALID_BUFFER_SLOT;
         sp<Fence> fence = Fence::NO_FENCE;
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
         IGraphicBufferProducer::QueueBufferInput input(0ull, true,
                 HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
@@ -779,8 +776,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> fence = Fence::NO_FENCE;
     auto startTime = systemTime();
-    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
-            &slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_GE(systemTime() - startTime, TIMEOUT);
 
     // We're technically attaching the same buffer multiple times (since we
@@ -801,7 +797,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> sourceFence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -824,7 +820,7 @@
     int slot = BufferQueue::INVALID_BUFFER_SLOT;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> firstBuffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
 
@@ -836,7 +832,7 @@
     // Dequeue a second buffer
     slot = BufferQueue::INVALID_BUFFER_SLOT;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+              mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     sp<GraphicBuffer> secondBuffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
 
@@ -887,8 +883,8 @@
     int slots[3] = {};
     mProducer->setMaxDequeuedBufferCount(3);
     for (size_t i = 0; i < 3; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -901,8 +897,7 @@
     // The first segment is a two-buffer segment, so we only put one buffer into
     // the queue at a time
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -917,17 +912,16 @@
     // two-buffer segment, but then at the end, we put two buffers in the queue
     // at the same time before draining it.
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
         std::this_thread::sleep_for(16ms);
     }
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
     ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -942,11 +936,10 @@
 
     // The third segment is a triple-buffer segment, so the queue is switching
     // between one buffer and two buffers deep.
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     for (size_t i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, mProducer->dequeueBuffer(
-                &slot, &fence, 0, 0, 0, 0, nullptr));
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
         ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
         ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -1026,8 +1019,8 @@
     int slots[4] = {};
     mProducer->setMaxDequeuedBufferCount(4);
     for (size_t i = 0; i < 4; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -1038,14 +1031,14 @@
     // Get buffers in all states: dequeued, filled, acquired, free
 
     // Fill 3 buffers
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     // Dequeue 1 buffer
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
 
     // Acquire and free 1 buffer
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -1104,8 +1097,8 @@
     int slots[2] = {};
     ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(2));
     for (size_t i = 0; i < 2; ++i) {
-        status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
-                0, 0, 0, 0, nullptr);
+        status_t result =
+                mProducer->dequeueBuffer(&slots[i], &fence, 0, 0, 0, 0, nullptr, nullptr);
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
         ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
     }
@@ -1115,10 +1108,10 @@
 
     // Fill 2 buffers without consumer consuming them. Verify that all
     // queued buffer returns proper bufferReplaced flag
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(false, output.bufferReplaced);
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
     ASSERT_EQ(true, output.bufferReplaced);
 }
@@ -1140,8 +1133,7 @@
             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
 
     // Dequeue, request, and queue one buffer
-    status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0,
-            nullptr);
+    status_t result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr);
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
@@ -1156,7 +1148,7 @@
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     // Dequeue and queue the buffer again
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     // Acquire and release the buffer again. Upon acquiring, the buffer handle
@@ -1168,7 +1160,7 @@
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     // Dequeue and queue the buffer again
-    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
+    ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr, nullptr));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     // Disconnect the producer end. This should clear all of the slots and mark
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index bcfc91c..dd23bd4 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -194,7 +194,8 @@
     };
 
     status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
-        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage, nullptr);
+        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage,
+                                        nullptr, nullptr);
     }
 
     void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
@@ -206,9 +207,12 @@
 
         ASSERT_NO_FATAL_FAILURE(ConnectProducer());
 
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
-                DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr)));
+
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                                    DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
+                                                    nullptr, nullptr)));
 
         EXPECT_LE(0, *slot);
         EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
@@ -343,11 +347,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     EXPECT_LE(0, dequeuedSlot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -403,10 +407,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     // Slot was enqueued without requesting a buffer
     {
@@ -472,10 +477,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS, nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)));
 
     // No return code, but at least test that it doesn't blow up...
     // TODO: add a return code
@@ -519,12 +525,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
     for (int i = 0; i < maxBuffers; ++i) {
-
-        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                         DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS, nullptr)))
+        EXPECT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "iteration: " << i << ", slot: " << dequeuedSlot;
     }
 
@@ -557,11 +562,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
     for (int i = 0; i < 2; i++) {
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                         DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot: " << dequeuedSlot;
     }
 
@@ -593,10 +598,11 @@
     // Should now be able to queue/dequeue as many buffers as we want without
     // blocking
     for (int i = 0; i < 5; ++i) {
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot : " << dequeuedSlot;
         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
@@ -610,10 +616,11 @@
         int dequeuedSlot = -1;
         sp<Fence> dequeuedFence;
 
-        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                TEST_PRODUCER_USAGE_BITS, nullptr)))
+        ASSERT_EQ(OK,
+                  ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                          (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence, DEFAULT_WIDTH,
+                                                    DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                                    TEST_PRODUCER_USAGE_BITS, nullptr, nullptr)))
                 << "slot: " << dequeuedSlot;
     }
 
@@ -630,8 +637,9 @@
     int slot = -1;
     sp<Fence> fence;
 
-    ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
-            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr));
+    ASSERT_EQ(NO_INIT,
+              mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                                       TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
 }
 
 TEST_F(IGraphicBufferProducerTest,
@@ -649,10 +657,11 @@
     int slot = -1;
     sp<Fence> fence;
 
-    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-            (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
-            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
-            nullptr)));
+    ASSERT_EQ(OK,
+              ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                      (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                                DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
+                                                nullptr, nullptr)));
 
     EXPECT_LE(0, slot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index 6bc3ccf..2b9fd5d 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -38,8 +38,10 @@
     }
     status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
-                           uint64_t usage, FrameEventHistoryDelta* outTimestamps) override {
-        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
+                           uint64_t usage, uint64_t* outBufferAge,
+                           FrameEventHistoryDelta* outTimestamps) override {
+        return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge,
+                                        outTimestamps);
     }
     status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
@@ -105,10 +107,10 @@
 
     // Override dequeueBuffer, optionally corrupting the returned slot number
     status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
-                           PixelFormat format, uint64_t usage,
+                           PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
                            FrameEventHistoryDelta* outTimestamps) override {
         EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
-                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
+                  mProducer->dequeueBuffer(buf, fence, width, height, format, usage, outBufferAge,
                                            outTimestamps));
         EXPECT_EQ(mExpectedSlot, *buf);
         if (mMaliciousValue != 0) {
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index e2f4948..ad6e051 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -82,8 +82,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -116,8 +116,8 @@
     // This should succeed even with allocation disabled since it will have
     // received the buffer back from the output BufferQueue
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
@@ -154,8 +154,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     uint32_t* dataIn;
@@ -191,8 +191,8 @@
     // This should succeed even with allocation disabled since it will have
     // received the buffer back from the output BufferQueues
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 TEST_F(StreamSplitterTest, OutputAbandonment) {
@@ -218,8 +218,8 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-                    GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
     // Abandon the output
@@ -231,8 +231,9 @@
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     // Input should be abandoned
-    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
-            GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
+    ASSERT_EQ(NO_INIT,
+              inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                           nullptr, nullptr));
 }
 
 } // namespace android
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 293bc25..d5c5927 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -285,6 +285,7 @@
         uint32_t seq,
         int32_t deviceId,
         int32_t source,
+        int32_t displayId,
         int32_t action,
         int32_t actionButton,
         int32_t flags,
@@ -327,6 +328,7 @@
     msg.body.motion.seq = seq;
     msg.body.motion.deviceId = deviceId;
     msg.body.motion.source = source;
+    msg.body.motion.displayId = displayId;
     msg.body.motion.action = action;
     msg.body.motion.actionButton = actionButton;
     msg.body.motion.flags = flags;
@@ -396,7 +398,8 @@
 }
 
 status_t InputConsumer::consume(InputEventFactoryInterface* factory,
-        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
+        int32_t* displayId) {
 #if DEBUG_TRANSPORT_ACTIONS
     ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
             mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
@@ -404,6 +407,7 @@
 
     *outSeq = 0;
     *outEvent = NULL;
+    *displayId = -1;  // Invalid display.
 
     // Fetch the next input message.
     // Loop until an event can be returned or no additional events are received.
@@ -418,7 +422,7 @@
             if (result) {
                 // Consume the next batched event unless batches are being held for later.
                 if (consumeBatches || result != WOULD_BLOCK) {
-                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
+                    result = consumeBatch(factory, frameTime, outSeq, outEvent, displayId);
                     if (*outEvent) {
 #if DEBUG_TRANSPORT_ACTIONS
                         ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
@@ -462,7 +466,7 @@
                     // the previous batch right now and defer the new message until later.
                     mMsgDeferred = true;
                     status_t result = consumeSamples(factory,
-                            batch, batch.samples.size(), outSeq, outEvent);
+                            batch, batch.samples.size(), outSeq, outEvent, displayId);
                     mBatches.removeAt(batchIndex);
                     if (result) {
                         return result;
@@ -496,6 +500,7 @@
             initializeMotionEvent(motionEvent, &mMsg);
             *outSeq = mMsg.body.motion.seq;
             *outEvent = motionEvent;
+            *displayId = mMsg.body.motion.displayId;
 #if DEBUG_TRANSPORT_ACTIONS
             ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
                     mChannel->getName().string(), *outSeq);
@@ -513,14 +518,14 @@
 }
 
 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
-        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
     status_t result;
     for (size_t i = mBatches.size(); i > 0; ) {
         i--;
         Batch& batch = mBatches.editItemAt(i);
         if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
-                    outSeq, outEvent);
+                    outSeq, outEvent, displayId);
             mBatches.removeAt(i);
             return result;
         }
@@ -534,7 +539,7 @@
             continue;
         }
 
-        result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
+        result = consumeSamples(factory, batch, split + 1, outSeq, outEvent, displayId);
         const InputMessage* next;
         if (batch.samples.isEmpty()) {
             mBatches.removeAt(i);
@@ -552,7 +557,7 @@
 }
 
 status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
-        Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
+        Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
     MotionEvent* motionEvent = factory->createMotionEvent();
     if (! motionEvent) return NO_MEMORY;
 
@@ -567,6 +572,7 @@
             mSeqChains.push(seqChain);
             addSample(motionEvent, &msg);
         } else {
+            *displayId = msg.body.motion.displayId;
             initializeMotionEvent(motionEvent, &msg);
         }
         chain = msg.body.motion.seq;
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 8e69c9c..a136738 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,7 +89,8 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+            0);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -132,6 +133,7 @@
     const uint32_t seq = 15;
     const int32_t deviceId = 1;
     const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+    const int32_t displayId = 0;
     const int32_t action = AMOTION_EVENT_ACTION_MOVE;
     const int32_t actionButton = 0;
     const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -164,7 +166,7 @@
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
     }
 
-    status = mPublisher->publishMotionEvent(seq, deviceId, source, action, actionButton,
+    status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
             flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
             downTime, eventTime, pointerCount,
             pointerProperties, pointerCoords);
@@ -173,7 +175,8 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+            0);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -256,7 +259,7 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -272,7 +275,7 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 81b9953..d19f3b8 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -38,31 +38,33 @@
   CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
   CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
   CHECK_OFFSET(InputMessage::Body::Key, source, 20);
-  CHECK_OFFSET(InputMessage::Body::Key, action, 24);
-  CHECK_OFFSET(InputMessage::Body::Key, flags, 28);
-  CHECK_OFFSET(InputMessage::Body::Key, keyCode, 32);
-  CHECK_OFFSET(InputMessage::Body::Key, scanCode, 36);
-  CHECK_OFFSET(InputMessage::Body::Key, metaState, 40);
-  CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 44);
-  CHECK_OFFSET(InputMessage::Body::Key, downTime, 48);
+  CHECK_OFFSET(InputMessage::Body::Key, displayId, 24);
+  CHECK_OFFSET(InputMessage::Body::Key, action, 28);
+  CHECK_OFFSET(InputMessage::Body::Key, flags, 32);
+  CHECK_OFFSET(InputMessage::Body::Key, keyCode, 36);
+  CHECK_OFFSET(InputMessage::Body::Key, scanCode, 40);
+  CHECK_OFFSET(InputMessage::Body::Key, metaState, 44);
+  CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 48);
+  CHECK_OFFSET(InputMessage::Body::Key, downTime, 56);
 
   CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
   CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
   CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
   CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
-  CHECK_OFFSET(InputMessage::Body::Motion, action, 24);
-  CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 28);
-  CHECK_OFFSET(InputMessage::Body::Motion, flags, 32);
-  CHECK_OFFSET(InputMessage::Body::Motion, metaState, 36);
-  CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 40);
-  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 44);
-  CHECK_OFFSET(InputMessage::Body::Motion, downTime, 48);
-  CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 56);
-  CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 60);
-  CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 64);
-  CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 68);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 72);
-  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 80);
+  CHECK_OFFSET(InputMessage::Body::Motion, displayId, 24);
+  CHECK_OFFSET(InputMessage::Body::Motion, action, 28);
+  CHECK_OFFSET(InputMessage::Body::Motion, actionButton, 32);
+  CHECK_OFFSET(InputMessage::Body::Motion, flags, 36);
+  CHECK_OFFSET(InputMessage::Body::Motion, metaState, 40);
+  CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 44);
+  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, downTime, 56);
+  CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 64);
+  CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);
+  CHECK_OFFSET(InputMessage::Body::Motion, xPrecision, 72);
+  CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 76);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 80);
+  CHECK_OFFSET(InputMessage::Body::Motion, pointers, 88);
 }
 
 } // namespace android
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index 0a537a3..a0e368c 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -38,7 +38,8 @@
         Sensor(*hwSensor, uuid_t(), halVersion) {
 }
 
-Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) :
+        Sensor("") {
     mName = hwSensor.name;
     mVendor = hwSensor.vendor;
     mVersion = hwSensor.version;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 6630d90..cabe94e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -15,6 +15,9 @@
 cc_library_shared {
     name: "libui",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
 
     clang: true,
     cppflags: [
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 3860390..bfb9a55 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -613,6 +613,12 @@
 
     std::unique_ptr<BufferConsumer> buffer_consumer =
         BufferConsumer::Import(std::move(buffer_handle_slot.first));
+    if (!buffer_consumer) {
+      ALOGE("ConsumerQueue::ImportBuffers: Failed to import buffer: slot=%zu",
+            buffer_handle_slot.second);
+      last_error = ErrorStatus(EPIPE);
+      continue;
+    }
 
     // Setup ignore state before adding buffer to the queue.
     if (ignore_on_import_) {
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index b44e55c..6613add 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -131,7 +131,7 @@
 
 status_t BufferHubQueueProducer::dequeueBuffer(
     int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
-    PixelFormat format, uint64_t usage,
+    PixelFormat format, uint64_t usage, uint64_t* /*outBufferAge*/,
     FrameEventHistoryDelta* /* out_timestamps */) {
   ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width,
            height, format, usage);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 638a56c..d33a831 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -43,6 +43,7 @@
   // See |IGraphicBufferProducer::dequeueBuffer|
   status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
                          uint32_t height, PixelFormat format, uint64_t usage,
+                         uint64_t* outBufferAge,
                          FrameEventHistoryDelta* outTimestamps) override;
 
   // See |IGraphicBufferProducer::detachBuffer|
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index c7692d0..8f55125 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -117,9 +117,9 @@
     ASSERT_NE(nullptr, outSlot);
     ASSERT_NE(nullptr, outFence);
 
-    int ret = mProducer->dequeueBuffer(outSlot, outFence, kDefaultWidth,
-                                       kDefaultHeight, kDefaultFormat,
-                                       kTestProducerUsageBits, nullptr);
+    int ret = mProducer->dequeueBuffer(
+        outSlot, outFence, kDefaultWidth, kDefaultHeight, kDefaultFormat,
+        kTestProducerUsageBits, nullptr, nullptr);
     // BUFFER_NEEDS_REALLOCATION can be either on or off.
     ASSERT_EQ(0, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & ret);
 
@@ -440,9 +440,10 @@
   sp<Fence> fence;
   for (int i = 0; i < 2; i++) {
     ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
-                      (mProducer->dequeueBuffer(
-                          &slot, &fence, kDefaultWidth, kDefaultHeight,
-                          kDefaultFormat, kTestProducerUsageBits, nullptr)))
+                      (mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
+                                                kDefaultHeight, kDefaultFormat,
+                                                kTestProducerUsageBits,
+                                                nullptr, nullptr)))
         << "slot: " << slot;
   }
 
@@ -458,7 +459,8 @@
 
   ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, kDefaultWidth,
                                               kDefaultHeight, kDefaultFormat,
-                                              kTestProducerUsageBits, nullptr));
+                                              kTestProducerUsageBits,
+                                              nullptr, nullptr));
 }
 
 TEST_F(BufferHubQueueProducerTest,
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 16da1d9..f75283d 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -464,6 +464,162 @@
   ASSERT_GT(event_fd, 0);
 }
 
+// Verifies a Dvr{Read,Write}BufferQueue contains the same set of
+// Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
+// the corresponding AHardwareBuffer handle stays the same.
+TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) {
+  ASSERT_NO_FATAL_FAILURE(CreateWriteBufferQueue());
+  ASSERT_NO_FATAL_FAILURE(AllocateBuffers(kQueueCapacity));
+
+  int fence_fd = -1;
+  DvrReadBufferQueue* read_queue = nullptr;
+  EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
+
+  // Read buffers.
+  std::array<DvrReadBuffer*, kQueueCapacity> rbs;
+  // Write buffers.
+  std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
+  // Hardware buffers for Read buffers.
+  std::unordered_map<int, AHardwareBuffer*> rhbs;
+  // Hardware buffers for Write buffers.
+  std::unordered_map<int, AHardwareBuffer*> whbs;
+
+  for (size_t i = 0; i < kQueueCapacity; i++) {
+    dvrReadBufferCreateEmpty(&rbs[i]);
+    dvrWriteBufferCreateEmpty(&wbs[i]);
+  }
+
+  constexpr int kNumTests = 100;
+  constexpr int kTimeout = 0;
+  TestMeta seq = 0U;
+
+  // This test runs the following operations many many times. Thus we prefer to
+  // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
+  std::function<void(size_t i)> Gain = [&](size_t i) {
+    ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wbs[i],
+                                            &fence_fd));
+    ASSERT_LT(fence_fd, 0);  // expect invalid fence.
+    ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
+    int buffer_id = dvrWriteBufferGetId(wbs[i]);
+    ASSERT_GT(buffer_id, 0);
+
+    AHardwareBuffer* hb = nullptr;
+    ASSERT_EQ(0, dvrWriteBufferGetAHardwareBuffer(wbs[i], &hb));
+
+    auto whb_it = whbs.find(buffer_id);
+    if (whb_it == whbs.end()) {
+      // If this is a new buffer id, check that total number of unique
+      // hardware buffers won't exceed queue capacity.
+      ASSERT_LT(whbs.size(), kQueueCapacity);
+      whbs.emplace(buffer_id, hb);
+    } else {
+      // If this is a buffer id we have seen before, check that the
+      // buffer_id maps to the same AHardwareBuffer handle.
+      ASSERT_EQ(hb, whb_it->second);
+    }
+  };
+
+  std::function<void(size_t i)> Post = [&](size_t i) {
+    ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
+
+    seq++;
+    ASSERT_EQ(0, dvrWriteBufferPost(wbs[i], /*fence=*/-1, &seq, sizeof(seq)));
+  };
+
+  std::function<void(size_t i)> Acquire = [&](size_t i) {
+    TestMeta out_seq = 0U;
+    ASSERT_EQ(0,
+              dvrReadBufferQueueDequeue(read_queue, kTimeout, rbs[i], &fence_fd,
+                                        &out_seq, sizeof(out_seq)));
+    ASSERT_LT(fence_fd, 0);  // expect invalid fence.
+    ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
+
+    int buffer_id = dvrReadBufferGetId(rbs[i]);
+    ASSERT_GT(buffer_id, 0);
+
+    AHardwareBuffer* hb = nullptr;
+    ASSERT_EQ(0, dvrReadBufferGetAHardwareBuffer(rbs[i], &hb));
+
+    auto rhb_it = rhbs.find(buffer_id);
+    if (rhb_it == rhbs.end()) {
+      // If this is a new buffer id, check that total number of unique hardware
+      // buffers won't exceed queue capacity.
+      ASSERT_LT(rhbs.size(), kQueueCapacity);
+      rhbs.emplace(buffer_id, hb);
+    } else {
+      // If this is a buffer id we have seen before, check that the buffer_id
+      // maps to the same AHardwareBuffer handle.
+      ASSERT_EQ(hb, rhb_it->second);
+    }
+  };
+
+  std::function<void(size_t i)> Release = [&](size_t i) {
+    ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
+
+    seq++;
+    ASSERT_EQ(0, dvrReadBufferRelease(rbs[i], /*fence=*/-1));
+  };
+
+  // Scenario one:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+    }
+    // Post all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Post(i));
+    }
+    // Acquire all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+    }
+    // Release all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Release(i));
+    }
+  }
+
+  // Scenario two:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain and post all write buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+      ASSERT_NO_FATAL_FAILURE(Post(i));
+    }
+    // Acquire and release all read buffers.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+      ASSERT_NO_FATAL_FAILURE(Release(i));
+    }
+  }
+
+  // Scenario three:
+  for (int i = 0; i < kNumTests; i++) {
+    // Gain all write buffers then post them in reversed order.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Gain(i));
+    }
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Post(kQueueCapacity - 1 - i));
+    }
+
+    // Acquire all write buffers then release them in reversed order.
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Acquire(i));
+    }
+    for (size_t i = 0; i < kQueueCapacity; i++) {
+      ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i));
+    }
+  }
+
+  // Clean up all read buffers and write buffers.
+  for (size_t i = 0; i < kQueueCapacity; i++) {
+    dvrReadBufferDestroy(rbs[i]);
+    dvrWriteBufferDestroy(wbs[i]);
+  }
+}
+
 }  // namespace
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index 04e3d5f..4852fab 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -194,6 +194,7 @@
            "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
            surface_id(), queue_id);
 
+  std::lock_guard<std::mutex> autolock(lock_);
   auto search = consumer_queues_.find(queue_id);
   if (search != consumer_queues_.end())
     return search->second;
@@ -202,6 +203,7 @@
 }
 
 std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
   std::vector<int32_t> queue_ids;
   for (const auto& entry : consumer_queues_)
     queue_ids.push_back(entry.first);
@@ -270,6 +272,7 @@
 }
 
 std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const {
+  std::lock_guard<std::mutex> autolock(lock_);
   std::vector<int32_t> queue_ids;
   if (direct_queue_)
     queue_ids.push_back(direct_queue_->id());
@@ -298,6 +301,9 @@
     }
 
     direct_queue_ = producer->CreateConsumerQueue();
+    if (direct_queue_->metadata_size() > 0) {
+      metadata_.reset(new uint8_t[direct_queue_->metadata_size()]);
+    }
     auto status = RegisterQueue(direct_queue_);
     if (!status) {
       ALOGE(
@@ -342,7 +348,12 @@
   while (true) {
     LocalHandle acquire_fence;
     size_t slot;
-    auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
+    auto buffer_status = direct_queue_->Dequeue(
+        0, &slot, metadata_.get(),
+        direct_queue_->metadata_size(), &acquire_fence);
+    ALOGD_IF(TRACE,
+             "DirectDisplaySurface::DequeueBuffersLocked: Dequeue with metadata_size: %zu",
+             direct_queue_->metadata_size());
     if (!buffer_status) {
       ALOGD_IF(
           TRACE > 1 && buffer_status.error() == ETIMEDOUT,
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 556183a..7a0fb18 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -133,6 +133,7 @@
   void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
                     int events) override;
 
+  // Accessed by both message dispatch thread and epoll event thread.
   std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
 };
 
@@ -143,7 +144,8 @@
                        const display::SurfaceAttributes& attributes)
       : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
                        user_id, attributes),
-        acquired_buffers_(kMaxPostedBuffers) {}
+        acquired_buffers_(kMaxPostedBuffers),
+        metadata_(nullptr){}
   std::vector<int32_t> GetQueueIds() const override;
   bool IsBufferAvailable();
   bool IsBufferPosted();
@@ -178,6 +180,9 @@
   RingBuffer<AcquiredBuffer> acquired_buffers_;
 
   std::shared_ptr<ConsumerQueue> direct_queue_;
+
+  // Stores metadata when it dequeue buffers from consumer queue.
+  std::unique_ptr<uint8_t[]> metadata_;
 };
 
 }  // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 4479d1e..11c1370 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -821,8 +821,9 @@
       std::unique_lock<std::mutex> lock(post_thread_mutex_);
       ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
 
-      // Tear down resources.
-      OnPostThreadPaused();
+      // Tear down resources if necessary.
+      if (was_running)
+        OnPostThreadPaused();
 
       was_running = false;
       post_thread_resumed_ = false;
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 2efb340..69067d2 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -869,10 +869,7 @@
         return true;
     }
 
-    // TODO: support sending secondary display events to input monitors
-    if (isMainDisplay(entry->displayId)) {
-        addMonitoringTargetsLocked(inputTargets);
-    }
+    addMonitoringTargetsLocked(inputTargets);
 
     // Dispatch the motion.
     if (conflictingPointerActions) {
@@ -2026,7 +2023,7 @@
 
             // Publish the motion event.
             status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
-                    motionEntry->deviceId, motionEntry->source,
+                    motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
                     dispatchEntry->resolvedAction, motionEntry->actionButton,
                     dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                     motionEntry->metaState, motionEntry->buttonState,
@@ -2600,8 +2597,9 @@
         uint32_t policyFlags) {
 #if DEBUG_INBOUND_EVENT_DETAILS
     ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
-            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
+            "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x, displayId=%d",
+            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags,
+            displayId);
 #endif
 
     nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 27009d0..935d0f6 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2373,6 +2373,35 @@
         || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
 }
 
+bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
+    switch (keyCode) {
+    case AKEYCODE_MEDIA_PLAY:
+    case AKEYCODE_MEDIA_PAUSE:
+    case AKEYCODE_MEDIA_PLAY_PAUSE:
+    case AKEYCODE_MUTE:
+    case AKEYCODE_HEADSETHOOK:
+    case AKEYCODE_MEDIA_STOP:
+    case AKEYCODE_MEDIA_NEXT:
+    case AKEYCODE_MEDIA_PREVIOUS:
+    case AKEYCODE_MEDIA_REWIND:
+    case AKEYCODE_MEDIA_RECORD:
+    case AKEYCODE_MEDIA_FAST_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_FORWARD:
+    case AKEYCODE_MEDIA_SKIP_BACKWARD:
+    case AKEYCODE_MEDIA_STEP_FORWARD:
+    case AKEYCODE_MEDIA_STEP_BACKWARD:
+    case AKEYCODE_MEDIA_AUDIO_TRACK:
+    case AKEYCODE_VOLUME_UP:
+    case AKEYCODE_VOLUME_DOWN:
+    case AKEYCODE_VOLUME_MUTE:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
+    case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
+        return true;
+    }
+    return false;
+}
+
 void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
         int32_t usageCode) {
     int32_t keyCode;
@@ -2446,7 +2475,7 @@
     // For internal keyboards, the key layout file should specify the policy flags for
     // each wake key individually.
     // TODO: Use the input device configuration to control this behavior more finely.
-    if (down && getDevice()->isExternal()) {
+    if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
         policyFlags |= POLICY_FLAG_WAKE;
     }
 
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 803dcc9..a6b9798 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1128,6 +1128,7 @@
     void dumpParameters(String8& dump);
 
     bool isKeyboardOrGamepadKey(int32_t scanCode);
+    bool isMediaKey(int32_t keyCode);
 
     void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a0abf12..fc60002 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -442,6 +442,11 @@
 android_color_mode_t DisplayDevice::getActiveColorMode() const {
     return mActiveColorMode;
 }
+
+void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) {
+    ANativeWindow* const window = mNativeWindow.get();
+    native_window_set_buffers_data_space(window, dataspace);
+}
 #endif
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e2852a7..8636e2a 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -141,6 +141,7 @@
 
     uint32_t                getLayerStack() const { return mLayerStack; }
     int32_t                 getDisplayType() const { return mType; }
+    bool                    isPrimary() const { return mType == DISPLAY_PRIMARY; }
     int32_t                 getHwcDisplayId() const { return mHwcDisplayId; }
     const wp<IBinder>&      getDisplayToken() const { return mDisplayToken; }
 
@@ -189,6 +190,7 @@
 #ifdef USE_HWC2
     android_color_mode_t getActiveColorMode() const;
     void setActiveColorMode(android_color_mode_t mode);
+    void setCompositionDataSpace(android_dataspace dataspace);
 #endif
 
     /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 5b869e1..1ac21c6 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -106,12 +106,6 @@
     if (result != NO_ERROR) {
         ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
                 strerror(-result), result);
-        return result;
-    }
-    result = mHwc.setClientTarget(mDisplayType, slot,
-            acquireFence, buf, dataspace);
-    if (result != NO_ERROR) {
-        ALOGE("error posting framebuffer: %d", result);
     }
     return result;
 #else
@@ -179,9 +173,16 @@
     mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
             &outSlot, &outBuffer);
     outDataspace = item.mDataSpace;
+    status_t result =
+            mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error posting framebuffer: %d", result);
+        return result;
+    }
 #else
     outBuffer = mCurrentBuffer;
 #endif
+
     return NO_ERROR;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c129ae5..34f1cec 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -345,8 +345,9 @@
         PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
     LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
 
-    status_t result = mSource[source]->dequeueBuffer(sslot, fence,
-            mSinkBufferWidth, mSinkBufferHeight, format, usage, nullptr);
+    status_t result =
+            mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
+                                           format, usage, nullptr, nullptr);
     if (result < 0)
         return result;
     int pslot = mapSource2ProducerSlot(source, *sslot);
@@ -384,12 +385,13 @@
     return result;
 }
 
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
+status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                              PixelFormat format, uint64_t usage,
+                                              uint64_t* outBufferAge,
+                                              FrameEventHistoryDelta* outTimestamps) {
     if (mDisplayId < 0) {
-        return mSource[SOURCE_SINK]->dequeueBuffer(
-                pslot, fence, w, h, format, usage, outTimestamps);
+        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
+                                                   outTimestamps);
     }
 
     VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
@@ -449,6 +451,9 @@
             *pslot = mapSource2ProducerSlot(source, sslot);
         }
     }
+    if (outBufferAge) {
+        *outBufferAge = 0;
+    }
     return result;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 7f8b39b..ac200ca 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -104,9 +104,9 @@
     virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta *outTimestamps);
+    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 392479f..2306d1a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -166,6 +166,8 @@
 
     virtual ~Layer();
 
+    void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
+
     // the this layer's size and format
     status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
 
@@ -249,6 +251,10 @@
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t setTransactionFlags(uint32_t flags);
 
+    bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const {
+        return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
+    }
+
     void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
             bool useIdentityTransform) const;
     Rect computeBounds(const Region& activeTransparentRegion) const;
@@ -701,6 +707,8 @@
     String8 mTransactionName; // A cached version of "TX - " + mName for systraces
     PixelFormat mFormat;
 
+    bool mPrimaryDisplayOnly = false;
+
     // these are protected by an external lock
     State mCurrentState;
     State mDrawingState;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index e717632..d103820 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -68,11 +68,11 @@
     return mProducer->setAsyncMode(async);
 }
 
-status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
-        FrameEventHistoryDelta* outTimestamps) {
-    return mProducer->dequeueBuffer(
-            slot, fence, w, h, format, usage, outTimestamps);
+status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                          PixelFormat format, uint64_t usage,
+                                          uint64_t* outBufferAge,
+                                          FrameEventHistoryDelta* outTimestamps) {
+    return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
 }
 
 status_t MonitoredProducer::detachBuffer(int slot) {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 58b9bc4..ff7f0f0 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -39,9 +39,9 @@
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint64_t usage,
-            FrameEventHistoryDelta* outTimestamps);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+                                   PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+                                   FrameEventHistoryDelta* outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bcc30f6..6ae217f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -385,6 +385,7 @@
 #ifdef USE_HWC2
         sp<DisplayDevice> hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
         if (hw->getWideColorSupport()) {
+            hw->setCompositionDataSpace(HAL_DATASPACE_V0_SRGB);
             setActiveColorModeInternal(hw, HAL_COLOR_MODE_SRGB);
         }
 #endif
@@ -1224,6 +1225,7 @@
                                              hasWideColorModes && hasWideColorDisplay);
     mDisplays.add(token, hw);
     setActiveColorModeInternal(hw, HAL_COLOR_MODE_NATIVE);
+    hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
 }
 
 void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
@@ -1681,12 +1683,11 @@
             const Transform& tr(displayDevice->getTransform());
             const Rect bounds(displayDevice->getBounds());
             if (displayDevice->isDisplayOn()) {
-                computeVisibleRegions(
-                        displayDevice->getLayerStack(), dirtyRegion,
-                        opaqueRegion);
+                computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
 
                 mDrawingState.traverseInZOrder([&](Layer* layer) {
-                    if (layer->getLayerStack() == displayDevice->getLayerStack()) {
+                    if (layer->belongsToDisplay(displayDevice->getLayerStack(),
+                                displayDevice->isPrimary())) {
                         Region drawRegion(tr.transform(
                                 layer->visibleNonTransparentRegion));
                         drawRegion.andSelf(bounds);
@@ -1872,6 +1873,7 @@
             // To achieve this we suppress color mode changes until after the boot animation
             if (mBootFinished) {
                 setActiveColorModeInternal(displayDevice, newColorMode);
+                displayDevice->setCompositionDataSpace(newDataSpace);
             }
         }
     }
@@ -2207,7 +2209,7 @@
                 disp.clear();
                 for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                     sp<const DisplayDevice> hw(mDisplays[dpy]);
-                    if (hw->getLayerStack() == currentlayerStack) {
+                    if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
                         if (disp == NULL) {
                             disp = hw;
                         } else {
@@ -2256,7 +2258,7 @@
                 // TODO: we could cache the transformed region
                 Region visibleReg;
                 visibleReg.set(layer->computeScreenBounds());
-                invalidateLayerStack(layer->getLayerStack(), visibleReg);
+                invalidateLayerStack(layer, visibleReg);
             }
         });
     }
@@ -2305,7 +2307,7 @@
     mTransactionCV.broadcast();
 }
 
-void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack,
+void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
         Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
@@ -2322,7 +2324,7 @@
         const Layer::State& s(layer->getDrawingState());
 
         // only consider the layers on the given layer stack
-        if (layer->getLayerStack() != layerStack)
+        if (!layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary()))
             return;
 
         /*
@@ -2437,11 +2439,10 @@
     outOpaqueRegion = aboveOpaqueLayers;
 }
 
-void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
-        const Region& dirty) {
+void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
-        if (hw->getLayerStack() == layerStack) {
+        if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
             hw->dirtyRegion.orSelf(dirty);
         }
     }
@@ -2482,7 +2483,7 @@
     for (auto& layer : mLayersWithQueuedFrames) {
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
-        invalidateLayerStack(layer->getLayerStack(), dirty);
+        invalidateLayerStack(layer, dirty);
         if (layer->isBufferLatched()) {
             newDataLatched = true;
         }
@@ -3104,6 +3105,13 @@
         return result;
     }
 
+    // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
+    // TODO b/64227542
+    if (windowType == 441731) {
+        windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
+        layer->setPrimaryDisplayOnly();
+    }
+
     layer->setInfo(windowType, ownerUid);
 
     result = addClientLayer(client, *handle, *gbp, layer, *parent);
@@ -4331,7 +4339,7 @@
     // We loop through the first level of layers without traversing,
     // as we need to interpret min/max layer Z in the top level Z space.
     for (const auto& layer : mDrawingState.layersSortedByZ) {
-        if (layer->getLayerStack() != hw->getLayerStack()) {
+        if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
             continue;
         }
         const Layer::State& state(layer->getDrawingState());
@@ -4383,7 +4391,7 @@
     bool secureLayerIsVisible = false;
     for (const auto& layer : mDrawingState.layersSortedByZ) {
         const Layer::State& state(layer->getDrawingState());
-        if ((layer->getLayerStack() != hw->getLayerStack()) ||
+        if (layer->belongsToDisplay(hw->getLayerStack(), false) ||
                 (state.z < minLayerZ || state.z > maxLayerZ)) {
             continue;
         }
@@ -4494,7 +4502,7 @@
         size_t i = 0;
         for (const auto& layer : mDrawingState.layersSortedByZ) {
             const Layer::State& state(layer->getDrawingState());
-            if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
+            if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ &&
                     state.z <= maxLayerZ) {
                 layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
                     ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 48bbd13..acfad46 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -494,7 +494,7 @@
 
     // mark a region of a layer stack dirty. this updates the dirty
     // region of all screens presenting this layer stack.
-    void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
+    void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
 
 #ifndef USE_HWC2
     int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
@@ -510,7 +510,7 @@
      * Compositing
      */
     void invalidateHwcGeometry();
-    void computeVisibleRegions(uint32_t layerStack,
+    void computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
             Region& dirtyRegion, Region& opaqueRegion);
 
     void preComposition(nsecs_t refreshStartTime);
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 213ab80..186031a 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1361,8 +1361,7 @@
             const Transform& tr(hw->getTransform());
             const Rect bounds(hw->getBounds());
             if (hw->isDisplayOn()) {
-                computeVisibleRegions(hw->getLayerStack(), dirtyRegion,
-                        opaqueRegion);
+                computeVisibleRegions(hw, dirtyRegion, opaqueRegion);
 
                 mDrawingState.traverseInZOrder([&](Layer* layer) {
                     if (layer->getLayerStack() == hw->getLayerStack()) {
@@ -1863,7 +1862,7 @@
                 // TODO: we could cache the transformed region
                 Region visibleReg;
                 visibleReg.set(layer->computeScreenBounds());
-                invalidateLayerStack(layer->getLayerStack(), visibleReg);
+                invalidateLayerStack(layer, visibleReg);
             }
         });
     }
@@ -1924,7 +1923,7 @@
     mTransactionCV.broadcast();
 }
 
-void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack,
+void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
         Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
@@ -1940,7 +1939,7 @@
         const Layer::State& s(layer->getDrawingState());
 
         // only consider the layers on the given layer stack
-        if (layer->getLayerStack() != layerStack)
+        if (layer->getLayerStack() != displayDevice->getLayerStack())
             return;
 
         /*
@@ -2055,8 +2054,8 @@
     outOpaqueRegion = aboveOpaqueLayers;
 }
 
-void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
-        const Region& dirty) {
+void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
+    uint32_t layerStack = layer->getLayerStack();
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
         if (hw->getLayerStack() == layerStack) {
@@ -2099,7 +2098,7 @@
         Layer* layer = layersWithQueuedFrames[i];
         const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
-        invalidateLayerStack(layer->getLayerStack(), dirty);
+        invalidateLayerStack(layer, dirty);
     }
 
     mVisibleRegionsDirty |= visibleRegions;
diff --git a/services/thermalservice/Android.bp b/services/thermalservice/Android.bp
new file mode 100644
index 0000000..d754560
--- /dev/null
+++ b/services/thermalservice/Android.bp
@@ -0,0 +1,61 @@
+subdirs = [
+    "libthermalcallback"
+]
+
+cc_library {
+    name: "libthermalservice",
+
+    srcs: [
+        "aidl/android/os/IThermalEventListener.aidl",
+        "aidl/android/os/IThermalService.aidl",
+        "aidl/android/os/Temperature.cpp",
+    ],
+    aidl: {
+      include_dirs: ["frameworks/native/services/thermalservice/aidl"],
+      export_aidl_headers: true,
+    },
+    export_include_dirs: ["aidl"],
+
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
+
+cc_binary {
+    name: "thermalserviced",
+
+    srcs: [
+        "ThermalService.cpp",
+        "thermalserviced.cpp",
+    ],
+
+    include_dirs: ["frameworks/native"],
+
+    shared_libs: [
+        "libthermalservice",
+        "libbinder",
+        "libutils",
+        "libthermalcallback",
+        "android.hardware.thermal@1.1",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+
+    init_rc: ["thermalservice.rc"],
+}
diff --git a/services/thermalservice/ThermalService.cpp b/services/thermalservice/ThermalService.cpp
new file mode 100644
index 0000000..6e09a83
--- /dev/null
+++ b/services/thermalservice/ThermalService.cpp
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#include "ThermalService.h"
+#include <android/os/IThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace os {
+
+/**
+ * Notify registered listeners of a thermal throttling start/stop event.
+ * @param temperature the temperature at which the event was generated
+ */
+binder::Status ThermalService::notifyThrottling(
+    const bool isThrottling, const Temperature& temperature) {
+    Mutex::Autolock _l(mListenersLock);
+
+    mThrottled = isThrottling;
+    mThrottleTemperature = temperature;
+
+    for (size_t i = 0; i < mListeners.size(); i++) {
+      mListeners[i]->notifyThrottling(isThrottling, temperature);
+    }
+    return binder::Status::ok();
+}
+
+/**
+ * Query whether the system is currently thermal throttling.
+ * @return true if currently thermal throttling, else false
+ */
+binder::Status ThermalService::isThrottling(bool* _aidl_return) {
+    Mutex::Autolock _l(mListenersLock);
+    *_aidl_return = mThrottled;
+    return binder::Status::ok();
+}
+
+/**
+ * Register a new thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ *                 notifications are to be sent
+ */
+binder::Status ThermalService::registerThermalEventListener(
+    const sp<IThermalEventListener>& listener) {
+    {
+        if (listener == NULL)
+            return binder::Status::ok();
+        Mutex::Autolock _l(mListenersLock);
+        // check whether this is a duplicate
+        for (size_t i = 0; i < mListeners.size(); i++) {
+            if (IInterface::asBinder(mListeners[i]) ==
+                IInterface::asBinder(listener)) {
+                return binder::Status::ok();
+            }
+        }
+
+        mListeners.add(listener);
+        IInterface::asBinder(listener)->linkToDeath(this);
+    }
+
+    return binder::Status::ok();
+}
+
+/**
+ * Unregister a previously-registered thermal event listener.
+ * @param listener the client's IThermalEventListener instance to which
+ *                 notifications are to no longer be sent
+ */
+binder::Status ThermalService::unregisterThermalEventListener(
+    const sp<IThermalEventListener>& listener) {
+    if (listener == NULL)
+        return binder::Status::ok();
+    Mutex::Autolock _l(mListenersLock);
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (IInterface::asBinder(mListeners[i]) ==
+            IInterface::asBinder(listener)) {
+            IInterface::asBinder(mListeners[i])->unlinkToDeath(this);
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+
+    return binder::Status::ok();
+}
+
+void ThermalService::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(mListenersLock);
+
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (IInterface::asBinder(mListeners[i]) == who) {
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+}
+
+/**
+ * Publish the supplied ThermalService to servicemanager.
+ */
+void ThermalService::publish(
+    const sp<ThermalService>& service) {
+    defaultServiceManager()->addService(String16("thermalservice"),
+                                        service);
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/services/thermalservice/ThermalService.h b/services/thermalservice/ThermalService.h
new file mode 100644
index 0000000..17dfcbc
--- /dev/null
+++ b/services/thermalservice/ThermalService.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICE_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICE_H
+
+#include <android/os/BnThermalService.h>
+#include <android/os/IThermalEventListener.h>
+#include <android/os/Temperature.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace os {
+
+class ThermalService : public BnThermalService,
+                       public IBinder::DeathRecipient {
+public:
+  ThermalService() : mThrottled(false) {};
+    void publish(const sp<ThermalService>& service);
+    binder::Status notifyThrottling(
+        const bool isThrottling, const Temperature& temperature);
+
+private:
+    Mutex mListenersLock;
+    Vector<sp<IThermalEventListener> > mListeners;
+    bool mThrottled;
+    Temperature mThrottleTemperature;
+
+    binder::Status registerThermalEventListener(
+        const sp<IThermalEventListener>& listener);
+    binder::Status unregisterThermalEventListener(
+        const sp<IThermalEventListener>& listener);
+    binder::Status isThrottling(bool* _aidl_return);
+    void binderDied(const wp<IBinder>& who);
+};
+
+};  // namespace os
+};  // namespace android
+
+#endif // ANDROID_THERMALSERVICE_THERMALSERVICE_H
diff --git a/services/thermalservice/aidl/android/os/IThermalEventListener.aidl b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
new file mode 100644
index 0000000..050325e
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalEventListener.aidl
@@ -0,0 +1,32 @@
+/**
+ * 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.
+ */
+
+package android.os;
+
+import android.os.Temperature;
+
+/**
+  * Listener for thermal events.
+  * {@hide}
+  */
+oneway interface IThermalEventListener {
+    /**
+     * Called when a thermal throttling start/stop event is received.
+     * @param temperature the temperature at which the event was generated.
+     */
+    void notifyThrottling(
+        in boolean isThrottling, in Temperature temperature);
+}
diff --git a/services/thermalservice/aidl/android/os/IThermalService.aidl b/services/thermalservice/aidl/android/os/IThermalService.aidl
new file mode 100644
index 0000000..e699202
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/IThermalService.aidl
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+package android.os;
+
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+
+/** {@hide} */
+interface IThermalService {
+    /**
+      * Register a listener for thermal events.
+      * @param listener the IThermalEventListener to be notified.
+      * {@hide}
+      */
+    void registerThermalEventListener(in IThermalEventListener listener);
+    /**
+      * Unregister a previously-registered listener for thermal events.
+      * @param listener the IThermalEventListener to no longer be notified.
+      * {@hide}
+      */
+    void unregisterThermalEventListener(in IThermalEventListener listener);
+    /**
+      * Send a thermal throttling start/stop notification to all listeners.
+      * @param temperature the temperature at which the event was generated.
+      * {@hide}
+      */
+    oneway void notifyThrottling(
+        in boolean isThrottling, in Temperature temperature);
+    /**
+      * Return whether system performance is currently thermal throttling.
+      * {@hide}
+      */
+    boolean isThrottling();
+}
diff --git a/services/thermalservice/aidl/android/os/Temperature.aidl b/services/thermalservice/aidl/android/os/Temperature.aidl
new file mode 100644
index 0000000..0293c39
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.aidl
@@ -0,0 +1,5 @@
+package android.os;
+
+/* Encodes a temperature used by ThermalService. */
+
+parcelable Temperature cpp_header "android/os/Temperature.h";
diff --git a/services/thermalservice/aidl/android/os/Temperature.cpp b/services/thermalservice/aidl/android/os/Temperature.cpp
new file mode 100644
index 0000000..df207b7
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "android/os/Temperature.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <binder/Parcel.h>
+#include <hardware/thermal.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+namespace android {
+namespace os {
+
+Temperature::Temperature() : value_(NAN), type_(DEVICE_TEMPERATURE_UNKNOWN) {}
+
+Temperature::Temperature(const float value, const int type) :
+    value_(value), type_(type)  {}
+
+Temperature::~Temperature() {}
+
+/*
+ * Parcel read/write code must be kept in sync with
+ * frameworks/base/core/java/android/os/Temperature.java
+ */
+
+status_t Temperature::readFromParcel(const Parcel* p) {
+    value_ = p->readFloat();
+    type_ = p->readInt32();
+    return OK;
+}
+
+status_t Temperature::writeToParcel(Parcel* p) const {
+    p->writeFloat(value_);
+    p->writeInt32(type_);
+    return OK;
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/services/thermalservice/aidl/android/os/Temperature.h b/services/thermalservice/aidl/android/os/Temperature.h
new file mode 100644
index 0000000..bbc5607
--- /dev/null
+++ b/services/thermalservice/aidl/android/os/Temperature.h
@@ -0,0 +1,33 @@
+#ifndef ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+#define ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+class Temperature : public Parcelable {
+ public:
+
+  Temperature();
+  Temperature(const float value, const int type);
+  ~Temperature() override;
+
+  float getValue() const {return value_;};
+  float getType() const {return type_;};
+
+  status_t writeToParcel(Parcel* parcel) const override;
+  status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+  // The value of the temperature as a float, or NAN if unknown.
+  float value_;
+  // The type of the temperature, an enum temperature_type from
+  // hardware/thermal.h
+  int type_;
+};
+
+}  // namespace os
+}  // namespace android
+
+#endif   // ANDROID_THERMALSERVICE_AIDL_ANDROID_OS_TEMPERATURE_H
diff --git a/services/thermalservice/libthermalcallback/Android.bp b/services/thermalservice/libthermalcallback/Android.bp
new file mode 100644
index 0000000..e98506e
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/Android.bp
@@ -0,0 +1,19 @@
+cc_library_shared {
+    name: "libthermalcallback",
+    srcs: [
+        "ThermalCallback.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    include_dirs: ["frameworks/native"],
+    shared_libs: [
+        "android.hardware.thermal@1.1",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libthermalservice",
+        "libutils",
+    ],
+}
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.cpp b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
new file mode 100644
index 0000000..5e094fa
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.cpp
@@ -0,0 +1,69 @@
+#define LOG_TAG "android.hardware.thermal.thermalcallback@1.1-impl"
+#include <log/log.h>
+
+#include "ThermalCallback.h"
+#include "services/thermalservice/ThermalService.h"
+#include <math.h>
+#include <android/os/Temperature.h>
+#include <hardware/thermal.h>
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::os::ThermalService;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+
+// Register a binder ThermalService object for sending events
+void ThermalCallback::registerThermalService(sp<ThermalService> thermalService)
+{
+    mThermalService = thermalService;
+}
+
+// Methods from IThermalCallback::V1_1 follow.
+Return<void> ThermalCallback::notifyThrottling(
+      bool isThrottling,
+      const android::hardware::thermal::V1_0::Temperature& temperature) {
+
+    // Convert HIDL IThermal Temperature to binder IThermalService Temperature.
+    if (mThermalService != nullptr) {
+        float value = NAN;
+        int type = DEVICE_TEMPERATURE_UNKNOWN;
+
+        switch(temperature.type) {
+          case TemperatureType::CPU:
+            type = DEVICE_TEMPERATURE_CPU;
+            break;
+          case TemperatureType::GPU:
+            type = DEVICE_TEMPERATURE_GPU;
+            break;
+          case TemperatureType::BATTERY:
+            type = DEVICE_TEMPERATURE_BATTERY;
+            break;
+          case TemperatureType::SKIN:
+            type = DEVICE_TEMPERATURE_SKIN;
+            break;
+          case TemperatureType::UNKNOWN:
+          default:
+            type = DEVICE_TEMPERATURE_UNKNOWN;
+            break;
+        }
+
+        value = temperature.currentValue == UNKNOWN_TEMPERATURE ? NAN :
+            temperature.currentValue;
+
+        android::os::Temperature thermal_svc_temp(value, type);
+        mThermalService->notifyThrottling(isThrottling, thermal_svc_temp);
+    } else {
+        ALOGE("IThermalService binder service not created, drop throttling event");
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
diff --git a/services/thermalservice/libthermalcallback/ThermalCallback.h b/services/thermalservice/libthermalcallback/ThermalCallback.h
new file mode 100644
index 0000000..3d72c68
--- /dev/null
+++ b/services/thermalservice/libthermalcallback/ThermalCallback.h
@@ -0,0 +1,43 @@
+#ifndef ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+#define ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+#include <android/os/Temperature.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "services/thermalservice/ThermalService.h"
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::os::ThermalService;
+
+class ThermalCallback : public IThermalCallback {
+ public:
+    // Register a binder ThermalService object for sending events
+    void registerThermalService(sp<ThermalService> thermalService);
+
+    // Methods from IThermalCallback::V1_1 follow.
+    Return<void> notifyThrottling(
+        bool isThrottling,
+        const android::hardware::thermal::V1_0::Temperature& temperature)
+        override;
+
+ private:
+    // Our registered binder ThermalService object to use for sending events
+    sp<android::os::ThermalService> mThermalService;
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
diff --git a/services/thermalservice/thermalservice.rc b/services/thermalservice/thermalservice.rc
new file mode 100644
index 0000000..b9836ce
--- /dev/null
+++ b/services/thermalservice/thermalservice.rc
@@ -0,0 +1,2 @@
+service thermalservice /system/bin/thermalserviced
+    class core
diff --git a/services/thermalservice/thermalserviced.cpp b/services/thermalservice/thermalserviced.cpp
new file mode 100644
index 0000000..b9315b8
--- /dev/null
+++ b/services/thermalservice/thermalserviced.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "thermalserviced"
+#include <log/log.h>
+
+#include "thermalserviced.h"
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+#include <android/hardware/thermal/1.1/IThermal.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
+
+using namespace android;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::os::ThermalService;
+
+template<typename T>
+using Return = hardware::Return<T>;
+
+namespace {
+
+// Our thermalserviced main object
+ThermalServiceDaemon* gThermalServiceDaemon;
+
+// Thermal HAL client
+sp<IThermal> gThermalHal = nullptr;
+
+// Binder death notifier informing of Thermal HAL death.
+struct ThermalServiceDeathRecipient : hidl_death_recipient {
+    virtual void serviceDied(
+        uint64_t cookie __unused, const wp<IBase>& who __unused) {
+        gThermalHal = nullptr;
+        ALOGE("IThermal HAL died");
+        gThermalServiceDaemon->getThermalHal();
+    }
+};
+
+sp<ThermalServiceDeathRecipient> gThermalHalDied = nullptr;
+
+}  // anonymous namespace
+
+void ThermalServiceDaemon::thermalServiceStartup() {
+    // Binder IThermalService startup
+    mThermalService = new android::os::ThermalService;
+    mThermalService->publish(mThermalService);
+    // Register IThermalService object with IThermalCallback
+    if (mThermalCallback != nullptr)
+        mThermalCallback->registerThermalService(mThermalService);
+    IPCThreadState::self()->joinThreadPool();
+}
+
+// Lookup Thermal HAL, register death notifier, register our
+// ThermalCallback with the Thermal HAL.
+void ThermalServiceDaemon::getThermalHal() {
+    gThermalHal = IThermal::getService();
+    if (gThermalHal == nullptr) {
+        ALOGW("Unable to get Thermal HAL V1.1, vendor thermal event notification not available");
+        return;
+    }
+
+    // Binder death notifier for Thermal HAL
+    if (gThermalHalDied == nullptr)
+        gThermalHalDied = new ThermalServiceDeathRecipient();
+
+    if (gThermalHalDied != nullptr)
+        gThermalHal->linkToDeath(gThermalHalDied, 0x451F /* cookie */);
+
+    if (mThermalCallback != nullptr) {
+        Return<void> ret = gThermalHal->registerThermalCallback(
+            mThermalCallback);
+        if (!ret.isOk())
+            ALOGE("registerThermalCallback failed, status: %s",
+                  ret.description().c_str());
+    }
+}
+
+void ThermalServiceDaemon::thermalCallbackStartup() {
+    status_t err;
+
+    // HIDL IThermalCallback startup
+    // Need at least 2 threads in thread pool since we wait for dead HAL
+    // to come back on the binder death notification thread and we need
+    // another thread for the incoming service now available call.
+    configureRpcThreadpool(2, false /* callerWillJoin */);
+    mThermalCallback = new ThermalCallback();
+    err = mThermalCallback->registerAsService();
+    ALOGE_IF(err != OK, "Cannot register %s: %d",
+        IThermalCallback::descriptor, err);
+
+    // Lookup Thermal HAL and register our ThermalCallback.
+    getThermalHal();
+}
+
+int main(int /*argc*/, char** /*argv*/) {
+    gThermalServiceDaemon = new ThermalServiceDaemon();
+    gThermalServiceDaemon->thermalCallbackStartup();
+    gThermalServiceDaemon->thermalServiceStartup();
+    /* NOTREACHED */
+}
diff --git a/services/thermalservice/thermalserviced.h b/services/thermalservice/thermalserviced.h
new file mode 100644
index 0000000..309e2fe
--- /dev/null
+++ b/services/thermalservice/thermalserviced.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_THERMALSERVICE_THERMALSERVICED_H
+#define ANDROID_THERMALSERVICE_THERMALSERVICED_H
+
+#include "ThermalService.h"
+#include "libthermalcallback/ThermalCallback.h"
+
+using namespace android;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
+using ::android::os::ThermalService;
+
+class ThermalServiceDaemon {
+ public:
+    void thermalServiceStartup();
+    void thermalCallbackStartup();
+    void getThermalHal();
+    ThermalServiceDaemon() {};
+
+ private:
+    sp<ThermalService> mThermalService;
+    sp<ThermalCallback> mThermalCallback;
+};
+
+#endif  // ANDROID_THERMALSERVICE_THERMALSERVICED_H
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index 251ed0e..bcfdad3 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -94,9 +94,6 @@
   if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
     return EINVAL;
   }
-  if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
-    return EINVAL;
-  }
   int32_t device_x = x * kWidth;
   int32_t device_y = y * kHeight;
   Touchpad& touchpad = touchpad_[touchpad_id];
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 5f55f19..069fb36 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1095,12 +1095,9 @@
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
         image_native_buffer.usage = int(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);
+        android_convertGralloc0To1Usage(int(img.buffer->usage),
+            &image_native_buffer.usage2.producer,
+            &image_native_buffer.usage2.consumer);
 
         result =
             dispatch.CreateImage(device, &image_create, nullptr, &img.image);