Merge "vulkan: Update Vulkan headers to 1.1.94"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 08218b8..1a932c3 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,6 +4,7 @@
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+               libs/binder/ndk/
                libs/graphicsenv/
                libs/gui/
                libs/renderengine/
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index f4e5b98..5c28c9d 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -9,8 +9,8 @@
     chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
     chmod 0666 /sys/kernel/tracing/events/regulator/enable
     chmod 0666 /sys/kernel/debug/tracing/events/regulator/enable
-    chmod 0666 /sys/kernel/tracing/events/pagecache/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/pagecache/enable
+    chmod 0666 /sys/kernel/tracing/events/filemap/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
 
     # irq
     chmod 0666 /sys/kernel/tracing/events/irq/enable
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 0ee6c3a..849eb44 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -108,7 +108,8 @@
         bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
         bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
         bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
-        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI) {
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI &&
+        bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_DEFAULT) {
         return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
                          StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
     }
@@ -137,6 +138,7 @@
     dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str());
     dprintf(fd, "version: %s\n", ds_.version_.c_str());
     dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str());
+    dprintf(fd, "bugreport_internal_dir_: %s\n", ds_.bugreport_internal_dir_.c_str());
     dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str());
     dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str());
     dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str());
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 9e59f58..617eab3 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -40,7 +40,7 @@
                                 boolean getSectionDetails);
 
     // These modes encapsulate a set of run time options for generating bugreports.
-    // A zipped bugreport; default mode.
+    // Takes a bugreport without user interference.
     const int BUGREPORT_MODE_FULL = 0;
 
     // Interactive bugreport, i.e. triggered by the user.
@@ -58,6 +58,9 @@
     // Bugreport limited to only wifi info.
     const int BUGREPORT_MODE_WIFI = 5;
 
+    // Default mode.
+    const int BUGREPORT_MODE_DEFAULT = 6;
+
     /*
      * Starts a bugreport in the background.
      */
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index df80651..2c93832 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -82,6 +82,7 @@
 using android::TIMED_OUT;
 using android::UNKNOWN_ERROR;
 using android::Vector;
+using android::base::StringPrintf;
 using android::os::dumpstate::CommandOptions;
 using android::os::dumpstate::DumpFileToFd;
 using android::os::dumpstate::DumpstateSectionReporter;
@@ -121,6 +122,69 @@
 
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
+
+namespace android {
+namespace os {
+namespace {
+
+static int Open(std::string path, int flags, mode_t mode = 0) {
+    int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
+    if (fd == -1) {
+        MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
+    }
+    return fd;
+}
+
+static int OpenForWrite(std::string path) {
+    return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+                S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+}
+
+static int OpenForRead(std::string path) {
+    return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+}
+
+bool CopyFile(int in_fd, int out_fd) {
+    char buf[4096];
+    ssize_t byte_count;
+    while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
+        if (!android::base::WriteFully(out_fd, buf, byte_count)) {
+            return false;
+        }
+    }
+    return (byte_count != -1);
+}
+
+static bool CopyFileToFd(const std::string& input_file, int out_fd) {
+    MYLOGD("Going to copy bugreport file (%s) to %d\n", ds.path_.c_str(), out_fd);
+
+    // Obtain a handle to the source file.
+    android::base::unique_fd in_fd(OpenForRead(input_file));
+    if (out_fd != -1 && in_fd.get() != -1) {
+        if (CopyFile(in_fd.get(), out_fd)) {
+            return true;
+        }
+        MYLOGE("Failed to copy zip file: %s\n", strerror(errno));
+    }
+    return false;
+}
+
+static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
+    if (input_file == output_file) {
+        MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
+               output_file.c_str());
+        return false;
+    }
+
+    MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
+    android::base::unique_fd out_fd(OpenForWrite(output_file));
+    return CopyFileToFd(input_file, out_fd.get());
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace android
+
 static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
                       const CommandOptions& options = CommandOptions::DEFAULT) {
     return ds.RunCommand(title, fullCommand, options);
@@ -137,8 +201,6 @@
 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
 static const std::string ZIP_ROOT_DIR = "FS";
 
-// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
-static const std::string kDumpstateBoardPath = "/bugreports/";
 static const std::string kProtoPath = "proto/";
 static const std::string kProtoExt = ".proto";
 static const std::string kDumpstateBoardFiles[] = {
@@ -1145,7 +1207,7 @@
                                 return !isalnum(c) &&
                                     std::string("@-_:.").find(c) == std::string::npos;
                             }, '_');
-            const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
+            const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
 
             {
                 auto fd = android::base::unique_fd(
@@ -1529,7 +1591,8 @@
     std::vector<std::string> paths;
     std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
     for (int i = 0; i < NUM_OF_DUMPS; i++) {
-        paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
+        paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
+                                        kDumpstateBoardFiles[i].c_str()));
         remover.emplace_back(android::base::make_scope_guard(std::bind(
             [](std::string path) {
                 if (remove(path.c_str()) != 0 && errno != ENOENT) {
@@ -1687,7 +1750,8 @@
         MYLOGE("Failed to add dumpstate log to .zip file\n");
         return false;
     }
-    // ... and re-opens it for further logging.
+    // TODO: Should truncate the existing file.
+    // ... and re-open it for further logging.
     redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
     fprintf(stderr, "\n");
 
@@ -1770,17 +1834,30 @@
     // clang-format on
 }
 
+static void MaybeResolveSymlink(std::string* path) {
+    std::string resolved_path;
+    if (android::base::Readlink(*path, &resolved_path)) {
+        *path = resolved_path;
+    }
+}
+
 /*
  * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
  * if we are writing zip files and adds the version file.
  */
 static void PrepareToWriteToFile() {
-    ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
+    MaybeResolveSymlink(&ds.bugreport_internal_dir_);
+
+    std::string base_name_part1 = "bugreport";
+    if (!ds.options_->use_outfile.empty()) {
+        ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str());
+        base_name_part1 = basename(ds.options_->use_outfile.c_str());
+    }
+
     std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
     std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
     ds.base_name_ =
-        android::base::StringPrintf("%s-%s-%s", basename(ds.options_->use_outfile.c_str()),
-                                    device_name.c_str(), build_id.c_str());
+        StringPrintf("%s-%s-%s", base_name_part1.c_str(), device_name.c_str(), build_id.c_str());
     if (ds.options_->do_add_date) {
         char date[80];
         strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
@@ -1801,15 +1878,18 @@
     ds.tmp_path_ = ds.GetPath(".tmp");
     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
 
+    std::string destination = ds.options_->fd != -1 ? StringPrintf("[fd:%d]", ds.options_->fd)
+                                                    : ds.bugreport_dir_.c_str();
     MYLOGD(
         "Bugreport dir: %s\n"
+        "Internal Bugreport dir: %s\n"
         "Base name: %s\n"
         "Suffix: %s\n"
         "Log path: %s\n"
         "Temporary path: %s\n"
         "Screenshot path: %s\n",
-        ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
-        ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
+        destination.c_str(), ds.bugreport_internal_dir_.c_str(), ds.base_name_.c_str(),
+        ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
 
     if (ds.options_->do_zip_file) {
         ds.path_ = ds.GetPath(".zip");
@@ -1875,6 +1955,19 @@
                     ds.path_ = new_path;
                 }
             }
+            // The zip file lives in an internal directory. Copy it over to output.
+            bool copy_succeeded = false;
+            if (ds.options_->fd != -1) {
+                copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->fd);
+            } else {
+                ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
+                copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
+            }
+            if (copy_succeeded) {
+                if (remove(ds.path_.c_str())) {
+                    MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno));
+                }
+            }
         }
     }
     if (do_text_file) {
@@ -1899,8 +1992,9 @@
 
 /* Broadcasts that we are done with the bugreport */
 static void SendBugreportFinishedBroadcast() {
-    if (!ds.path_.empty()) {
-        MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
+    // TODO(b/111441001): use callback instead of broadcast.
+    if (!ds.final_path_.empty()) {
+        MYLOGI("Final bugreport path: %s\n", ds.final_path_.c_str());
         // clang-format off
 
         std::vector<std::string> am_args = {
@@ -1908,7 +2002,7 @@
              "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
              "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
              "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
-             "--es", "android.intent.extra.BUGREPORT", ds.path_,
+             "--es", "android.intent.extra.BUGREPORT", ds.final_path_,
              "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
         };
         // clang-format on
@@ -1930,7 +2024,7 @@
         if (ds.options_->is_remote_mode) {
             am_args.push_back("--es");
             am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
-            am_args.push_back(SHA256_file_hash(ds.path_));
+            am_args.push_back(SHA256_file_hash(ds.final_path_));
             SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
         } else {
             SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
@@ -1954,6 +2048,8 @@
             return "BUGREPORT_TELEPHONY";
         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
             return "BUGREPORT_WIFI";
+        case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+            return "BUGREPORT_DEFAULT";
     }
 }
 
@@ -1994,12 +2090,14 @@
             options->do_fb = true;
             options->do_broadcast = true;
             break;
+        case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
+            break;
     }
 }
 
 static Dumpstate::BugreportMode getBugreportModeFromProperty() {
-    // If the system property is not set, it's assumed to be a full bugreport.
-    Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
+    // If the system property is not set, it's assumed to be a default bugreport.
+    Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
 
     std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
     if (!extra_options.empty()) {
@@ -2007,6 +2105,8 @@
         // Currently, it contains the type of the requested bugreport.
         if (extra_options == "bugreportplus") {
             mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
+        } else if (extra_options == "bugreportfull") {
+            mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
         } else if (extra_options == "bugreportremote") {
             mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
         } else if (extra_options == "bugreportwear") {
@@ -2060,6 +2160,7 @@
     MYLOGI("telephony_only: %d\n", options.telephony_only);
     MYLOGI("wifi_only: %d\n", options.wifi_only);
     MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
+    MYLOGI("fd: %d\n", options.fd);
     MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
     MYLOGI("extra_options: %s\n", options.extra_options.c_str());
     MYLOGI("args: %s\n", options.args.c_str());
@@ -2125,8 +2226,13 @@
 }
 
 bool Dumpstate::DumpOptions::ValidateOptions() const {
-    if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast)
-            && use_outfile.empty()) {
+    if (fd != -1 && !do_zip_file) {
+        return false;
+    }
+
+    bool has_out_file_options = !use_outfile.empty() || fd != -1;
+    if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
+        !has_out_file_options) {
         return false;
     }
 
@@ -2148,10 +2254,31 @@
     options_ = std::move(options);
 }
 
+/*
+ * Dumps relevant information to a bugreport based on the given options.
+ *
+ * The bugreport can be dumped to a file or streamed to a socket.
+ *
+ * How dumping to file works:
+ * stdout is redirected to a temporary file. This will later become the main bugreport entry.
+ * stderr is redirected a log file.
+ *
+ * The temporary bugreport is then populated via printfs, dumping contents of files and
+ * output of commands to stdout.
+ *
+ * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
+ * text file.
+ *
+ * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
+ * gets added to the archive.
+ *
+ * Bugreports are first generated in a local directory and later copied to the caller's fd or
+ * directory.
+ */
 Dumpstate::RunStatus Dumpstate::Run() {
+    LogDumpOptions(*options_);
     if (!options_->ValidateOptions()) {
         MYLOGE("Invalid options specified\n");
-        LogDumpOptions(*options_);
         return RunStatus::INVALID_INPUT;
     }
     /* set as high priority, and protect from OOM killer */
@@ -2191,9 +2318,9 @@
 
     // TODO: temporarily set progress until it's part of the Dumpstate constructor
     std::string stats_path =
-        is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt",
-                                                     dirname(options_->use_outfile.c_str()))
-                       : "";
+        is_redirecting
+            ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
+            : "";
     progress_.reset(new Progress(stats_path));
 
     /* gets the sequential id */
@@ -2289,13 +2416,18 @@
     int dup_stdout_fd;
     int dup_stderr_fd;
     if (is_redirecting) {
+        // Redirect stderr to log_path_ for debugging.
         TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
         redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()));
         if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
                    strerror(errno));
         }
+
+        // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
+        // moved into zip file later, if zipping.
         TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
+        // TODO: why not write to a file instead of stdout to overcome this problem?
         /* TODO: rather than generating a text file now and zipping it later,
            it would be more efficient to redirect stdout to the zip entry
            directly, but the libziparchive doesn't support that option yet. */
@@ -2370,7 +2502,7 @@
     return RunStatus::OK;
 }
 
-/* Main entry point for dumpstate. */
+/* Main entry point for dumpstate binary. */
 int run_main(int argc, char* argv[]) {
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
     Dumpstate::RunStatus status = options->Initialize(argc, argv);
@@ -2382,7 +2514,7 @@
     switch (status) {
         case Dumpstate::RunStatus::OK:
             return 0;
-            break;
+            // TODO(b/111441001): Exit directly in the following cases.
         case Dumpstate::RunStatus::HELP:
             ShowUsageAndExit(0 /* exit code */);
             break;
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 35cbdb1..ee952d9 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -142,7 +142,7 @@
     float growth_factor_;
     int32_t n_runs_;
     int32_t average_max_;
-    const std::string& path_;
+    std::string path_;
 };
 
 /*
@@ -164,6 +164,11 @@
 static std::string VERSION_DEFAULT = "default";
 
 /*
+ * Directory used by Dumpstate binary to keep its local files.
+ */
+static const std::string DUMPSTATE_DIRECTORY = "/bugreports";
+
+/*
  * Structure that contains the information of an open dump file.
  */
 struct DumpData {
@@ -196,7 +201,8 @@
         BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE,
         BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR,
         BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY,
-        BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI
+        BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI,
+        BUGREPORT_DEFAULT = android::os::IDumpstate::BUGREPORT_MODE_DEFAULT
     };
 
     static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS;
@@ -300,7 +306,11 @@
      */
     bool FinishZipFile();
 
-    /* Gets the path of a bugreport file with the given suffix. */
+    /* Constructs a full path inside directory with file name formatted using the given suffix. */
+    std::string GetPath(const std::string& directory, const std::string& suffix) const;
+
+    /* Constructs a full path inside bugreport_internal_dir_ with file name formatted using the
+     * given suffix. */
     std::string GetPath(const std::string& suffix) const;
 
     /* Returns true if the current version supports priority dump feature. */
@@ -314,7 +324,6 @@
     /* Sets runtime options. */
     void SetOptions(std::unique_ptr<DumpOptions> options);
 
-    // TODO: add other options from DumpState.
     /*
      * Structure to hold options that determine the behavior of dumpstate.
      */
@@ -333,6 +342,10 @@
         bool wifi_only = false;
         // Whether progress updates should be published.
         bool do_progress_updates = false;
+        // File descriptor to output zip file. -1 indicates not set. Takes precedence over
+        // use_outfile.
+        int fd = -1;
+        // Partial path to output file.
         std::string use_outfile;
         // TODO: rename to MODE.
         // Extra options passed as system property.
@@ -381,12 +394,6 @@
     // Bugreport format version;
     std::string version_ = VERSION_CURRENT;
 
-    // Full path of the directory where the bugreport files will be written.
-    std::string bugreport_dir_;
-
-    // Full path of the temporary file containing the screenshot (when requested).
-    std::string screenshot_path_;
-
     time_t now_;
 
     // Base name (without suffix or extensions) of the bugreport files, typically
@@ -397,15 +404,30 @@
     // `-d`), but it could be changed by the user..
     std::string name_;
 
-    // Full path of the temporary file containing the bugreport.
+    std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY;
+
+    // Full path of the temporary file containing the bugreport, inside bugreport_internal_dir_.
+    // At the very end this file is pulled into the zip file.
     std::string tmp_path_;
 
-    // Full path of the file containing the dumpstate logs.
+    // Full path of the file containing the dumpstate logs, inside bugreport_internal_dir_.
+    // This is useful for debugging.
     std::string log_path_;
 
-    // Pointer to the actual path, be it zip or text.
+    // Full path of the bugreport file, be it zip or text, inside bugreport_internal_dir_.
     std::string path_;
 
+    // TODO: If temporary this should be removed at the end.
+    // Full path of the temporary file containing the screenshot (when requested).
+    std::string screenshot_path_;
+
+    // TODO(b/111441001): remove when obsolete.
+    // Full path of the final zip file inside the caller-specified directory, if available.
+    std::string final_path_;
+
+    // The caller-specified directory, if available.
+    std::string bugreport_dir_;
+
     // Pointer to the zipped file.
     std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose};
 
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 9ca894d..fcf9371 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -36,6 +36,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <cutils/properties.h>
 
 namespace android {
 namespace os {
@@ -148,7 +149,10 @@
     virtual void SetUp() {
         options_ = Dumpstate::DumpOptions();
     }
-
+    void TearDown() {
+        // Reset the property
+        property_set("dumpstate.options", "");
+    }
     Dumpstate::DumpOptions options_;
 };
 
@@ -163,7 +167,6 @@
 
     EXPECT_EQ(status, Dumpstate::RunStatus::OK);
 
-    // These correspond to bugreport_mode = full, because that's the default.
     EXPECT_FALSE(options_.do_add_date);
     EXPECT_FALSE(options_.do_zip_file);
     EXPECT_EQ("", options_.use_outfile);
@@ -171,10 +174,295 @@
     EXPECT_FALSE(options_.use_control_socket);
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_TRUE(options_.do_fb);
+    EXPECT_FALSE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.do_broadcast);
+}
+
+TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstatez"),
+        const_cast<char*>("-S"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.use_control_socket);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_fb);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.do_broadcast);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate"),
+        const_cast<char*>("-s"),
+    };
+    // clang-format on
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.use_socket);
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_EQ("", options_.use_outfile);
+    EXPECT_FALSE(options_.do_add_date);
+    EXPECT_FALSE(options_.do_zip_file);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_fb);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.do_broadcast);
+}
+
+TEST_F(DumpOptionsTest, InitializeFullBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+    property_set("dumpstate.options", "bugreportfull");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_fb);
+    EXPECT_TRUE(options_.do_zip_file);
     EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.do_start_service);
+}
+
+TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "bugreportplus");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.do_progress_updates);
+    EXPECT_TRUE(options_.do_start_service);
+    EXPECT_FALSE(options_.do_fb);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "bugreportremote");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.do_vibrate);
+    EXPECT_FALSE(options_.do_fb);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeWearBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "bugreportwear");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_fb);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.do_progress_updates);
+    EXPECT_TRUE(options_.do_start_service);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "bugreporttelephony");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_fb);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.telephony_only);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "bugreportwifi");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_fb);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.wifi_only);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+}
+
+TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
+    // default: commandline options are not overridden
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("bugreport"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-B"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+    };
+    // clang-format on
+
+    property_set("dumpstate.options", "");
+
+    Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
+
+    EXPECT_EQ(status, Dumpstate::RunStatus::OK);
+    EXPECT_TRUE(options_.do_add_date);
+    EXPECT_TRUE(options_.do_fb);
+    EXPECT_TRUE(options_.do_zip_file);
+    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_EQ(" abc", std::string(options_.use_outfile));
+
+    // Other options retain default values
+    EXPECT_TRUE(options_.do_vibrate);
+    EXPECT_FALSE(options_.use_control_socket);
+    EXPECT_FALSE(options_.show_header_only);
+    EXPECT_FALSE(options_.do_progress_updates);
+    EXPECT_FALSE(options_.is_remote_mode);
+    EXPECT_FALSE(options_.use_socket);
+    EXPECT_FALSE(options_.wifi_only);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial1) {
@@ -203,10 +491,10 @@
     // Other options retain default values
     EXPECT_FALSE(options_.show_header_only);
     EXPECT_TRUE(options_.do_vibrate);
-    EXPECT_TRUE(options_.do_fb);
+    EXPECT_FALSE(options_.do_fb);
     EXPECT_FALSE(options_.do_progress_updates);
     EXPECT_FALSE(options_.is_remote_mode);
-    EXPECT_TRUE(options_.do_broadcast);
+    EXPECT_FALSE(options_.do_broadcast);
 }
 
 TEST_F(DumpOptionsTest, InitializePartial2) {
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 6cbb691..d97ffbf 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -229,7 +229,11 @@
 }
 
 std::string Dumpstate::GetPath(const std::string& suffix) const {
-    return android::base::StringPrintf("%s/%s-%s%s", bugreport_dir_.c_str(), base_name_.c_str(),
+    return GetPath(bugreport_internal_dir_, suffix);
+}
+
+std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
+    return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
                                        name_.c_str(), suffix.c_str());
 }
 
diff --git a/data/etc/android.software.ipsec_tunnels.xml b/data/etc/android.software.ipsec_tunnels.xml
new file mode 100644
index 0000000..f7ffc02
--- /dev/null
+++ b/data/etc/android.software.ipsec_tunnels.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!--
+     This is the feature indicating that the device has support for multinetworking-capable IPsec
+     tunnels
+-->
+
+<permissions>
+    <feature name="android.software.ipsec_tunnels" />
+</permissions>
diff --git a/headers/media_plugin/media/openmax/OMX_AsString.h b/headers/media_plugin/media/openmax/OMX_AsString.h
index dc25ded..8e75b54 100644
--- a/headers/media_plugin/media/openmax/OMX_AsString.h
+++ b/headers/media_plugin/media/openmax/OMX_AsString.h
@@ -188,7 +188,9 @@
 inline static const char *asString(OMX_AUDIO_CODINGEXTTYPE i, const char *def = "??") {
     switch (i) {
         case OMX_AUDIO_CodingAndroidAC3:  return "AndroidAC3";
+        case OMX_AUDIO_CodingAndroidEAC3: return "AndroidEAC3";
         case OMX_AUDIO_CodingAndroidOPUS: return "AndroidOPUS";
+        case OMX_AUDIO_CodingAndroidAC4:  return "AndroidAC4";
         default:                          return asString((OMX_AUDIO_CODINGTYPE)i, def);
     }
 }
@@ -536,6 +538,7 @@
         case OMX_IndexParamAudioAndroidOpus:            return "ParamAudioAndroidOpus";
         case OMX_IndexParamAudioAndroidAacPresentation: return "ParamAudioAndroidAacPresentation";
         case OMX_IndexParamAudioAndroidEac3:            return "ParamAudioAndroidEac3";
+        case OMX_IndexParamAudioAndroidAc4:             return "ParamAudioAndroidAc4";
         case OMX_IndexParamAudioProfileQuerySupported:  return "ParamAudioProfileQuerySupported";
 //      case OMX_IndexParamNalStreamFormatSupported:    return "ParamNalStreamFormatSupported";
 //      case OMX_IndexParamNalStreamFormat:             return "ParamNalStreamFormat";
diff --git a/headers/media_plugin/media/openmax/OMX_AudioExt.h b/headers/media_plugin/media/openmax/OMX_AudioExt.h
index 8409553..1ea740f 100644
--- a/headers/media_plugin/media/openmax/OMX_AudioExt.h
+++ b/headers/media_plugin/media/openmax/OMX_AudioExt.h
@@ -48,6 +48,7 @@
     OMX_AUDIO_CodingAndroidAC3,         /**< AC3 encoded data */
     OMX_AUDIO_CodingAndroidOPUS,        /**< OPUS encoded data */
     OMX_AUDIO_CodingAndroidEAC3,        /**< EAC3 encoded data */
+    OMX_AUDIO_CodingAndroidAC4,         /**< AC4 encoded data */
 } OMX_AUDIO_CODINGEXTTYPE;
 
 typedef struct OMX_AUDIO_PARAM_ANDROID_AC3TYPE {
@@ -68,6 +69,15 @@
                                         variable or unknown sampling rate. */
 } OMX_AUDIO_PARAM_ANDROID_EAC3TYPE;
 
+typedef struct OMX_AUDIO_PARAM_ANDROID_AC4TYPE {
+    OMX_U32 nSize;                 /**< size of the structure in bytes */
+    OMX_VERSIONTYPE nVersion;      /**< OMX specification version information */
+    OMX_U32 nPortIndex;            /**< port that this structure applies to */
+    OMX_U32 nChannels;             /**< Number of channels */
+    OMX_U32 nSampleRate;           /**< Sampling rate of the source data.  Use 0 for
+                                        variable or unknown sampling rate. */
+} OMX_AUDIO_PARAM_ANDROID_AC4TYPE;
+
 typedef struct OMX_AUDIO_PARAM_ANDROID_OPUSTYPE {
     OMX_U32 nSize;            /**< size of the structure in bytes */
     OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
diff --git a/headers/media_plugin/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h
index 716d959..9fc3ef3 100644
--- a/headers/media_plugin/media/openmax/OMX_IndexExt.h
+++ b/headers/media_plugin/media/openmax/OMX_IndexExt.h
@@ -64,6 +64,7 @@
     OMX_IndexParamAudioAndroidEac3,                 /**< reference: OMX_AUDIO_PARAM_ANDROID_EAC3TYPE */
     OMX_IndexParamAudioProfileQuerySupported,       /**< reference: OMX_AUDIO_PARAM_ANDROID_PROFILETYPE */
     OMX_IndexParamAudioAndroidAacDrcPresentation,   /**< reference: OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE */
+    OMX_IndexParamAudioAndroidAc4,                  /**< reference: OMX_AUDIO_PARAM_ANDROID_AC4TYPE */
     OMX_IndexExtAudioEndUnused,
 
     /* Image parameters and configurations */
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index c6fcaa4..ff1860e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -163,9 +163,7 @@
     ScopedAResource& operator=(ScopedAResource&&) = delete;
 
     // move-constructing is okay
-    ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) {
-      other.mT = DEFAULT;
-    }
+    ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
 
    private:
     T mT;
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index c2a6764..dfdda0c 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -135,8 +135,8 @@
 }
 
 void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
-                               bool developerOptIn, const int rulesFd, const long rulesOffset,
-                               const long rulesLength) {
+                               const std::string developerOptIn, const int rulesFd,
+                               const long rulesOffset, const long rulesLength) {
     if (!mAnglePath.empty()) {
         ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
               path.c_str());
@@ -153,7 +153,13 @@
         mAngleAppName = appName;
     }
 
-    mAngleDeveloperOptIn = developerOptIn;
+    if (!mAngleDeveloperOptIn.empty()) {
+        ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'",
+              mAngleDeveloperOptIn.c_str(), developerOptIn.c_str());
+    } else {
+        ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
+        mAngleDeveloperOptIn = developerOptIn;
+    }
 
     ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd);
     mAngleRulesFd = rulesFd;
@@ -182,8 +188,8 @@
     return mAngleAppName.c_str();
 }
 
-bool GraphicsEnv::getAngleDeveloperOptIn() {
-    return mAngleDeveloperOptIn;
+const char* GraphicsEnv::getAngleDeveloperOptIn() {
+    return mAngleDeveloperOptIn.c_str();
 }
 
 int GraphicsEnv::getAngleRulesFd() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 20e4d66..4ec53f1 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -44,12 +44,12 @@
     // (libraries must be stored uncompressed and page aligned); such elements
     // in the search path must have a '!' after the zip filename, e.g.
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
-    void setAngleInfo(const std::string path, const std::string appName, bool devOptIn,
+    void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
                       const int rulesFd, const long rulesOffset, const long rulesLength);
     android_namespace_t* getAngleNamespace();
     const char* getAngleAppName();
     const char* getAngleAppPref();
-    bool getAngleDeveloperOptIn();
+    const char* getAngleDeveloperOptIn();
     int getAngleRulesFd();
     long getAngleRulesOffset();
     long getAngleRulesLength();
@@ -69,7 +69,7 @@
     std::string mDriverPath;
     std::string mAnglePath;
     std::string mAngleAppName;
-    bool mAngleDeveloperOptIn;
+    std::string mAngleDeveloperOptIn;
     int mAngleRulesFd;
     long mAngleRulesOffset;
     long mAngleRulesLength;
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index 8af1a67..e64ba9b 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -901,7 +901,7 @@
     int const* constFds = static_cast<int const*>(baseFds.get());
     numFds = baseNumFds;
     if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
-        for (auto nhA : nhAA) {
+        for (const auto& nhA : nhAA) {
             for (auto nh : nhA) {
                 if (nh != nullptr) {
                     native_handle_close(nh);
@@ -912,8 +912,8 @@
         return false;
     }
 
-    for (auto nhA : nhAA) {
-        for (auto nh : nhA) {
+    for (const auto& nhA : nhAA) {
+        for (const auto& nh : nhA) {
             if (nh != nullptr) {
                 native_handle_delete(nh);
             }
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d37b810..67afbd6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -207,7 +207,7 @@
 }
 
 TEST_F(SurfaceTest, QueryDefaultBuffersDataSpace) {
-    const android_dataspace TEST_DATASPACE = HAL_DATASPACE_SRGB;
+    const android_dataspace TEST_DATASPACE = HAL_DATASPACE_V0_SRGB;
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
     BufferQueue::createBufferQueue(&producer, &consumer);
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index e747ee1..3816c1b 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -61,6 +61,16 @@
 // to use Binder.
 static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
 
+using dvr::BufferHubDefs::AnyClientAcquired;
+using dvr::BufferHubDefs::AnyClientGained;
+using dvr::BufferHubDefs::AnyClientPosted;
+using dvr::BufferHubDefs::IsClientAcquired;
+using dvr::BufferHubDefs::IsClientGained;
+using dvr::BufferHubDefs::IsClientPosted;
+using dvr::BufferHubDefs::IsClientReleased;
+using dvr::BufferHubDefs::kHighBitsMask;
+using dvr::BufferHubDefs::kMetadataHeaderSize;
+
 } // namespace
 
 BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
@@ -71,7 +81,7 @@
 BufferHubClient::~BufferHubClient() {}
 
 bool BufferHubClient::IsValid() const {
-  return IsConnected() && GetChannelHandle().valid();
+    return IsConnected() && GetChannelHandle().valid();
 }
 
 LocalChannelHandle BufferHubClient::TakeChannelHandle() {
@@ -151,11 +161,17 @@
     }
 
     size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
-    if (metadataSize < dvr::BufferHubDefs::kMetadataHeaderSize) {
+    if (metadataSize < kMetadataHeaderSize) {
         ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata too small: %zu", metadataSize);
         return -EINVAL;
     }
 
+    // Populate shortcuts to the atomics in metadata.
+    auto metadata_header = mMetadata.metadata_header();
+    buffer_state_ = &metadata_header->buffer_state;
+    fence_state_ = &metadata_header->fence_state;
+    active_clients_bit_mask_ = &metadata_header->active_clients_bit_mask;
+
     // Import the buffer: We only need to hold on the native_handle_t here so that
     // GraphicBuffer instance can be created in future.
     mBufferHandle = bufferTraits.take_buffer_handle();
@@ -176,7 +192,93 @@
 
     // TODO(b/112012161) Set up shared fences.
     ALOGD("BufferHubBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64 ".", id(),
-          mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire));
+          buffer_state_->load(std::memory_order_acquire));
+    return 0;
+}
+
+int BufferHubBuffer::Gain() {
+    uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+    if (IsClientGained(current_buffer_state, mClientStateMask)) {
+        ALOGV("%s: Buffer is already gained by this client %" PRIx64 ".", __FUNCTION__,
+              mClientStateMask);
+        return 0;
+    }
+    do {
+        if (AnyClientGained(current_buffer_state & (~mClientStateMask)) ||
+            AnyClientAcquired(current_buffer_state)) {
+            ALOGE("%s: Buffer is in use, id=%d mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+                  __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+            return -EBUSY;
+        }
+        // Change the buffer state to gained state, whose value happens to be the same as
+        // mClientStateMask.
+    } while (!buffer_state_->compare_exchange_weak(current_buffer_state, mClientStateMask,
+                                                   std::memory_order_acq_rel,
+                                                   std::memory_order_acquire));
+    // TODO(b/119837586): Update fence state and return GPU fence.
+    return 0;
+}
+
+int BufferHubBuffer::Post() {
+    uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+    uint64_t current_active_clients_bit_mask = 0ULL;
+    uint64_t updated_buffer_state = 0ULL;
+    do {
+        if (!IsClientGained(current_buffer_state, mClientStateMask)) {
+            ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
+                  "mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+                  __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+            return -EBUSY;
+        }
+        // Set the producer client buffer state to released, other clients' buffer state to posted.
+        current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire);
+        updated_buffer_state =
+                current_active_clients_bit_mask & (~mClientStateMask) & kHighBitsMask;
+    } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+                                                   std::memory_order_acq_rel,
+                                                   std::memory_order_acquire));
+    // TODO(b/119837586): Update fence state and return GPU fence if needed.
+    return 0;
+}
+
+int BufferHubBuffer::Acquire() {
+    uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+    if (IsClientAcquired(current_buffer_state, mClientStateMask)) {
+        ALOGV("%s: Buffer is already acquired by this client %" PRIx64 ".", __FUNCTION__,
+              mClientStateMask);
+        return 0;
+    }
+    uint64_t updated_buffer_state = 0ULL;
+    do {
+        if (!IsClientPosted(current_buffer_state, mClientStateMask)) {
+            ALOGE("%s: Cannot acquire a buffer that is not in posted state. buffer_id=%d "
+                  "mClientStateMask=%" PRIx64 " state=%" PRIx64 ".",
+                  __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+            return -EBUSY;
+        }
+        // Change the buffer state for this consumer from posted to acquired.
+        updated_buffer_state = current_buffer_state ^ mClientStateMask;
+    } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+                                                   std::memory_order_acq_rel,
+                                                   std::memory_order_acquire));
+    // TODO(b/119837586): Update fence state and return GPU fence.
+    return 0;
+}
+
+int BufferHubBuffer::Release() {
+    uint64_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
+    if (IsClientReleased(current_buffer_state, mClientStateMask)) {
+        ALOGV("%s: Buffer is already released by this client %" PRIx64 ".", __FUNCTION__,
+              mClientStateMask);
+        return 0;
+    }
+    uint64_t updated_buffer_state = 0ULL;
+    do {
+        updated_buffer_state = current_buffer_state & (~mClientStateMask);
+    } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
+                                                   std::memory_order_acq_rel,
+                                                   std::memory_order_acquire));
+    // TODO(b/119837586): Update fence state and return GPU fence if needed.
     return 0;
 }
 
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 37cf617..20f27c5 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -42,9 +42,6 @@
         for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
             bits = bits | bit;
         }
-        // TODO(b/72323293, b/72703005): Remove these additional bits
-        bits = bits | (1 << 10) | (1 << 13);
-
         return bits;
     }();
     return valid10UsageBits;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index a2f1783..f56e6b9 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -101,6 +101,9 @@
     if (layerCount < 1)
         layerCount = 1;
 
+    // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
+    usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
+
     Gralloc2::IMapper::BufferDescriptorInfo info = {};
     info.width = width;
     info.height = height;
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 6850b43..03d10e7 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -103,6 +103,27 @@
     // to read from and/or write into.
     bool IsValid() const { return mBufferHandle.IsValid(); }
 
+    // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
+    // gained.
+    // The buffer can be gained as long as there is no other client in acquired or gained state.
+    int Gain();
+
+    // Posts the gained buffer for other buffer clients to use the buffer.
+    // The buffer can be posted iff the buffer state for this client is gained.
+    // After posting the buffer, this client is put to released state and does not have access to
+    // the buffer for this cycle of the usage of the buffer.
+    int Post();
+
+    // Acquires the buffer for shared read permission.
+    // The buffer can be acquired iff the buffer state for this client is posted.
+    int Acquire();
+
+    // Releases the buffer.
+    // The buffer can be released from any buffer state.
+    // After releasing the buffer, this client no longer have any permissions to the buffer for the
+    // current cycle of the usage of the buffer.
+    int Release();
+
     // Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
     // all possible bits).
     pdx::Status<int> GetEventMask(int events) {
@@ -130,6 +151,9 @@
 
     // Global id for the buffer that is consistent across processes.
     int mId = -1;
+
+    // Client state mask of this BufferHubBuffer object. It is unique amoung all
+    // clients/users of the buffer.
     uint64_t mClientStateMask = 0;
 
     // Stores ground truth of the buffer.
@@ -141,6 +165,10 @@
     // An ashmem-based metadata object. The same shared memory are mapped to the
     // bufferhubd daemon and all buffer clients.
     BufferHubMetadata mMetadata;
+    // Shortcuts to the atomics inside the header of mMetadata.
+    std::atomic<uint64_t>* buffer_state_{nullptr};
+    std::atomic<uint64_t>* fence_state_{nullptr};
+    std::atomic<uint64_t>* active_clients_bit_mask_{nullptr};
 
     // PDX backend.
     BufferHubClient mClient;
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index fcc6d37..18bbb3e 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -74,7 +74,12 @@
 cc_test {
     name: "BufferHubMetadata_test",
     header_libs: ["libbufferhub_headers", "libdvr_headers"],
-    shared_libs: ["libpdx_default_transport", "libui", "libutils"],
+    shared_libs: [
+        "libbase",
+        "libpdx_default_transport",
+        "libui",
+        "libutils",
+    ],
     srcs: ["BufferHubMetadata_test.cpp"],
     cflags: ["-Wall", "-Werror"],
 }
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 6c7d06b..e33acf6 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -36,7 +36,14 @@
 const int kUsage = 0;
 const size_t kUserMetadataSize = 0;
 
+using dvr::BufferHubDefs::AnyClientAcquired;
+using dvr::BufferHubDefs::AnyClientGained;
+using dvr::BufferHubDefs::AnyClientPosted;
 using dvr::BufferHubDefs::IsBufferReleased;
+using dvr::BufferHubDefs::IsClientAcquired;
+using dvr::BufferHubDefs::IsClientGained;
+using dvr::BufferHubDefs::IsClientPosted;
+using dvr::BufferHubDefs::IsClientReleased;
 using dvr::BufferHubDefs::kFirstClientBitMask;
 using dvr::BufferHubDefs::kMetadataHeaderSize;
 using frameworks::bufferhub::V1_0::BufferHubStatus;
@@ -48,9 +55,40 @@
 using pdx::LocalChannelHandle;
 
 class BufferHubBufferTest : public ::testing::Test {
+protected:
     void SetUp() override { android::hardware::ProcessState::self()->startThreadPool(); }
 };
 
+class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
+protected:
+    void SetUp() override {
+        BufferHubBufferTest::SetUp();
+        CreateTwoClientsOfABuffer();
+    }
+
+    std::unique_ptr<BufferHubBuffer> b1;
+    uint64_t b1ClientMask = 0ULL;
+    std::unique_ptr<BufferHubBuffer> b2;
+    uint64_t b2ClientMask = 0ULL;
+
+private:
+    // Creates b1 and b2 as the clients of the same buffer for testing.
+    void CreateTwoClientsOfABuffer();
+};
+
+void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
+    b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+    b1ClientMask = b1->client_state_mask();
+    ASSERT_NE(b1ClientMask, 0ULL);
+    auto statusOrHandle = b1->Duplicate();
+    ASSERT_TRUE(statusOrHandle);
+    LocalChannelHandle h2 = statusOrHandle.take();
+    b2 = BufferHubBuffer::Import(std::move(h2));
+    b2ClientMask = b2->client_state_mask();
+    ASSERT_NE(b2ClientMask, 0ULL);
+    ASSERT_NE(b2ClientMask, b1ClientMask);
+}
+
 TEST_F(BufferHubBufferTest, CreateBufferHubBufferFails) {
     // Buffer Creation will fail: BLOB format requires height to be 1.
     auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
@@ -315,5 +353,180 @@
     EXPECT_EQ(nullptr, client2.get());
 }
 
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
+    ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+    // Successful gaining the buffer should change the buffer state bit of b1 to
+    // gained state, other client state bits to released state.
+    EXPECT_EQ(b1->Gain(), 0);
+    EXPECT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    auto current_buffer_state = b1->buffer_state();
+    ASSERT_TRUE(IsClientGained(current_buffer_state, b1ClientMask));
+
+    // Gaining from gained state by the same client should not return error.
+    EXPECT_EQ(b1->Gain(), 0);
+
+    // Gaining from gained state by another client should return error.
+    EXPECT_EQ(b2->Gain(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_EQ(b2->Acquire(), 0);
+    ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+    // Gaining from acquired state should fail.
+    EXPECT_EQ(b1->Gain(), -EBUSY);
+    EXPECT_EQ(b2->Gain(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+    // Gaining a buffer who has other posted client should succeed.
+    EXPECT_EQ(b1->Gain(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+    // A posted client should be able to gain the buffer when there is no other clients in
+    // acquired state.
+    EXPECT_EQ(b2->Gain(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+
+    EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+
+    EXPECT_EQ(b1->Post(), 0);
+    auto current_buffer_state = b1->buffer_state();
+    EXPECT_TRUE(IsClientReleased(current_buffer_state, b1ClientMask));
+    EXPECT_TRUE(IsClientPosted(current_buffer_state, b2ClientMask));
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+    // Post from posted state should fail.
+    EXPECT_EQ(b1->Post(), -EBUSY);
+    EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_EQ(b2->Acquire(), 0);
+    ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+    // Posting from acquired state should fail.
+    EXPECT_EQ(b1->Post(), -EBUSY);
+    EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) {
+    ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+    // Posting from released state should fail.
+    EXPECT_EQ(b1->Post(), -EBUSY);
+    EXPECT_EQ(b2->Post(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+
+    // Acquire from posted state should pass.
+    EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+
+    // Acquire from released state should fail, although there are other clients
+    // in posted state.
+    EXPECT_EQ(b1->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_EQ(b2->Acquire(), 0);
+    auto current_buffer_state = b1->buffer_state();
+    ASSERT_TRUE(IsClientAcquired(current_buffer_state, b2ClientMask));
+
+    // Acquiring from acquired state by the same client should not error out.
+    EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) {
+    ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+    // Acquiring form released state should fail.
+    EXPECT_EQ(b1->Acquire(), -EBUSY);
+    EXPECT_EQ(b2->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+
+    // Acquiring from gained state should fail.
+    EXPECT_EQ(b1->Acquire(), -EBUSY);
+    EXPECT_EQ(b2->Acquire(), -EBUSY);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) {
+    ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+
+    EXPECT_EQ(b1->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) {
+    ASSERT_TRUE(IsBufferReleased(b1->buffer_state()));
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+
+    EXPECT_EQ(b1->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+
+    EXPECT_EQ(b2->Release(), 0);
+}
+
+TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) {
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+    ASSERT_EQ(b2->Acquire(), 0);
+    ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+
+    EXPECT_EQ(b2->Release(), 0);
+}
+
 } // namespace
 } // namespace android
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index de03fad..cd92b62 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -224,15 +224,17 @@
   uint64_t current_fence_state = fence_state_->load(std::memory_order_acquire);
   uint64_t current_active_clients_bit_mask =
       active_clients_bit_mask_->load(std::memory_order_acquire);
-  // If there is an release fence from consumer, we need to return it.
+  // If there are release fence(s) from consumer(s), we need to return it to the
+  // consumer(s).
   // TODO(b/112007999) add an atomic variable in metadata header in shared
   // memory to indicate which client is the last producer of the buffer.
   // Currently, assume the first client is the only producer to the buffer.
   if (current_fence_state & current_active_clients_bit_mask &
       (~BufferHubDefs::kFirstClientBitMask)) {
     *out_fence = shared_release_fence_.Duplicate();
-    out_meta->release_fence_mask =
-        current_fence_state & current_active_clients_bit_mask;
+    out_meta->release_fence_mask = current_fence_state &
+                                   current_active_clients_bit_mask &
+                                   (~BufferHubDefs::kFirstClientBitMask);
   }
 
   return 0;
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index ad4ffd7..501bf58 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -28,17 +28,17 @@
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
 /*
-** This header is generated from the Khronos OpenGL / OpenGL ES XML
-** API Registry. The current version of the Registry, generator scripts
+** This header is generated from the Khronos EGL XML API Registry.
+** The current version of the Registry, generator scripts
 ** used to make the header, and the header can be found at
 **   http://www.khronos.org/registry/egl
 **
-** Khronos $Git commit SHA1: bae3518c48 $ on $Git commit date: 2018-05-17 10:56:57 -0700 $
+** Khronos $Git commit SHA1: 726475c203 $ on $Git commit date: 2018-10-03 23:51:49 -0700 $
 */
 
 #include <EGL/eglplatform.h>
 
-#define EGL_EGLEXT_VERSION 20180517
+#define EGL_EGLEXT_VERSION 20181204
 
 /* Generated C header for:
  * API: egl
@@ -681,6 +681,7 @@
 #ifndef EGL_EXT_device_drm
 #define EGL_EXT_device_drm 1
 #define EGL_DRM_DEVICE_FILE_EXT           0x3233
+#define EGL_DRM_MASTER_FD_EXT             0x333C
 #endif /* EGL_EXT_device_drm */
 
 #ifndef EGL_EXT_device_enumeration
@@ -716,6 +717,11 @@
 #define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
 #endif /* EGL_EXT_gl_colorspace_display_p3_linear */
 
+#ifndef EGL_EXT_gl_colorspace_display_p3_passthrough
+#define EGL_EXT_gl_colorspace_display_p3_passthrough 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490
+#endif /* EGL_EXT_gl_colorspace_display_p3_passthrough */
+
 #ifndef EGL_EXT_gl_colorspace_scrgb
 #define EGL_EXT_gl_colorspace_scrgb 1
 #define EGL_GL_COLORSPACE_SCRGB_EXT       0x3351
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 583aec9..c80b79a 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -197,6 +197,7 @@
     defaults: ["gles_libs_defaults"],
     srcs: ["GLES_CM/gl.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv1\""],
+    version_script: "libGLESv1_CM.map.txt",
 }
 
 //##############################################################################
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 6edadcd..50e30c2 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -41,6 +41,12 @@
 extern "C" {
   android_namespace_t* android_get_exported_namespace(const char*);
 
+  typedef enum ANGLEPreference {
+      ANGLE_PREFER_DEFAULT = 0,
+      ANGLE_PREFER_NATIVE = 1,
+      ANGLE_PREFER_ANGLE = 2,
+  } ANGLEPreference;
+
   // TODO(ianelliott@): Get the following from an ANGLE header:
   // Version-1 API:
   typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse);
@@ -524,6 +530,17 @@
     return nullptr;
 }
 
+static ANGLEPreference getAngleDevOption(const char* devOption) {
+    if (devOption == nullptr)
+        return ANGLE_PREFER_DEFAULT;
+
+    if (strcmp(devOption, "angle") == 0) {
+        return ANGLE_PREFER_ANGLE;
+    } else if (strcmp(devOption, "native") == 0) {
+        return ANGLE_PREFER_NATIVE;
+    }
+    return ANGLE_PREFER_DEFAULT;
+}
 
 static bool check_angle_rules(void* so, const char* app_name) {
     bool use_angle = false;
@@ -646,15 +663,19 @@
     char prop[PROPERTY_VALUE_MAX];
 
     const char* app_name = android::GraphicsEnv::getInstance().getAngleAppName();
-    bool developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
+    const char* developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn();
 
     // Determine whether or not to use ANGLE:
-    bool use_angle = developer_opt_in;
+    ANGLEPreference developer_option = getAngleDevOption(developer_opt_in);
+    bool use_angle = (developer_option == ANGLE_PREFER_ANGLE);
 
     if (use_angle) {
         ALOGV("User set \"Developer Options\" to force the use of ANGLE");
     } else if (cnx->angleDecided) {
         use_angle = cnx->useAngle;
+    } else if (developer_option == ANGLE_PREFER_NATIVE) {
+        ALOGV("User set \"Developer Options\" to force the use of Native");
+        use_angle = false;
     } else {
         // The "Developer Options" value wasn't set to force the use of ANGLE.  Need to temporarily
         // load ANGLE and call the updatable opt-in/out logic:
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 4433af0..c100db7 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -378,7 +378,8 @@
         if (wideColorBoardConfig && hasColorSpaceSupport) {
             mExtensionString.append(
                     "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
-                    "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 ");
+                    "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "
+                    "EGL_EXT_gl_colorspace_display_p3_passthrough ");
         }
 
         bool hasHdrBoardConfig =
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 547a669..79166a7 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -461,11 +461,13 @@
     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
         return HAL_DATASPACE_UNKNOWN;
     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
-        return HAL_DATASPACE_SRGB;
+        return HAL_DATASPACE_V0_SRGB;
     } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
         return HAL_DATASPACE_DISPLAY_P3;
     } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
         return HAL_DATASPACE_DISPLAY_P3_LINEAR;
+    } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT) {
+        return HAL_DATASPACE_DISPLAY_P3;
     } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
         return HAL_DATASPACE_V0_SCRGB;
     } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
@@ -510,6 +512,9 @@
     if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_linear")) {
         colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
     }
+    if (findExtension(dp->disp.queryString.extensions, "EGL_EXT_gl_colorspace_display_p3_passthrough")) {
+        colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT);
+    }
     return colorSpaces;
 }
 
@@ -527,6 +532,7 @@
                 case EGL_GL_COLORSPACE_LINEAR_KHR:
                 case EGL_GL_COLORSPACE_SRGB_KHR:
                 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+                case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
                 case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
                 case EGL_GL_COLORSPACE_SCRGB_EXT:
                 case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 459b135..cca91c3 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -217,6 +217,7 @@
     // Test that display-p3 extensions exist
     ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
     ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
 
     // Use 8-bit to keep forcus on Display-P3 aspect
     EGLint attrs[] = {
@@ -289,6 +290,59 @@
     EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
 }
 
+TEST_F(EGLTest, EGLDisplayP3Passthrough) {
+    EGLConfig config;
+    EGLBoolean success;
+
+    if (!hasWideColorDisplay) {
+        // skip this test if device does not have wide-color display
+        std::cerr << "[          ] Device does not support wide-color, test skipped" << std::endl;
+        return;
+    }
+
+    // Test that display-p3 extensions exist
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
+
+    get8BitConfig(config);
+
+    struct DummyConsumer : public BnConsumerListener {
+        void onFrameAvailable(const BufferItem& /* item */) override {}
+        void onBuffersReleased() override {}
+        void onSidebandStreamChanged() override {}
+    };
+
+    // Create a EGLSurface
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    consumer->consumerConnect(new DummyConsumer, false);
+    sp<Surface> mSTC = new Surface(producer);
+    sp<ANativeWindow> mANW = mSTC;
+    EGLint winAttrs[] = {
+            // clang-format off
+            EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT,
+            EGL_NONE,              EGL_NONE
+            // clang-format on
+    };
+
+    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+    android_dataspace dataspace =
+        static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+    ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+    EGLint value;
+    success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+    ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, value);
+
+    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
 TEST_F(EGLTest, EGLDisplayP31010102) {
     EGLint numConfigs;
     EGLConfig config;
@@ -303,6 +357,7 @@
     // Test that display-p3 extensions exist
     ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
     ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
+    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
 
     // Use 8-bit to keep forcus on Display-P3 aspect
     EGLint attrs[] = {
diff --git a/opengl/tests/lib/include/EGLUtils.h b/opengl/tests/lib/include/EGLUtils.h
index eb9571d..cfa378f 100644
--- a/opengl/tests/lib/include/EGLUtils.h
+++ b/opengl/tests/lib/include/EGLUtils.h
@@ -280,6 +280,8 @@
             return String8("EGL_GL_COLORSPACE_SRGB_KHR");
         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
             return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT");
+        case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
+            return String8("EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT");
         case  EGL_GL_COLORSPACE_LINEAR_KHR:
             return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
         default:
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index 26771e1..8d661ae 100644
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -894,6 +894,11 @@
             <unused start="0x3481" end="0x348F"/>
     </enums>
 
+    <enums namespace="EGL" start="0x3490" end="0x349F" vendor="EXT" comment="Reserved for Courtney Goeltzenleuchter - Android (gitlab EGL bug 69)">
+        <enum value="0x3490" name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/>
+            <unused start="0x3491" end="0x349F"/>
+    </enums>
+
 <!-- Please remember that new enumerant allocations must be obtained by
      request to the Khronos API registrar (see comments at the top of this
      file) File requests in the Khronos Bugzilla, EGL project, Registry
@@ -903,8 +908,8 @@
 
 <!-- Reservable for future use. To generate a new range, allocate multiples
      of 16 starting at the lowest available point in this block. -->
-    <enums namespace="EGL" start="0x3490" end="0x3FFF" vendor="KHR" comment="Reserved for future use">
-            <unused start="0x3490" end="0x3FFF"/>
+    <enums namespace="EGL" start="0x34A0" end="0x3FFF" vendor="KHR" comment="Reserved for future use">
+            <unused start="0x34A0" end="0x3FFF"/>
     </enums>
 
     <enums namespace="EGL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with GL.">
@@ -2250,6 +2255,11 @@
                 <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_gl_colorspace_display_p3_passthrough" supported="egl">
+            <require>
+                <enum name="EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_image_dma_buf_import" supported="egl">
             <require>
                 <enum name="EGL_LINUX_DMA_BUF_EXT"/>
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 885348e..6879a73 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -97,6 +97,9 @@
 // Number of recent events to keep for debugging purposes.
 constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
 
+// Sequence number for synthesized or injected events.
+constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
+
 
 static inline nsecs_t now() {
     return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -710,7 +713,7 @@
         entry->policyFlags = policyFlags;
         entry->repeatCount += 1;
     } else {
-        KeyEntry* newEntry = new KeyEntry(currentTime,
+        KeyEntry* newEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
                 entry->deviceId, entry->source, entry->displayId, policyFlags,
                 entry->action, entry->flags, entry->keyCode, entry->scanCode,
                 entry->metaState, entry->repeatCount + 1, entry->downTime);
@@ -1663,11 +1666,17 @@
 
 void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
         int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
+    sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
+    if (inputChannel == nullptr) {
+        ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
+        return;
+    }
+
     inputTargets.push();
 
     const InputWindowInfo* windowInfo = windowHandle->getInfo();
     InputTarget& target = inputTargets.editTop();
-    target.inputChannel = getInputChannelLocked(windowHandle->getToken());
+    target.inputChannel = inputChannel;
     target.flags = targetFlags;
     target.xOffset = - windowInfo->frameLeft;
     target.yOffset = - windowInfo->frameTop;
@@ -2468,6 +2477,7 @@
     }
 
     MotionEntry* splitMotionEntry = new MotionEntry(
+            originalMotionEntry->sequenceNum,
             originalMotionEntry->eventTime,
             originalMotionEntry->deviceId,
             originalMotionEntry->source,
@@ -2501,7 +2511,8 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);
+        ConfigurationChangedEntry* newEntry =
+                new ConfigurationChangedEntry(args->sequenceNum, args->eventTime);
         needWake = enqueueInboundEventLocked(newEntry);
     } // release lock
 
@@ -2606,7 +2617,7 @@
             mLock.lock();
         }
 
-        KeyEntry* newEntry = new KeyEntry(args->eventTime,
+        KeyEntry* newEntry = new KeyEntry(args->sequenceNum, args->eventTime,
                 args->deviceId, args->source, args->displayId, policyFlags,
                 args->action, flags, keyCode, args->scanCode,
                 metaState, repeatCount, args->downTime);
@@ -2690,7 +2701,7 @@
         }
 
         // Just enqueue a new motion event.
-        MotionEntry* newEntry = new MotionEntry(args->eventTime,
+        MotionEntry* newEntry = new MotionEntry(args->sequenceNum, args->eventTime,
                 args->deviceId, args->source, args->displayId, policyFlags,
                 args->action, args->actionButton, args->flags,
                 args->metaState, args->buttonState,
@@ -2734,7 +2745,8 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);
+        DeviceResetEntry* newEntry =
+                new DeviceResetEntry(args->sequenceNum, args->eventTime, args->deviceId);
         needWake = enqueueInboundEventLocked(newEntry);
     } // release lock
 
@@ -2793,7 +2805,7 @@
         }
 
         mLock.lock();
-        firstInjectedEntry = new KeyEntry(keyEvent.getEventTime(),
+        firstInjectedEntry = new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, keyEvent.getEventTime(),
                 keyEvent.getDeviceId(), keyEvent.getSource(), keyEvent.getDisplayId(),
                 policyFlags, action, flags,
                 keyEvent.getKeyCode(), keyEvent.getScanCode(), keyEvent.getMetaState(),
@@ -2825,7 +2837,7 @@
         mLock.lock();
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
         const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        firstInjectedEntry = new MotionEntry(*sampleEventTimes,
+        firstInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
                 motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
                 policyFlags,
                 action, actionButton, motionEvent->getFlags(),
@@ -2839,7 +2851,8 @@
         for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
             sampleEventTimes += 1;
             samplePointerCoords += pointerCount;
-            MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
+            MotionEntry* nextInjectedEntry = new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM,
+                    *sampleEventTimes,
                     motionEvent->getDeviceId(), motionEvent->getSource(),
                     motionEvent->getDisplayId(), policyFlags,
                     action, actionButton, motionEvent->getFlags(),
@@ -4273,9 +4286,10 @@
 
 // --- InputDispatcher::EventEntry ---
 
-InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) :
-        refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags),
-        injectionState(nullptr), dispatchInProgress(false) {
+InputDispatcher::EventEntry::EventEntry(uint32_t sequenceNum, int32_t type,
+        nsecs_t eventTime, uint32_t policyFlags) :
+        sequenceNum(sequenceNum), refCount(1), type(type), eventTime(eventTime),
+        policyFlags(policyFlags), injectionState(nullptr), dispatchInProgress(false) {
 }
 
 InputDispatcher::EventEntry::~EventEntry() {
@@ -4301,8 +4315,9 @@
 
 // --- InputDispatcher::ConfigurationChangedEntry ---
 
-InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) :
-        EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
+InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(
+        uint32_t sequenceNum, nsecs_t eventTime) :
+        EventEntry(sequenceNum, TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
 }
 
 InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
@@ -4315,8 +4330,9 @@
 
 // --- InputDispatcher::DeviceResetEntry ---
 
-InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) :
-        EventEntry(TYPE_DEVICE_RESET, eventTime, 0),
+InputDispatcher::DeviceResetEntry::DeviceResetEntry(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
+        EventEntry(sequenceNum, TYPE_DEVICE_RESET, eventTime, 0),
         deviceId(deviceId) {
 }
 
@@ -4331,11 +4347,11 @@
 
 // --- InputDispatcher::KeyEntry ---
 
-InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
+InputDispatcher::KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
         int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
         int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
         int32_t repeatCount, nsecs_t downTime) :
-        EventEntry(TYPE_KEY, eventTime, policyFlags),
+        EventEntry(sequenceNum, TYPE_KEY, eventTime, policyFlags),
         deviceId(deviceId), source(source), displayId(displayId), action(action), flags(flags),
         keyCode(keyCode), scanCode(scanCode), metaState(metaState),
         repeatCount(repeatCount), downTime(downTime),
@@ -4366,7 +4382,7 @@
 
 // --- InputDispatcher::MotionEntry ---
 
-InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId,
+InputDispatcher::MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
         uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
         int32_t actionButton,
         int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
@@ -4374,7 +4390,7 @@
         uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
         float xOffset, float yOffset) :
-        EventEntry(TYPE_MOTION, eventTime, policyFlags),
+        EventEntry(sequenceNum, TYPE_MOTION, eventTime, policyFlags),
         eventTime(eventTime),
         deviceId(deviceId), source(source), displayId(displayId), action(action),
         actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
@@ -4688,7 +4704,7 @@
     for (size_t i = 0; i < mKeyMementos.size(); i++) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (shouldCancelKey(memento, options)) {
-            outEvents.push(new KeyEntry(currentTime,
+            outEvents.push(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
                     memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
                     AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
@@ -4698,7 +4714,7 @@
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (shouldCancelMotion(memento, options)) {
-            outEvents.push(new MotionEntry(currentTime,
+            outEvents.push(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
                     memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
                     memento.hovering
                             ? AMOTION_EVENT_ACTION_HOVER_EXIT
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 73bcc25..05b5dad 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -454,6 +454,7 @@
             TYPE_MOTION
         };
 
+        uint32_t sequenceNum;
         mutable int32_t refCount;
         int32_t type;
         nsecs_t eventTime;
@@ -469,13 +470,13 @@
         virtual void appendDescription(std::string& msg) const = 0;
 
     protected:
-        EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags);
+        EventEntry(uint32_t sequenceNum, int32_t type, nsecs_t eventTime, uint32_t policyFlags);
         virtual ~EventEntry();
         void releaseInjectionState();
     };
 
     struct ConfigurationChangedEntry : EventEntry {
-        explicit ConfigurationChangedEntry(nsecs_t eventTime);
+        explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
         virtual void appendDescription(std::string& msg) const;
 
     protected:
@@ -485,7 +486,7 @@
     struct DeviceResetEntry : EventEntry {
         int32_t deviceId;
 
-        DeviceResetEntry(nsecs_t eventTime, int32_t deviceId);
+        DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
         virtual void appendDescription(std::string& msg) const;
 
     protected:
@@ -515,7 +516,7 @@
         InterceptKeyResult interceptKeyResult; // set based on the interception result
         nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
 
-        KeyEntry(nsecs_t eventTime,
+        KeyEntry(uint32_t sequenceNum, nsecs_t eventTime,
                 int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
                 int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
                 int32_t repeatCount, nsecs_t downTime);
@@ -544,7 +545,7 @@
         PointerProperties pointerProperties[MAX_POINTERS];
         PointerCoords pointerCoords[MAX_POINTERS];
 
-        MotionEntry(nsecs_t eventTime,
+        MotionEntry(uint32_t sequenceNum, nsecs_t eventTime,
                 int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
                 int32_t action, int32_t actionButton, int32_t flags,
                 int32_t metaState, int32_t buttonState, int32_t edgeFlags,
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 25a39a8..23cceb4 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -26,13 +26,14 @@
 
 // --- NotifyConfigurationChangedArgs ---
 
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(nsecs_t eventTime) :
-        eventTime(eventTime) {
+NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
+        uint32_t sequenceNum, nsecs_t eventTime) :
+        NotifyArgs(sequenceNum), eventTime(eventTime) {
 }
 
 NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
         const NotifyConfigurationChangedArgs& other) :
-        eventTime(other.eventTime) {
+        NotifyArgs(other.sequenceNum), eventTime(other.eventTime) {
 }
 
 void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& listener) const {
@@ -42,19 +43,19 @@
 
 // --- NotifyKeyArgs ---
 
-NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
-        int32_t displayId, uint32_t policyFlags,
+NotifyKeyArgs::NotifyKeyArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
+        uint32_t source, int32_t displayId, uint32_t policyFlags,
         int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
         int32_t metaState, nsecs_t downTime) :
-        eventTime(eventTime), deviceId(deviceId), source(source), displayId(displayId),
-        policyFlags(policyFlags),
+        NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId), source(source),
+        displayId(displayId), policyFlags(policyFlags),
         action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
         metaState(metaState), downTime(downTime) {
 }
 
 NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) :
-        eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
-        displayId(other.displayId), policyFlags(other.policyFlags),
+        NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId),
+        source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
         action(other.action), flags(other.flags),
         keyCode(other.keyCode), scanCode(other.scanCode),
         metaState(other.metaState), downTime(other.downTime) {
@@ -67,15 +68,15 @@
 
 // --- NotifyMotionArgs ---
 
-NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
-        int32_t displayId, uint32_t policyFlags,
+NotifyMotionArgs::NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
+        uint32_t source, int32_t displayId, uint32_t policyFlags,
         int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
         int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
         uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
         float xPrecision, float yPrecision, nsecs_t downTime) :
-        eventTime(eventTime), deviceId(deviceId), source(source), displayId(displayId),
-        policyFlags(policyFlags),
+        NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId), source(source),
+        displayId(displayId), policyFlags(policyFlags),
         action(action), actionButton(actionButton),
         flags(flags), metaState(metaState), buttonState(buttonState),
         edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
@@ -88,8 +89,8 @@
 }
 
 NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
-        eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
-        displayId(other.displayId), policyFlags(other.policyFlags),
+        NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId),
+        source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
         action(other.action), actionButton(other.actionButton), flags(other.flags),
         metaState(other.metaState), buttonState(other.buttonState),
         edgeFlags(other.edgeFlags),
@@ -108,14 +109,14 @@
 
 // --- NotifySwitchArgs ---
 
-NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
+NotifySwitchArgs::NotifySwitchArgs(uint32_t sequenceNum, nsecs_t eventTime, uint32_t policyFlags,
         uint32_t switchValues, uint32_t switchMask) :
-        eventTime(eventTime), policyFlags(policyFlags),
+        NotifyArgs(sequenceNum), eventTime(eventTime), policyFlags(policyFlags),
         switchValues(switchValues), switchMask(switchMask) {
 }
 
 NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
-        eventTime(other.eventTime), policyFlags(other.policyFlags),
+        NotifyArgs(other.sequenceNum), eventTime(other.eventTime), policyFlags(other.policyFlags),
         switchValues(other.switchValues), switchMask(other.switchMask) {
 }
 
@@ -126,12 +127,13 @@
 
 // --- NotifyDeviceResetArgs ---
 
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId) :
-        eventTime(eventTime), deviceId(deviceId) {
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(
+        uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
+        NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId) {
 }
 
 NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
-        eventTime(other.eventTime), deviceId(other.deviceId) {
+        NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId) {
 }
 
 void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 9e748d8..7e00f42 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -236,8 +236,8 @@
             || (action == AKEY_EVENT_ACTION_UP
                     && (lastButtonState & buttonState)
                     && !(currentButtonState & buttonState))) {
-        NotifyKeyArgs args(when, deviceId, source, displayId, policyFlags,
-                action, 0, keyCode, 0, context->getGlobalMetaState(), when);
+        NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
+                policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
         context->getListener()->notifyKey(&args);
     }
 }
@@ -261,7 +261,7 @@
         const sp<InputReaderPolicyInterface>& policy,
         const sp<InputListenerInterface>& listener) :
         mContext(this), mEventHub(eventHub), mPolicy(policy),
-        mGlobalMetaState(0), mGeneration(1),
+        mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
         mConfigurationChangesToRefresh(0) {
     mQueuedListener = new QueuedInputListener(listener);
@@ -547,7 +547,7 @@
     updateGlobalMetaStateLocked();
 
     // Enqueue configuration changed.
-    NotifyConfigurationChangedArgs args(when);
+    NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
     mQueuedListener->notifyConfigurationChanged(&args);
 }
 
@@ -945,6 +945,9 @@
     return mReader->mEventHub.get();
 }
 
+uint32_t InputReader::ContextImpl::getNextSequenceNum() {
+    return (mReader->mNextSequenceNum)++;
+}
 
 // --- InputDevice ---
 
@@ -1265,7 +1268,7 @@
 }
 
 void InputDevice::notifyReset(nsecs_t when) {
-    NotifyDeviceResetArgs args(when, mId);
+    NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
     mContext->getListener()->notifyDeviceReset(&args);
 }
 
@@ -2038,7 +2041,8 @@
 void SwitchInputMapper::sync(nsecs_t when) {
     if (mUpdatedSwitchMask) {
         uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
-        NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);
+        NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
+                mUpdatedSwitchMask);
         getListener()->notifySwitch(&args);
 
         mUpdatedSwitchMask = 0;
@@ -2420,8 +2424,8 @@
         policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
     }
 
-    NotifyKeyArgs args(when, getDeviceId(), mSource, getDisplayId(), policyFlags,
-            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+            getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
     getListener()->notifyKey(&args);
 }
@@ -2638,6 +2642,7 @@
                 mOrientation = internalViewport->orientation;
             }
         }
+        getPolicy()->updatePointerDisplay();
         bumpGeneration();
     }
 }
@@ -2783,7 +2788,7 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
-        displayId = ADISPLAY_ID_DEFAULT;
+        displayId = mPointerController->getDisplayId();
     } else {
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
@@ -2823,7 +2828,8 @@
             while (!released.isEmpty()) {
                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
                 buttonState &= ~actionButton;
-                NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, displayId, policyFlags,
+                NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                        mSource, displayId, policyFlags,
                         AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
                         metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                         /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
@@ -2832,8 +2838,8 @@
             }
         }
 
-        NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
-                motionEventAction, 0, 0, metaState, currentButtonState,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
+                displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
                 AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                 mXPrecision, mYPrecision, downTime);
@@ -2844,9 +2850,9 @@
             while (!pressed.isEmpty()) {
                 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
                 buttonState |= actionButton;
-                NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, displayId, policyFlags,
-                        AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
-                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                        mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
+                        actionButton, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                         /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                         mXPrecision, mYPrecision, downTime);
                 getListener()->notifyMotion(&pressArgs);
@@ -2858,8 +2864,8 @@
         // Send hover move after UP to tell the application that the mouse is hovering now.
         if (motionEventAction == AMOTION_EVENT_ACTION_UP
                 && (mSource == AINPUT_SOURCE_MOUSE)) {
-            NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+            NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
                     metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                     /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                     mXPrecision, mYPrecision, downTime);
@@ -2871,7 +2877,8 @@
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
             pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-            NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
+            NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
                     AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
                     AMOTION_EVENT_EDGE_FLAG_NONE,
                     /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
@@ -3002,7 +3009,8 @@
         int32_t metaState = mContext->getGlobalMetaState();
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
 
-        NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
+        NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
                 AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
@@ -3601,6 +3609,9 @@
             (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
         if (mPointerController == nullptr) {
             mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+            getPolicy()->updatePointerDisplay();
+        } else if (viewportChanged) {
+            getPolicy()->updatePointerDisplay();
         }
     } else {
         mPointerController.clear();
@@ -4694,7 +4705,8 @@
     int32_t metaState = mContext->getGlobalMetaState();
     policyFlags |= POLICY_FLAG_VIRTUAL;
 
-    NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, mViewport.displayId,
+    NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
+            mViewport.displayId,
             policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
     getListener()->notifyKey(&args);
 }
@@ -5387,8 +5399,9 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
 
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
+        int32_t displayId = mPointerController->getDisplayId();
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, displayId, mSource,
+                mViewport.displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
                 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                 0, 0, mPointerGesture.downTime);
@@ -6294,6 +6307,7 @@
 void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
         bool down, bool hovering) {
     int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t displayId = mViewport.displayId;
 
     if (mPointerController != nullptr) {
         if (down || hovering) {
@@ -6304,13 +6318,15 @@
         } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
         }
+        displayId = mPointerController->getDisplayId();
     }
 
     if (mPointerSimple.down && !down) {
         mPointerSimple.down = false;
 
         // Send up.
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                  AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
                  /* deviceTimestamp */ 0,
                  1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
@@ -6323,7 +6339,8 @@
         mPointerSimple.hovering = false;
 
         // Send hover exit.
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
                 /* deviceTimestamp */ 0,
                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
@@ -6338,7 +6355,8 @@
             mPointerSimple.downTime = when;
 
             // Send down.
-            NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
                     AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
                     /* deviceTimestamp */ 0,
                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
@@ -6348,7 +6366,8 @@
         }
 
         // Send move.
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
                 /* deviceTimestamp */ 0,
                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
@@ -6362,7 +6381,8 @@
             mPointerSimple.hovering = true;
 
             // Send hover enter.
-            NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
                     AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
                     mCurrentRawState.buttonState, 0,
                     /* deviceTimestamp */ 0,
@@ -6373,7 +6393,8 @@
         }
 
         // Send hover move.
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
                 mCurrentRawState.buttonState, 0,
                 /* deviceTimestamp */ 0,
@@ -6395,7 +6416,8 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-        NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
                 /* deviceTimestamp */ 0,
                 1, &mPointerSimple.currentProperties, &pointerCoords,
@@ -6457,8 +6479,10 @@
             ALOG_ASSERT(false);
         }
     }
-
-    NotifyMotionArgs args(when, getDeviceId(), source, mViewport.displayId, policyFlags,
+    int32_t displayId = mPointerController != nullptr ?
+            mPointerController->getDisplayId() : mViewport.displayId;
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+            source, displayId, policyFlags,
             action, actionButton, flags, metaState, buttonState, edgeFlags,
             deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
             xPrecision, yPrecision, downTime);
@@ -7382,8 +7406,8 @@
     // TODO: Use the input device configuration to control this behavior more finely.
     uint32_t policyFlags = 0;
 
-    NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE,
-            policyFlags,
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+            AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
             AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
             /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
             0, 0, 0);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 13f1bed..35f3c23 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -96,6 +96,8 @@
     virtual InputReaderPolicyInterface* getPolicy() = 0;
     virtual InputListenerInterface* getListener() = 0;
     virtual EventHubInterface* getEventHub() = 0;
+
+    virtual uint32_t getNextSequenceNum() = 0;
 };
 
 
@@ -168,6 +170,7 @@
         virtual InputReaderPolicyInterface* getPolicy();
         virtual InputListenerInterface* getListener();
         virtual EventHubInterface* getEventHub();
+        virtual uint32_t getNextSequenceNum();
     } mContext;
 
     friend class ContextImpl;
@@ -183,6 +186,9 @@
 
     InputReaderConfiguration mConfig;
 
+    // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
+    uint32_t mNextSequenceNum;
+
     // The event queue.
     static const int EVENT_BUFFER_SIZE = 256;
     RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index a3d919b..f3a30ab 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -28,6 +28,12 @@
 
 /* Superclass of all input event argument objects */
 struct NotifyArgs {
+    uint32_t sequenceNum;
+
+    inline NotifyArgs() : sequenceNum(0) { }
+
+    inline explicit NotifyArgs(uint32_t sequenceNum) : sequenceNum(sequenceNum) { }
+
     virtual ~NotifyArgs() { }
 
     virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
@@ -40,7 +46,7 @@
 
     inline NotifyConfigurationChangedArgs() { }
 
-    explicit NotifyConfigurationChangedArgs(nsecs_t eventTime);
+    NotifyConfigurationChangedArgs(uint32_t sequenceNum, nsecs_t eventTime);
 
     NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other);
 
@@ -66,9 +72,9 @@
 
     inline NotifyKeyArgs() { }
 
-    NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
-            int32_t metaState, nsecs_t downTime);
+    NotifyKeyArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+            int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+            int32_t scanCode, int32_t metaState, nsecs_t downTime);
 
     NotifyKeyArgs(const NotifyKeyArgs& other);
 
@@ -107,8 +113,8 @@
 
     inline NotifyMotionArgs() { }
 
-    NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
-            uint32_t policyFlags,
+    NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+            int32_t displayId, uint32_t policyFlags,
             int32_t action, int32_t actionButton, int32_t flags,
             int32_t metaState, int32_t buttonState,
             int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
@@ -132,7 +138,7 @@
 
     inline NotifySwitchArgs() { }
 
-    NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
+    NotifySwitchArgs(uint32_t sequenceNum, nsecs_t eventTime, uint32_t policyFlags,
             uint32_t switchValues, uint32_t switchMask);
 
     NotifySwitchArgs(const NotifySwitchArgs& other);
@@ -151,7 +157,7 @@
 
     inline NotifyDeviceResetArgs() { }
 
-    NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId);
+    NotifyDeviceResetArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
 
     NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
 
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index fe1c50b..5a78df7 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -342,6 +342,9 @@
     /* Gets the affine calibration associated with the specified device. */
     virtual TouchAffineTransformation getTouchAffineTransformation(
             const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+
+    /* Update the pointer controller associated with the specified display. */
+    virtual void updatePointerDisplay() = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index e94dd94..e60b3f4 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -58,6 +58,9 @@
     /* Gets the absolute location of the pointer. */
     virtual void getPosition(float* outX, float* outY) const = 0;
 
+    /* Gets the id of the display where the pointer should be shown. */
+    virtual int32_t getDisplayId() const = 0;
+
     enum Transition {
         // Fade/unfade immediately.
         TRANSITION_IMMEDIATE,
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 04b87d5..855247f 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -57,6 +57,7 @@
     float mMinX, mMinY, mMaxX, mMaxY;
     float mX, mY;
     int32_t mButtonState;
+    int32_t mDisplayId;
 
 protected:
     virtual ~FakePointerController() { }
@@ -64,7 +65,7 @@
 public:
     FakePointerController() :
         mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
-        mButtonState(0) {
+        mButtonState(0), mDisplayId(ADISPLAY_ID_DEFAULT) {
     }
 
     void setBounds(float minX, float minY, float maxX, float maxY) {
@@ -75,6 +76,10 @@
         mMaxY = maxY;
     }
 
+    void setDisplayId(int32_t displayId) {
+        mDisplayId = displayId;
+    }
+
     virtual void setPosition(float x, float y) {
         mX = x;
         mY = y;
@@ -93,6 +98,10 @@
         *outY = mY;
     }
 
+    virtual int32_t getDisplayId() const {
+        return mDisplayId;
+    }
+
 private:
     virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
         *outMinX = mMinX;
@@ -262,6 +271,9 @@
     virtual std::string getDeviceAlias(const InputDeviceIdentifier&) {
         return "";
     }
+
+    virtual void updatePointerDisplay() {
+    }
 };
 
 
@@ -841,13 +853,14 @@
     int32_t mGlobalMetaState;
     bool mUpdateGlobalMetaStateWasCalled;
     int32_t mGeneration;
+    uint32_t mNextSequenceNum;
 
 public:
     FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
             const sp<InputReaderPolicyInterface>& policy,
             const sp<InputListenerInterface>& listener) :
             mEventHub(eventHub), mPolicy(policy), mListener(listener),
-            mGlobalMetaState(0) {
+            mGlobalMetaState(0), mNextSequenceNum(1) {
     }
 
     virtual ~FakeInputReaderContext() { }
@@ -911,6 +924,10 @@
     virtual void dispatchExternalStylusState(const StylusState&) {
 
     }
+
+    virtual uint32_t getNextSequenceNum() {
+        return mNextSequenceNum++;
+    }
 };
 
 
@@ -1556,6 +1573,39 @@
     ASSERT_EQ(1, event.value);
 }
 
+TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) {
+    constexpr int32_t deviceId = 1;
+    constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+    InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass);
+    // Must add at least one mapper or the device will be ignored!
+    FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
+    device->addMapper(mapper);
+    mReader->setNextDevice(device);
+    addDevice(deviceId, "fake", deviceClass, nullptr);
+
+    NotifyDeviceResetArgs resetArgs;
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+    uint32_t prevSequenceNum = resetArgs.sequenceNum;
+
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
+    prevSequenceNum = resetArgs.sequenceNum;
+
+    enableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
+    prevSequenceNum = resetArgs.sequenceNum;
+
+    disableDevice(deviceId, device);
+    mReader->loopOnce();
+    mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs);
+    ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
+    prevSequenceNum = resetArgs.sequenceNum;
+}
+
 
 // --- InputDeviceTest ---
 
@@ -3127,6 +3177,30 @@
     ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
 }
 
+TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addMapperAndConfigure(mapper);
+
+    // Setup PointerController for second display.
+    constexpr int32_t SECOND_DISPLAY_ID = 1;
+    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+    mFakePointerController->setPosition(100, 200);
+    mFakePointerController->setButtonState(0);
+    mFakePointerController->setDisplayId(SECOND_DISPLAY_ID);
+
+    NotifyMotionArgs args;
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+    ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+    ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
+}
+
 
 // --- TouchInputMapperTest ---
 
@@ -4625,7 +4699,6 @@
             toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
 }
 
-
 // --- MultiTouchInputMapperTest ---
 
 class MultiTouchInputMapperTest : public TouchInputMapperTest {
@@ -6246,4 +6319,30 @@
     ASSERT_EQ(DISPLAY_ID, args.displayId);
 }
 
+TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
+    // Setup PointerController for second display.
+    sp<FakePointerController> fakePointerController = new FakePointerController();
+    fakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+    fakePointerController->setPosition(100, 200);
+    fakePointerController->setButtonState(0);
+    fakePointerController->setDisplayId(SECONDARY_DISPLAY_ID);
+    mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    addMapperAndConfigure(mapper);
+
+    // Check source is mouse that would obtain the PointerController.
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
+
+    NotifyMotionArgs motionArgs;
+    processPosition(mapper, 100, 100);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
+    ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+}
+
 } // namespace android
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 8dc80cc..776efab 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -32,8 +32,9 @@
         const String16& opPackageName, bool hasSensorAccess)
     : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
       mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
-      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName),
-      mDestroyed(false), mHasSensorAccess(hasSensorAccess) {
+      mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
+      mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false),
+      mHasSensorAccess(hasSensorAccess) {
     mChannel = new BitTube(mService->mSocketBufferSize);
 #if DEBUG_CONNECTIONS
     mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -405,9 +406,6 @@
         reAllocateCacheLocked(events, count);
     } else {
         // The events do not fit within the cache: drop the oldest events.
-        ALOGW("Dropping events from cache (%d / %d) to save %d newer events", mCacheSize,
-                mMaxCacheSize, count);
-
         int freeSpace = mMaxCacheSize - mCacheSize;
 
         // Drop up to the currently cached number of events to make room for new events
@@ -419,6 +417,18 @@
         // Determine the number of new events to copy into the cache
         int eventsToCopy = std::min(mMaxCacheSize, count);
 
+        constexpr nsecs_t kMinimumTimeBetweenDropLogNs = 2 * 1000 * 1000 * 1000; // 2 sec
+        if (events[0].timestamp - mTimeOfLastEventDrop > kMinimumTimeBetweenDropLogNs) {
+            ALOGW("Dropping %d cached events (%d/%d) to save %d/%d new events. %d events previously"
+                    " dropped", cachedEventsToDrop, mCacheSize, mMaxCacheSize, eventsToCopy,
+                    count, mEventsDropped);
+            mEventsDropped = 0;
+            mTimeOfLastEventDrop = events[0].timestamp;
+        } else {
+            // Record the number dropped
+            mEventsDropped += cachedEventsToDrop + newEventsToDrop;
+        }
+
         // Check for any flush complete events in the events that will be dropped
         countFlushCompleteEventsLocked(mEventCache, cachedEventsToDrop);
         countFlushCompleteEventsLocked(events, newEventsToDrop);
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index eefd81a..061809f 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -165,6 +165,8 @@
 
     sensors_event_t *mEventCache;
     int mCacheSize, mMaxCacheSize;
+    int64_t mTimeOfLastEventDrop;
+    int mEventsDropped;
     String8 mPackageName;
     const String16 mOpPackageName;
 #if DEBUG_CONNECTIONS
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 9b1c0db..4e4d7dd 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -431,26 +431,25 @@
     }
 
     ui::Dataspace dataSpace = getDrawingDataSpace();
-    // treat modern dataspaces as legacy dataspaces whenever possible, until
-    // we can trust the buffer producers
+    // translate legacy dataspaces to modern dataspaces
     switch (dataSpace) {
-        case ui::Dataspace::V0_SRGB:
-            dataSpace = ui::Dataspace::SRGB;
+        case ui::Dataspace::SRGB:
+            dataSpace = ui::Dataspace::V0_SRGB;
             break;
-        case ui::Dataspace::V0_SRGB_LINEAR:
-            dataSpace = ui::Dataspace::SRGB_LINEAR;
+        case ui::Dataspace::SRGB_LINEAR:
+            dataSpace = ui::Dataspace::V0_SRGB_LINEAR;
             break;
-        case ui::Dataspace::V0_JFIF:
-            dataSpace = ui::Dataspace::JFIF;
+        case ui::Dataspace::JFIF:
+            dataSpace = ui::Dataspace::V0_JFIF;
             break;
-        case ui::Dataspace::V0_BT601_625:
-            dataSpace = ui::Dataspace::BT601_625;
+        case ui::Dataspace::BT601_625:
+            dataSpace = ui::Dataspace::V0_BT601_625;
             break;
-        case ui::Dataspace::V0_BT601_525:
-            dataSpace = ui::Dataspace::BT601_525;
+        case ui::Dataspace::BT601_525:
+            dataSpace = ui::Dataspace::V0_BT601_525;
             break;
-        case ui::Dataspace::V0_BT709:
-            dataSpace = ui::Dataspace::BT709;
+        case ui::Dataspace::BT709:
+            dataSpace = ui::Dataspace::V0_BT709;
             break;
         default:
             break;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 48fd47f..2963a97 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -98,7 +98,7 @@
 Dataspace colorModeToDataspace(ColorMode mode) {
     switch (mode) {
         case ColorMode::SRGB:
-            return Dataspace::SRGB;
+            return Dataspace::V0_SRGB;
         case ColorMode::DISPLAY_P3:
             return Dataspace::DISPLAY_P3;
         case ColorMode::DISPLAY_BT2020:
@@ -817,7 +817,7 @@
 bool DisplayDevice::hasRenderIntent(RenderIntent intent) const {
     // assume a render intent is supported when SRGB supports it; we should
     // get rid of that assumption.
-    auto iter = mColorModes.find(getColorModeKey(Dataspace::SRGB, intent));
+    auto iter = mColorModes.find(getColorModeKey(Dataspace::V0_SRGB, intent));
     return iter != mColorModes.end() && iter->second.renderIntent == intent;
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 91be71e..6d0fdad 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -506,8 +506,7 @@
 
     // this gives us only the "orientation" component of the transform
     const State& s(getDrawingState());
-    const int bufferWidth = getBufferSize(s).getWidth();
-    const int bufferHeight = getBufferSize(s).getHeight();
+    const Rect bufferSize = getBufferSize(s);
     auto blendMode = HWC2::BlendMode::None;
     if (!isOpaque(s) || getAlpha() != 1.0f) {
         blendMode =
@@ -526,7 +525,7 @@
     Region activeTransparentRegion(getActiveTransparentRegion(s));
     ui::Transform t = getTransform();
     Rect activeCrop = getCrop(s);
-    if (!activeCrop.isEmpty()) {
+    if (!activeCrop.isEmpty() && bufferSize.isValid()) {
         activeCrop = t.transform(activeCrop);
         if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
             activeCrop.clear();
@@ -538,15 +537,16 @@
         // transform.inverse().transform(transform.transform(Rect)) != Rect
         // in which case we need to make sure the final rect is clipped to the
         // display bounds.
-        if (!activeCrop.intersect(Rect(bufferWidth, bufferHeight), &activeCrop)) {
+        if (!activeCrop.intersect(bufferSize, &activeCrop)) {
             activeCrop.clear();
         }
         // mark regions outside the crop as transparent
-        activeTransparentRegion.orSelf(Rect(0, 0, bufferWidth, activeCrop.top));
-        activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, bufferWidth, bufferHeight));
+        activeTransparentRegion.orSelf(Rect(0, 0, bufferSize.getWidth(), activeCrop.top));
+        activeTransparentRegion.orSelf(
+                Rect(0, activeCrop.bottom, bufferSize.getWidth(), bufferSize.getHeight()));
         activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
         activeTransparentRegion.orSelf(
-                Rect(activeCrop.right, activeCrop.top, bufferWidth, activeCrop.bottom));
+                Rect(activeCrop.right, activeCrop.top, bufferSize.getWidth(), activeCrop.bottom));
     }
 
     // computeBounds returns a FloatRect to provide more accuracy during the
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a142928..a14ca2d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -734,24 +734,6 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
-    // This is a hack. Per definition of getDataspaceSaturationMatrix, the returned matrix
-    // is used to saturate legacy sRGB content. However, to make sure the same color under
-    // Display P3 will be saturated to the same color, we intentionally break the API spec
-    // and apply this saturation matrix on Display P3 content. Unless the risk of applying
-    // such saturation matrix on Display P3 is understood fully, the API should always return
-    // identify matrix.
-    mEnhancedSaturationMatrix =
-            getHwComposer().getDataspaceSaturationMatrix(*display->getId(), Dataspace::SRGB_LINEAR);
-
-    // we will apply this on Display P3.
-    if (mEnhancedSaturationMatrix != mat4()) {
-        ColorSpace srgb(ColorSpace::sRGB());
-        ColorSpace displayP3(ColorSpace::DisplayP3());
-        mat4 srgbToP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform());
-        mat4 p3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform());
-        mEnhancedSaturationMatrix = srgbToP3 * mEnhancedSaturationMatrix * p3ToSrgb;
-    }
-
     ALOGV("Done initializing");
 }
 
@@ -2106,7 +2088,7 @@
 //  - Dataspace::BT2020_PQ
 Dataspace SurfaceFlinger::getBestDataspace(const sp<const DisplayDevice>& display,
                                            Dataspace* outHdrDataSpace) const {
-    Dataspace bestDataSpace = Dataspace::SRGB;
+    Dataspace bestDataSpace = Dataspace::V0_SRGB;
     *outHdrDataSpace = Dataspace::UNKNOWN;
 
     for (const auto& layer : display->getVisibleLayersSortedByZ()) {
@@ -2431,7 +2413,7 @@
     Dataspace defaultDataSpace = Dataspace::UNKNOWN;
     if (display->hasWideColorGamut()) {
         defaultColorMode = ColorMode::SRGB;
-        defaultDataSpace = Dataspace::SRGB;
+        defaultDataSpace = Dataspace::V0_SRGB;
     }
     setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace,
                                RenderIntent::COLORIMETRIC);
@@ -3085,7 +3067,6 @@
 
     mat4 colorMatrix;
     bool applyColorMatrix = false;
-    bool needsEnhancedColorMatrix = false;
 
     // Framebuffer will live in this scope for GPU composition.
     std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
@@ -3132,16 +3113,6 @@
             colorMatrix = mDrawingState.colorMatrix;
         }
 
-        // The current enhanced saturation matrix is designed to enhance Display P3,
-        // thus we only apply this matrix when the render intent is not colorimetric
-        // and the output color space is Display P3.
-        needsEnhancedColorMatrix =
-            (display->getActiveRenderIntent() >= RenderIntent::ENHANCE &&
-             outputDataspace == Dataspace::DISPLAY_P3);
-        if (needsEnhancedColorMatrix) {
-            colorMatrix *= mEnhancedSaturationMatrix;
-        }
-
         display->setViewportAndProjection();
 
         // Never touch the framebuffer if we don't have any framebuffer layers
@@ -3216,9 +3187,6 @@
                             tmpMatrix = mDrawingState.colorMatrix;
                         }
                         tmpMatrix *= layer->getColorTransform();
-                        if (needsEnhancedColorMatrix) {
-                            tmpMatrix *= mEnhancedSaturationMatrix;
-                        }
                         getRenderEngine().setColorTransform(tmpMatrix);
                     } else {
                         getRenderEngine().setColorTransform(colorMatrix);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9f52058..4977ca0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -986,8 +986,6 @@
     std::thread::id mMainThreadId;
 
     DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED;
-    // Applied on Display P3 layers when the render intent is non-colorimetric.
-    mat4 mEnhancedSaturationMatrix;
 
     ui::Dataspace mDefaultCompositionDataspace;
     ui::Dataspace mWideColorGamutCompositionDataspace;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 42b7146..1a13f77 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -24,6 +24,7 @@
     },
     srcs: [
         ":libsurfaceflinger_sources",
+        "libsurfaceflinger_unittest_main.cpp",
         "CompositionTest.cpp",
         "DisplayIdentificationTest.cpp",
         "DisplayTransactionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 34cee3e..02aa5ce 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -1144,7 +1144,7 @@
 
     getBestColorMode();
 
-    ASSERT_EQ(ui::Dataspace::SRGB, mOutDataspace);
+    ASSERT_EQ(ui::Dataspace::V0_SRGB, mOutDataspace);
     ASSERT_EQ(ui::ColorMode::SRGB, mOutColorMode);
     ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
 }
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index bfd34cd..86f1a39 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -27,6 +27,8 @@
 
 #include "TimeStats/TimeStats.h"
 
+#include "libsurfaceflinger_unittest_main.h"
+
 using namespace android::surfaceflinger;
 using namespace google::protobuf;
 
@@ -486,6 +488,10 @@
 }
 
 TEST_F(TimeStatsTest, canSurviveMonkey) {
+    if (g_noSlowTests) {
+        GTEST_SKIP();
+    }
+
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
 
     for (size_t i = 0; i < 10000000; ++i) {
diff --git a/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.cpp b/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.cpp
new file mode 100644
index 0000000..bc1f00d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 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 <gtest/gtest.h>
+
+#include "libsurfaceflinger_unittest_main.h"
+
+// ------------------------------------------------------------------------
+// To pass extra command line arguments to the Google Test executable from
+// atest, you have to use this somewhat verbose syntax:
+//
+// clang-format off
+//
+//     atest libsurfaceflinger_unittest -- --module-arg libsurfaceflinger_unittest:native-test-flag:<--flag>[:<value>]
+//
+// For example:
+//
+//     atest libsurfaceflinger_unittest -- --module-arg libsurfaceflinger_unittest:native-test-flag:--no-slow
+//
+// clang-format on
+//  ------------------------------------------------------------------------
+
+// Set to true if "--no-slow" is passed to the test.
+bool g_noSlowTests = false;
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "--no-slow") == 0) {
+            g_noSlowTests = true;
+        }
+    }
+
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.h b/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.h
new file mode 100644
index 0000000..e742c50
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/libsurfaceflinger_unittest_main.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+// Set to true if "--no-slow" is passed to the test.
+extern bool g_noSlowTests;
diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp
index 90cc6de..2320a90 100644
--- a/services/utils/tests/PriorityDumper_test.cpp
+++ b/services/utils/tests/PriorityDumper_test.cpp
@@ -54,7 +54,7 @@
 };
 
 static void addAll(Vector<String16>& av, const std::vector<std::string>& v) {
-    for (auto element : v) {
+    for (const auto& element : v) {
         av.add(String16(element.c_str()));
     }
 }
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index f936e95..158ef9c 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -153,6 +153,17 @@
   }
 }
 
+void ConsumerChannel::OnProducerGained() {
+  // Clear the signal if exist. There is a possiblity that the signal still
+  // exist in consumer client when producer gains the buffer, e.g. newly added
+  // consumer fail to acquire the previous posted buffer in time. Then, when
+  // producer gains back the buffer, posts the buffer again and signal the
+  // consumer later, there won't be an signal change in eventfd, and thus,
+  // consumer will miss the posted buffer later. Thus, we need to clear the
+  // signal in consumer clients if the signal exist.
+  ClearAvailable();
+}
+
 void ConsumerChannel::OnProducerPosted() {
   acquired_ = false;
   released_ = false;
diff --git a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
index de0f23c..5fb4ec1 100644
--- a/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/consumer_channel.h
@@ -26,6 +26,7 @@
   uint64_t client_state_mask() const { return client_state_mask_; }
   BufferInfo GetBufferInfo() const override;
 
+  void OnProducerGained();
   void OnProducerPosted();
   void OnProducerClosed();
 
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index ab1d94c..b541fb3 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -424,7 +424,7 @@
   // Signal any interested consumers. If there are none, the buffer will stay
   // in posted state until a consumer comes online. This behavior guarantees
   // that no frame is silently dropped.
-  for (auto consumer : consumer_channels_) {
+  for (auto& consumer : consumer_channels_) {
     consumer->OnProducerPosted();
   }
 
@@ -437,6 +437,9 @@
 
   ClearAvailable();
   post_fence_.close();
+  for (auto& consumer : consumer_channels_) {
+    consumer->OnProducerGained();
+  }
   return {std::move(returned_fence_)};
 }
 
@@ -533,7 +536,7 @@
 
   uint64_t current_buffer_state =
       buffer_state_->load(std::memory_order_acquire);
-  if (BufferHubDefs::IsClientReleased(current_buffer_state,
+  if (BufferHubDefs::IsBufferReleased(current_buffer_state &
                                       ~orphaned_consumer_bit_mask_)) {
     SignalAvailable();
     if (orphaned_consumer_bit_mask_) {
@@ -560,7 +563,7 @@
 
   uint64_t current_buffer_state =
       buffer_state_->load(std::memory_order_acquire);
-  if (BufferHubDefs::IsClientReleased(current_buffer_state,
+  if (BufferHubDefs::IsBufferReleased(current_buffer_state &
                                       ~orphaned_consumer_bit_mask_)) {
     SignalAvailable();
   }
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 7eaf7b2..fed8481 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -39,6 +39,9 @@
         "-Wno-switch-enum",
         "-Wno-undef",
 
+        // Have clang emit complete debug_info.
+        "-fstandalone-debug",
+
         //"-DLOG_NDEBUG=0",
     ],