Merge changes Idcd4808c,I108ccb75,I446e5795,Idae2d3d9,I2a81817c

* changes:
  SF: Separate out display color handling
  SF: Separate out render surface code
  SF: Move DisplaySurface into CompositionEngine
  SF: Move state out of DisplayDevice to a new Output class
  SF: Setup CompositionEngine::Display
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 9b12a02..99f3739 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -140,6 +140,12 @@
     chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
     chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
 
+    # filemap events for iorapd
+    chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache/enable
+    chmod 0666 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache/enable
+
 # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
@@ -165,7 +171,7 @@
     chmod 0666 /sys/kernel/tracing/per_cpu/cpu5/trace
     chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
     chmod 0666 /sys/kernel/tracing/per_cpu/cpu6/trace
-    chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu6/trace
+    chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu7/trace
     chmod 0666 /sys/kernel/tracing/per_cpu/cpu7/trace
     chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu8/trace
     chmod 0666 /sys/kernel/tracing/per_cpu/cpu8/trace
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4e5d68d..8c8cd51 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -475,47 +475,6 @@
     return false;
 }
 
-static void dump_systrace() {
-    if (!ds.IsZipping()) {
-        MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
-        return;
-    }
-    std::string systrace_path = ds.GetPath("-systrace.txt");
-    if (systrace_path.empty()) {
-        MYLOGE("Not dumping systrace because path is empty\n");
-        return;
-    }
-    const char* path = "/sys/kernel/debug/tracing/tracing_on";
-    long int is_tracing;
-    if (read_file_as_long(path, &is_tracing)) {
-        return; // error already logged
-    }
-    if (is_tracing <= 0) {
-        MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
-        return;
-    }
-
-    MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
-            systrace_path.c_str());
-    if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
-                   CommandOptions::WithTimeout(120).Build())) {
-        MYLOGE("systrace timed out, its zip entry will be incomplete\n");
-        // TODO: RunCommand tries to kill the process, but atrace doesn't die
-        // peacefully; ideally, we should call strace to stop itself, but there is no such option
-        // yet (just a --async_stop, which stops and dump
-        // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
-        //   MYLOGE("could not stop systrace ");
-        // }
-    }
-    if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
-        MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
-    } else {
-        if (remove(systrace_path.c_str())) {
-            MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
-        }
-    }
-}
-
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -1446,12 +1405,8 @@
 
 /* Dumps state for the default case. Returns true if everything went fine. */
 static bool DumpstateDefault() {
-    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
-    // First try to dump anrd trace if the daemon is running. Otherwise, dump
-    // the raw trace.
-    if (!dump_anrd_trace()) {
-        dump_systrace();
-    }
+    // Try to dump anrd trace if the daemon is running.
+    dump_anrd_trace();
 
     // Invoking the following dumpsys calls before dump_traces() to try and
     // keep the system stats as close to its initial state as possible.
@@ -2262,6 +2217,28 @@
     options_ = std::move(options);
 }
 
+Dumpstate::RunStatus Dumpstate::Run() {
+    Dumpstate::RunStatus status = RunInternal();
+    if (listener_ != nullptr) {
+        switch (status) {
+            case Dumpstate::RunStatus::OK:
+                // TODO(b/111441001): duration argument does not make sense. Remove.
+                listener_->onFinished(0 /* duration */, options_->notification_title,
+                                      options_->notification_description);
+                break;
+            case Dumpstate::RunStatus::HELP:
+                break;
+            case Dumpstate::RunStatus::INVALID_INPUT:
+                listener_->onError(android::os::IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
+                break;
+            case Dumpstate::RunStatus::ERROR:
+                listener_->onError(android::os::IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
+                break;
+        }
+    }
+    return status;
+}
+
 /*
  * Dumps relevant information to a bugreport based on the given options.
  *
@@ -2283,7 +2260,7 @@
  * Bugreports are first generated in a local directory and later copied to the caller's fd or
  * directory.
  */
-Dumpstate::RunStatus Dumpstate::Run() {
+Dumpstate::RunStatus Dumpstate::RunInternal() {
     LogDumpOptions(*options_);
     if (!options_->ValidateOptions()) {
         MYLOGE("Invalid options specified\n");
@@ -2488,6 +2465,7 @@
     /* tell activity manager we're done */
     if (options_->do_broadcast) {
         SendBugreportFinishedBroadcast();
+        // Note that listener_ is notified in Run();
     }
 
     MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 529111e..c620c07 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -449,6 +449,8 @@
     std::vector<DumpData> anr_data_;
 
   private:
+    RunStatus RunInternal();
+
     // Used by GetInstance() only.
     explicit Dumpstate(const std::string& version = VERSION_CURRENT);
 
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 98ee1b0..cd9b97f 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -656,8 +656,9 @@
         }
 
         if (update_progress) {
-            message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
-                                                   listener_name.c_str(), progress, max);
+            message += android::base::StringPrintf("Setting progress (%s): %d/%d (%d%%)\n",
+                                                   listener_name.c_str(), progress, max,
+                                                   (100 * progress / max));
         }
 
         return message;
@@ -816,12 +817,14 @@
     SetProgress(0, 30);
 
     EXPECT_CALL(*listener, onProgressUpdated(20));
+    EXPECT_CALL(*listener, onProgress(66));  // 20/30 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
     std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
 
     EXPECT_CALL(*listener, onProgressUpdated(30));
+    EXPECT_CALL(*listener, onProgress(100));  // 35/35 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
     progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
     EXPECT_THAT(out, StrEq("stdout\n"));
@@ -830,6 +833,7 @@
     // Run a command that will increase maximum timeout.
     EXPECT_CALL(*listener, onProgressUpdated(31));
     EXPECT_CALL(*listener, onMaxProgressUpdated(37));
+    EXPECT_CALL(*listener, onProgress(83));  // 31/37 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
     progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase
     EXPECT_THAT(out, StrEq("stdout\n"));
@@ -838,6 +842,7 @@
     // Make sure command ran while in dry_run is counted.
     SetDryRun(true);
     EXPECT_CALL(*listener, onProgressUpdated(35));
+    EXPECT_CALL(*listener, onProgress(94));  // 35/37 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
     progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
     EXPECT_THAT(out, IsEmpty());
@@ -854,6 +859,7 @@
 
     // First update should always be sent.
     EXPECT_CALL(*listener, onProgressUpdated(1));
+    EXPECT_CALL(*listener, onProgress(12));  // 1/12 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
     std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
     EXPECT_THAT(out, StrEq("stdout\n"));
@@ -866,6 +872,7 @@
 
     // Third update should be sent because it reaches threshold (6 - 1 = 5).
     EXPECT_CALL(*listener, onProgressUpdated(6));
+    EXPECT_CALL(*listener, onProgress(75));  // 6/8 %
     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
     progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
     EXPECT_THAT(out, StrEq("stdout\n"));
@@ -1105,6 +1112,7 @@
     SetProgress(0, 30);
 
     EXPECT_CALL(*listener, onProgressUpdated(5));
+    EXPECT_CALL(*listener, onProgress(16));  // 5/30 %
     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
 
     std::string progress_message =
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 990fd43..528e43d 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -949,16 +949,22 @@
         fsync(control_socket_fd_);
     }
 
+    int percent = 100 * progress / max;
     if (listener_ != nullptr) {
-        if (progress % 100 == 0) {
-            // We don't want to spam logcat, so only log multiples of 100.
-            MYLOGD("Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+        if (percent % 5 == 0) {
+            // We don't want to spam logcat, so only log multiples of 5.
+            MYLOGD("Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(), progress, max,
+                   percent);
         } else {
             // stderr is ignored on normal invocations, but useful when calling
             // /system/bin/dumpstate directly for debuggging.
-            fprintf(stderr, "Setting progress (%s): %d/%d\n", listener_name_.c_str(), progress, max);
+            fprintf(stderr, "Setting progress (%s): %d/%d (%d%%)\n", listener_name_.c_str(),
+                    progress, max, percent);
         }
+        // TODO(b/111441001): Remove in favor of onProgress
         listener_->onProgressUpdated(progress);
+
+        listener_->onProgress(percent);
     }
 }
 
diff --git a/cmds/surfacereplayer/OWNERS b/cmds/surfacereplayer/OWNERS
new file mode 100644
index 0000000..cc4c842
--- /dev/null
+++ b/cmds/surfacereplayer/OWNERS
@@ -0,0 +1,2 @@
+mathias@google.com
+racarr@google.com
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index cfd2b40..214559d 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -774,7 +774,8 @@
     AKEYCODE_THUMBS_UP = 286,
     /** Thumbs down key. Apps can use this to let user downvote content. */
     AKEYCODE_THUMBS_DOWN = 287,
-    /** Consumed by system to switch current viewer profile. */
+    /** Used to switch current account that is consuming content.
+     * May be consumed by system to switch current viewer profile. */
     AKEYCODE_PROFILE_SWITCH = 288
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 05d96ff..d31d1f1 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -112,15 +112,25 @@
 
 #if __ANDROID_API__ >= 29
 
+/**
+ * Possible values of the flags argument to android_res_nsend and android_res_nquery.
+ * Values are ORed together.
+ */
 enum ResNsendFlags : uint32_t {
-    // Send a single request to a single resolver and fail on timeout or network errors
+    /**
+     * Send a single request to a single resolver and fail on timeout or network errors
+     */
     ANDROID_RESOLV_NO_RETRY = 1 << 0,
 
-    // Do not cache the result of the lookup. The lookup may return a result that is already
-    // in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+    /**
+     * Do not cache the result of the lookup. The lookup may return a result that is already
+     * in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+     */
     ANDROID_RESOLV_NO_CACHE_STORE = 1 << 1,
 
-    // Don't lookup the request in cache, do not write back the response into the cache
+    /**
+     * Don't lookup the request in cache.
+     */
     ANDROID_RESOLV_NO_CACHE_LOOKUP = 1 << 2,
 };
 
@@ -136,8 +146,7 @@
  * POSIX error code (see errno.h) if an immediate error occurs.
  */
 int android_res_nquery(net_handle_t network,
-        const char *dname, int ns_class, int ns_type,
-        enum ResNsendFlags flags) __INTRODUCED_IN(29);
+        const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
 
 /**
  * Issue the query |msg| on the given |network|.
@@ -148,10 +157,11 @@
  * POSIX error code (see errno.h) if an immediate error occurs.
  */
 int android_res_nsend(net_handle_t network,
-        const uint8_t *msg, size_t msglen, enum ResNsendFlags flags) __INTRODUCED_IN(29);
+        const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
 
 /**
  * Read a result for the query associated with the |fd| descriptor.
+ * Closes |fd| before returning.
  *
  * Returns:
  *     < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 005564d..1a1b010 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -64,6 +64,7 @@
 #define ASENSOR_RESOLUTION_INVALID     (nanf(""))
 #define ASENSOR_FIFO_COUNT_INVALID     (-1)
 #define ASENSOR_DELAY_INVALID          INT32_MIN
+#define ASENSOR_INVALID                (-1)
 
 /* (Keep in sync with hardware/sensors-base.h and Sensor.java.) */
 
@@ -208,6 +209,35 @@
      */
     ASENSOR_TYPE_HEART_BEAT = 31,
     /**
+     * This sensor type is for delivering additional sensor information aside
+     * from sensor event data.
+     *
+     * Additional information may include:
+     *     - {@link ASENSOR_ADDITIONAL_INFO_INTERNAL_TEMPERATURE}
+     *     - {@link ASENSOR_ADDITIONAL_INFO_SAMPLING}
+     *     - {@link ASENSOR_ADDITIONAL_INFO_SENSOR_PLACEMENT}
+     *     - {@link ASENSOR_ADDITIONAL_INFO_UNTRACKED_DELAY}
+     *     - {@link ASENSOR_ADDITIONAL_INFO_VEC3_CALIBRATION}
+     *
+     * This type will never bind to a sensor. In other words, no sensor in the
+     * sensor list can have the type {@link ASENSOR_TYPE_ADDITIONAL_INFO}.
+     *
+     * If a device supports the sensor additional information feature, it will
+     * report additional information events via {@link ASensorEvent} and will
+     * have {@link ASensorEvent#type} set to
+     * {@link ASENSOR_TYPE_ADDITIONAL_INFO} and {@link ASensorEvent#sensor} set
+     * to the handle of the reporting sensor.
+     *
+     * Additional information reports consist of multiple frames ordered by
+     * {@link ASensorEvent#timestamp}. The first frame in the report will have
+     * a {@link AAdditionalInfoEvent#type} of
+     * {@link ASENSOR_ADDITIONAL_INFO_BEGIN}, and the last frame in the report
+     * will have a {@link AAdditionalInfoEvent#type} of
+     * {@link ASENSOR_ADDITIONAL_INFO_END}.
+     *
+     */
+    ASENSOR_TYPE_ADDITIONAL_INFO = 33,
+    /**
      * {@link ASENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT}
      */
     ASENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT = 34,
@@ -273,6 +303,51 @@
     ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER = 2
 };
 
+/**
+ * Sensor Additional Info Types.
+ *
+ * Used to populate {@link AAdditionalInfoEvent#type}.
+ */
+enum {
+    /** Marks the beginning of additional information frames */
+    ASENSOR_ADDITIONAL_INFO_BEGIN = 0,
+
+    /** Marks the end of additional information frames */
+    ASENSOR_ADDITIONAL_INFO_END = 1,
+
+    /**
+     * Estimation of the delay that is not tracked by sensor timestamps. This
+     * includes delay introduced by sensor front-end filtering, data transport,
+     * etc.
+     * float[2]: delay in seconds, standard deviation of estimated value
+     */
+    ASENSOR_ADDITIONAL_INFO_UNTRACKED_DELAY = 0x10000,
+
+    /** float: Celsius temperature */
+    ASENSOR_ADDITIONAL_INFO_INTERNAL_TEMPERATURE,
+
+    /**
+     * First three rows of a homogeneous matrix, which represents calibration to
+     * a three-element vector raw sensor reading.
+     * float[12]: 3x4 matrix in row major order
+     */
+    ASENSOR_ADDITIONAL_INFO_VEC3_CALIBRATION,
+
+    /**
+     * Location and orientation of sensor element in the device frame: origin is
+     * the geometric center of the mobile device screen surface; the axis
+     * definition corresponds to Android sensor definitions.
+     * float[12]: 3x4 matrix in row major order
+     */
+    ASENSOR_ADDITIONAL_INFO_SENSOR_PLACEMENT,
+
+    /**
+     * float[2]: raw sample period in seconds,
+     *           standard deviation of sampling period
+     */
+    ASENSOR_ADDITIONAL_INFO_SAMPLING,
+};
+
 /*
  * A few useful constants
  */
@@ -341,7 +416,7 @@
     int32_t  handle;
 } ADynamicSensorEvent;
 
-typedef struct {
+typedef struct AAdditionalInfoEvent {
     int32_t type;
     int32_t serial;
     union {
@@ -444,6 +519,7 @@
  * - ASensor_getStringType()
  * - ASensor_getReportingMode()
  * - ASensor_isWakeUpSensor()
+ * - ASensor_getHandle()
  */
 typedef struct ASensor ASensor;
 /**
@@ -785,6 +861,24 @@
 int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
 #endif /* __ANDROID_API__ >= 26 */
 
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+/**
+ * Returns the sensor's handle.
+ *
+ * The handle identifies the sensor within the system and is included in the
+ * {@link ASensorEvent#sensor} field of sensor events, including those sent with type
+ * {@link ASENSOR_TYPE_ADDITIONAL_INFO}.
+ *
+ * A sensor's handle is able to be used to map {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to the
+ * sensor that generated the event.
+ *
+ * It is important to note that the value returned by {@link ASensor_getHandle} is not the same as
+ * the value returned by the Java API {@link android.hardware.Sensor#getId} and no mapping exists
+ * between the values.
+ */
+int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(__ANDROID_API_Q__);
+#endif /* __ANDROID_API__ >= ANDROID_API_Q__ */
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/input/Input.h b/include/input/Input.h
index 2c4a511..805957a 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -241,6 +241,11 @@
     DEEP_PRESS = 2,
 };
 
+/**
+ * String representation of MotionClassification
+ */
+const char* motionClassificationToString(MotionClassification classification);
+
 /*
  * Pointer coordinate data.
  */
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index dddbfb0..63606e5 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -105,8 +105,9 @@
             int32_t flags;
             int32_t metaState;
             int32_t buttonState;
+            MotionClassification classification; // base type: uint8_t
+            uint8_t empty2[3];
             int32_t edgeFlags;
-            uint32_t empty2;
             nsecs_t downTime __attribute__((aligned(8)));
             float xOffset;
             float yOffset;
@@ -271,6 +272,7 @@
             int32_t edgeFlags,
             int32_t metaState,
             int32_t buttonState,
+            MotionClassification classification,
             float xOffset,
             float yOffset,
             float xPrecision,
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index f6cc3af..96ee295 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -86,6 +86,10 @@
 class BBinder::Extras
 {
 public:
+    // unlocked objects
+    bool mRequestingSid = false;
+
+    // for below objects
     Mutex mLock;
     BpBinder::ObjectManager mObjects;
 };
@@ -163,19 +167,8 @@
     const void* objectID, void* object, void* cleanupCookie,
     object_cleanup_func func)
 {
-    Extras* e = mExtras.load(std::memory_order_acquire);
-
-    if (!e) {
-        e = new Extras;
-        Extras* expected = nullptr;
-        if (!mExtras.compare_exchange_strong(expected, e,
-                                             std::memory_order_release,
-                                             std::memory_order_acquire)) {
-            delete e;
-            e = expected;  // Filled in by CAS
-        }
-        if (e == nullptr) return; // out of memory
-    }
+    Extras* e = getOrCreateExtras();
+    if (!e) return; // out of memory
 
     AutoMutex _l(e->mLock);
     e->mObjects.attach(objectID, object, cleanupCookie, func);
@@ -204,6 +197,30 @@
     return this;
 }
 
+bool BBinder::isRequestingSid()
+{
+    Extras* e = mExtras.load(std::memory_order_acquire);
+
+    return e && e->mRequestingSid;
+}
+
+void BBinder::setRequestingSid(bool requestingSid)
+{
+    Extras* e = mExtras.load(std::memory_order_acquire);
+
+    if (!e) {
+        // default is false. Most things don't need sids, so avoiding allocations when possible.
+        if (!requestingSid) {
+            return;
+        }
+
+        e = getOrCreateExtras();
+        if (!e) return; // out of memory
+    }
+
+    e->mRequestingSid = true;
+}
+
 BBinder::~BBinder()
 {
     Extras* e = mExtras.load(std::memory_order_relaxed);
@@ -267,6 +284,25 @@
     }
 }
 
+BBinder::Extras* BBinder::getOrCreateExtras()
+{
+    Extras* e = mExtras.load(std::memory_order_acquire);
+
+    if (!e) {
+        e = new Extras;
+        Extras* expected = nullptr;
+        if (!mExtras.compare_exchange_strong(expected, e,
+                                             std::memory_order_release,
+                                             std::memory_order_acquire)) {
+            delete e;
+            e = expected;  // Filled in by CAS
+        }
+        if (e == nullptr) return nullptr; // out of memory
+    }
+
+    return e;
+}
+
 // ---------------------------------------------------------------------------
 
 enum {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 1d4e234..9a561cb 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -88,7 +88,8 @@
     "BR_FINISHED",
     "BR_DEAD_BINDER",
     "BR_CLEAR_DEATH_NOTIFICATION_DONE",
-    "BR_FAILED_REPLY"
+    "BR_FAILED_REPLY",
+    "BR_TRANSACTION_SEC_CTX",
 };
 
 static const char *kCommandStrings[] = {
@@ -365,6 +366,11 @@
     return mCallingPid;
 }
 
+const char* IPCThreadState::getCallingSid() const
+{
+    return mCallingSid;
+}
+
 uid_t IPCThreadState::getCallingUid() const
 {
     return mCallingUid;
@@ -372,6 +378,7 @@
 
 int64_t IPCThreadState::clearCallingIdentity()
 {
+    // ignore mCallingSid for legacy reasons
     int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
     clearCaller();
     return token;
@@ -442,12 +449,14 @@
 void IPCThreadState::restoreCallingIdentity(int64_t token)
 {
     mCallingUid = (int)(token>>32);
+    mCallingSid = nullptr;  // not enough data to restore
     mCallingPid = (int)token;
 }
 
 void IPCThreadState::clearCaller()
 {
     mCallingPid = getpid();
+    mCallingSid = nullptr;  // expensive to lookup
     mCallingUid = getuid();
 }
 
@@ -1135,10 +1144,19 @@
         }
         break;
 
+    case BR_TRANSACTION_SEC_CTX:
     case BR_TRANSACTION:
         {
-            binder_transaction_data tr;
-            result = mIn.read(&tr, sizeof(tr));
+            binder_transaction_data_secctx tr_secctx;
+            binder_transaction_data& tr = tr_secctx.transaction_data;
+
+            if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
+                result = mIn.read(&tr_secctx, sizeof(tr_secctx));
+            } else {
+                result = mIn.read(&tr, sizeof(tr));
+                tr_secctx.secctx = 0;
+            }
+
             ALOG_ASSERT(result == NO_ERROR,
                 "Not enough command data for brTRANSACTION");
             if (result != NO_ERROR) break;
@@ -1154,6 +1172,7 @@
                 tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
 
             const pid_t origPid = mCallingPid;
+            const char* origSid = mCallingSid;
             const uid_t origUid = mCallingUid;
             const int32_t origStrictModePolicy = mStrictModePolicy;
             const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
@@ -1166,10 +1185,12 @@
             clearPropagateWorkSource();
 
             mCallingPid = tr.sender_pid;
+            mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx);
             mCallingUid = tr.sender_euid;
             mLastTransactionBinderFlags = tr.flags;
 
-            //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
+            // ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid,
+            //    (mCallingSid ? mCallingSid : "<N/A>"), mCallingUid);
 
             Parcel reply;
             status_t error;
@@ -1201,8 +1222,8 @@
             }
 
             mIPCThreadStateBase->popCurrentState();
-            //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
-            //     mCallingPid, origPid, origUid);
+            //ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n",
+            //     mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid);
 
             if ((tr.flags & TF_ONE_WAY) == 0) {
                 LOG_ONEWAY("Sending reply to %d!", mCallingPid);
@@ -1213,6 +1234,7 @@
             }
 
             mCallingPid = origPid;
+            mCallingSid = origSid;
             mCallingUid = origUid;
             mStrictModePolicy = origStrictModePolicy;
             mLastTransactionBinderFlags = origTransactionBinderFlags;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d285030..f779d6e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -220,7 +220,7 @@
     }
 
     if (binder != nullptr) {
-        IBinder *local = binder->localBinder();
+        BBinder *local = binder->localBinder();
         if (!local) {
             BpBinder *proxy = binder->remoteBinder();
             if (proxy == nullptr) {
@@ -232,6 +232,9 @@
             obj.handle = handle;
             obj.cookie = 0;
         } else {
+            if (local->isRequestingSid()) {
+                obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+            }
             obj.hdr.type = BINDER_TYPE_BINDER;
             obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
             obj.cookie = reinterpret_cast<uintptr_t>(local);
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 3798b61..79db0cb 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -181,8 +181,20 @@
         mBinderContextCheckFunc = checkFunc;
         mBinderContextUserData = userData;
 
-        int dummy = 0;
-        status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+        flat_binder_object obj {
+            .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
+        };
+
+        status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+        // fallback to original method
+        if (result != 0) {
+            android_errorWriteLog(0x534e4554, "121035042");
+
+            int dummy = 0;
+            result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+        }
+
         if (result == 0) {
             mManagesContexts = true;
         } else if (result == -1) {
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index c251468..cf3ef84 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -60,6 +60,10 @@
 
     virtual BBinder*    localBinder();
 
+    bool                isRequestingSid();
+    // This must be called before the object is sent to another process. Not thread safe.
+    void                setRequestingSid(bool requestSid);
+
 protected:
     virtual             ~BBinder();
 
@@ -75,6 +79,8 @@
 
     class Extras;
 
+    Extras*             getOrCreateExtras();
+
     std::atomic<Extras*> mExtras;
             void*       mReserved0;
 };
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index a6b0f7e..614b0b3 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -42,6 +42,11 @@
             status_t            clearLastError();
 
             pid_t               getCallingPid() const;
+            // nullptr if unavailable
+            //
+            // this can't be restored once it's cleared, and it does not return the
+            // context of the current process when not in a binder call.
+            const char*         getCallingSid() const;
             uid_t               getCallingUid() const;
 
             void                setStrictModePolicy(int32_t policy);
@@ -64,6 +69,7 @@
             int32_t             getLastTransactionBinderFlags() const;
 
             int64_t             clearCallingIdentity();
+            // Restores PID/UID (not SID)
             void                restoreCallingIdentity(int64_t token);
             
             int                 setupPolling(int* fd);
@@ -174,6 +180,7 @@
             Parcel              mOut;
             status_t            mLastError;
             pid_t               mCallingPid;
+            const char*         mCallingSid;
             uid_t               mCallingUid;
             // The UID of the process who is responsible for this transaction.
             // This is used for resource attribution.
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index cd151ee..240b708 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -27,8 +27,8 @@
 #include <utils/String16.h>
 #include <utils/Vector.h>
 #include <utils/Flattenable.h>
-#include <linux/android/binder.h>
 
+#include <binder/binder_kernel.h>
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
 #include <binder/Map.h>
diff --git a/libs/binder/include/binder/binder_kernel.h b/libs/binder/include/binder/binder_kernel.h
new file mode 100644
index 0000000..c7f6b4b
--- /dev/null
+++ b/libs/binder/include/binder/binder_kernel.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BINDER_KERNEL_H
+#define ANDROID_BINDER_KERNEL_H
+
+#include <linux/android/binder.h>
+
+/**
+ * This file exists because the uapi kernel headers in bionic are built
+ * from upstream kernel headers only, and not all of the hwbinder kernel changes
+ * have made it upstream yet. Therefore, the modifications to the
+ * binder header are added locally in this file.
+ */
+
+enum {
+        FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
+};
+
+#define BINDER_SET_CONTEXT_MGR_EXT      _IOW('b', 13, struct flat_binder_object)
+
+struct binder_transaction_data_secctx {
+        struct binder_transaction_data transaction_data;
+        binder_uintptr_t secctx;
+};
+
+enum {
+        BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+                              struct binder_transaction_data_secctx),
+};
+
+#endif // ANDROID_BINDER_KERNEL_H
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 37c24ef..429ce0e 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -24,7 +24,7 @@
 
 namespace android {
 
-class NativeLoaderNamespace;
+struct NativeLoaderNamespace;
 
 class GraphicsEnv {
 public:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a481e81..ad2dc14 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -66,7 +66,8 @@
     virtual void setTransactionState(const Vector<ComposerState>& state,
                                      const Vector<DisplayState>& displays, uint32_t flags,
                                      const sp<IBinder>& applyToken,
-                                     const InputWindowCommands& commands) {
+                                     const InputWindowCommands& commands,
+                                     int64_t desiredPresentTime) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
 
@@ -83,6 +84,7 @@
         data.writeUint32(flags);
         data.writeStrongBinder(applyToken);
         commands.write(data);
+        data.writeInt64(desiredPresentTime);
         remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
@@ -681,6 +683,54 @@
         result = reply.readUint64Vector(&outStats->component_3_sample);
         return result;
     }
+
+    virtual status_t getProtectedContentSupport(bool* outSupported) const {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT, data, &reply);
+        bool result;
+        status_t err = reply.readBool(&result);
+        if (err == NO_ERROR) {
+            *outSupported = result;
+        }
+        return err;
+    }
+
+    virtual status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
+                                 int32_t* outBufferId) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+
+        data.writeStrongBinder(token);
+        if (buffer) {
+            data.writeBool(true);
+            data.write(*buffer);
+        } else {
+            data.writeBool(false);
+        }
+
+        status_t result = remote()->transact(BnSurfaceComposer::CACHE_BUFFER, data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+
+        int32_t id = -1;
+        result = reply.readInt32(&id);
+        if (result == NO_ERROR) {
+            *outBufferId = id;
+        }
+        return result;
+    }
+
+    virtual status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+
+        data.writeStrongBinder(token);
+        data.writeInt32(bufferId);
+
+        return remote()->transact(BnSurfaceComposer::UNCACHE_BUFFER, data, &reply);
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -736,7 +786,10 @@
             sp<IBinder> applyToken = data.readStrongBinder();
             InputWindowCommands inputWindowCommands;
             inputWindowCommands.read(data);
-            setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands);
+
+            int64_t desiredPresentTime = data.readInt64();
+            setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands,
+                                desiredPresentTime);
             return NO_ERROR;
         }
         case BOOT_FINISHED: {
@@ -1017,7 +1070,7 @@
                 reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
                 reply->writeInt32(static_cast<int32_t>(wideColorGamutPixelFormat));
             }
-            return NO_ERROR;
+            return error;
         }
         case GET_COLOR_MANAGEMENT: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1026,7 +1079,7 @@
             if (error == NO_ERROR) {
                 reply->writeBool(result);
             }
-            return result;
+            return error;
         }
         case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1110,6 +1163,57 @@
             }
             return result;
         }
+        case GET_PROTECTED_CONTENT_SUPPORT: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            bool result;
+            status_t error = getProtectedContentSupport(&result);
+            if (error == NO_ERROR) {
+                reply->writeBool(result);
+            }
+            return error;
+        }
+        case CACHE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> token;
+            status_t result = data.readStrongBinder(&token);
+            if (result != NO_ERROR) {
+                ALOGE("cache buffer failure in reading token: %d", result);
+                return result;
+            }
+
+            sp<GraphicBuffer> buffer = new GraphicBuffer();
+            if (data.readBool()) {
+                result = data.read(*buffer);
+                if (result != NO_ERROR) {
+                    ALOGE("cache buffer failure in reading buffer: %d", result);
+                    return result;
+                }
+            }
+            int32_t bufferId = -1;
+            status_t error = cacheBuffer(token, buffer, &bufferId);
+            if (error == NO_ERROR) {
+                reply->writeInt32(bufferId);
+            }
+            return error;
+        }
+        case UNCACHE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> token;
+            status_t result = data.readStrongBinder(&token);
+            if (result != NO_ERROR) {
+                ALOGE("uncache buffer failure in reading token: %d", result);
+                return result;
+            }
+
+            int32_t bufferId = -1;
+            result = data.readInt32(&bufferId);
+            if (result != NO_ERROR) {
+                ALOGE("uncache buffer failure in reading buffer id: %d", result);
+                return result;
+            }
+
+            return uncacheBuffer(token, bufferId);
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 1be55e6..ce88d7b 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -39,7 +39,16 @@
     if (err != NO_ERROR) {
         return err;
     }
-    return output->writeBool(releasePreviousBuffer);
+    if (previousReleaseFence) {
+        err = output->writeBool(true);
+        if (err != NO_ERROR) {
+            return err;
+        }
+        err = output->write(*previousReleaseFence);
+    } else {
+        err = output->writeBool(false);
+    }
+    return err;
 }
 
 status_t SurfaceStats::readFromParcel(const Parcel* input) {
@@ -51,7 +60,19 @@
     if (err != NO_ERROR) {
         return err;
     }
-    return input->readBool(&releasePreviousBuffer);
+    bool hasFence = false;
+    err = input->readBool(&hasFence);
+    if (err != NO_ERROR) {
+        return err;
+    }
+    if (hasFence) {
+        previousReleaseFence = new Fence();
+        err = input->read(*previousReleaseFence);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+    return NO_ERROR;
 }
 
 status_t TransactionStats::writeToParcel(Parcel* output) const {
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e5170ab..40b55fa 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -94,6 +94,9 @@
         }
     }
 
+    output.writeStrongBinder(cachedBuffer.token);
+    output.writeInt32(cachedBuffer.bufferId);
+
     return NO_ERROR;
 }
 
@@ -164,6 +167,9 @@
         listenerCallbacks.emplace_back(listener, callbackIds);
     }
 
+    cachedBuffer.token = input.readStrongBinder();
+    cachedBuffer.bufferId = input.readInt32();
+
     return NO_ERROR;
 }
 
@@ -372,6 +378,10 @@
     }
 #endif
 
+    if (other.what & eCachedBufferChanged) {
+        what |= eCachedBufferChanged;
+        cachedBuffer = other.cachedBuffer;
+    }
     if ((other.what & what) != other.what) {
         ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
               "other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index a7c7e79..73150dc 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -1,8 +1,7 @@
-brianderson@google.com
 jessehall@google.com
 jwcai@google.com
+lpy@google.com
+marissaw@google.com
 mathias@google.com
-olv@google.com
-pceballos@google.com
 racarr@google.com
 stoza@google.com
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8b9e4d7..a82054b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -159,11 +159,12 @@
 
 // ---------------------------------------------------------------------------
 
-SurfaceComposerClient::Transaction::Transaction(const Transaction& other) :
-    mForceSynchronous(other.mForceSynchronous),
-    mTransactionNestCount(other.mTransactionNestCount),
-    mAnimation(other.mAnimation),
-    mEarlyWakeup(other.mEarlyWakeup) {
+SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
+      : mForceSynchronous(other.mForceSynchronous),
+        mTransactionNestCount(other.mTransactionNestCount),
+        mAnimation(other.mAnimation),
+        mEarlyWakeup(other.mEarlyWakeup),
+        mDesiredPresentTime(other.mDesiredPresentTime) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
     mInputWindowCommands = other.mInputWindowCommands;
@@ -218,7 +219,7 @@
     s.state.parentHandleForChild = nullptr;
 
     composerStates.add(s);
-    sf->setTransactionState(composerStates, displayStates, 0, nullptr, {});
+    sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1);
 }
 
 status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
@@ -284,7 +285,8 @@
     mEarlyWakeup = false;
 
     sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
-    sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands);
+    sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands,
+                            mDesiredPresentTime);
     mInputWindowCommands.clear();
     mStatus = NO_ERROR;
     return NO_ERROR;
@@ -658,6 +660,21 @@
     return *this;
 }
 
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCachedBuffer(
+        const sp<SurfaceControl>& sc, int32_t bufferId) {
+    layer_state_t* s = getLayerState(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+    s->what |= layer_state_t::eCachedBufferChanged;
+    s->cachedBuffer.token = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    s->cachedBuffer.bufferId = bufferId;
+
+    registerSurfaceControlForCallback(sc);
+    return *this;
+}
+
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence(
         const sp<SurfaceControl>& sc, const sp<Fence>& fence) {
     layer_state_t* s = getLayerState(sc);
@@ -742,6 +759,12 @@
     return *this;
 }
 
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime(
+        nsecs_t desiredPresentTime) {
+    mDesiredPresentTime = desiredPresentTime;
+    return *this;
+}
+
 SurfaceComposerClient::Transaction&
 SurfaceComposerClient::Transaction::addTransactionCompletedCallback(
         TransactionCompletedCallbackTakesContext callback, void* callbackContext) {
@@ -1049,6 +1072,26 @@
 
 // ----------------------------------------------------------------------------
 
+status_t SurfaceComposerClient::cacheBuffer(const sp<GraphicBuffer>& buffer, int32_t* outBufferId) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    if (buffer == nullptr || outBufferId == nullptr) {
+        return BAD_VALUE;
+    }
+    return sf->cacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()),
+                           buffer, outBufferId);
+}
+
+status_t SurfaceComposerClient::uncacheBuffer(int32_t bufferId) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    if (bufferId < 0) {
+        return BAD_VALUE;
+    }
+    return sf->uncacheBuffer(IInterface::asBinder(TransactionCompletedListener::getIInstance()),
+                             bufferId);
+}
+
+// ----------------------------------------------------------------------------
+
 status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     return sf->enableVSyncInjections(enable);
@@ -1118,6 +1161,12 @@
                                        wideColorGamutDataspace, wideColorGamutPixelFormat);
 }
 
+bool SurfaceComposerClient::getProtectedContentSupport() {
+    bool supported = false;
+    ComposerService::getComposerService()->getProtectedContentSupport(&supported);
+    return supported;
+}
+
 status_t SurfaceComposerClient::clearAnimationFrameStats() {
     return ComposerService::getComposerService()->clearAnimationFrameStats();
 }
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 537c957..b377a41 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -40,13 +40,14 @@
 #define BQ_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
 #define BQ_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
 
-#define ATRACE_BUFFER_INDEX(index)                                   \
-    if (ATRACE_ENABLED()) {                                          \
-        char ___traceBuf[1024];                                      \
-        snprintf(___traceBuf, 1024, "%s: %d",                        \
-                mCore->mConsumerName.string(), (index));             \
-        android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);  \
-    }
+#define ATRACE_BUFFER_INDEX(index)                                                         \
+    do {                                                                                   \
+        if (ATRACE_ENABLED()) {                                                            \
+            char ___traceBuf[1024];                                                        \
+            snprintf(___traceBuf, 1024, "%s: %d", mCore->mConsumerName.string(), (index)); \
+            android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);                    \
+        }                                                                                  \
+    } while (false)
 
 namespace android {
 
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1534fca..418d5fb 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -116,7 +116,8 @@
     virtual void setTransactionState(const Vector<ComposerState>& state,
                                      const Vector<DisplayState>& displays, uint32_t flags,
                                      const sp<IBinder>& applyToken,
-                                     const InputWindowCommands& inputWindowCommands) = 0;
+                                     const InputWindowCommands& inputWindowCommands,
+                                     int64_t desiredPresentTime) = 0;
 
     /* signal that we're done booting.
      * Requires ACCESS_SURFACE_FLINGER permission
@@ -309,6 +310,17 @@
     virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
                                                uint64_t timestamp,
                                                DisplayedFrameStats* outStats) const = 0;
+
+    /*
+     * Gets whether SurfaceFlinger can support protected content in GPU composition.
+     * Requires the ACCESS_SURFACE_FLINGER permission.
+     */
+    virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
+
+    virtual status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
+                                 int32_t* outBufferId) = 0;
+
+    virtual status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -350,6 +362,9 @@
         GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
         SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
         GET_DISPLAYED_CONTENT_SAMPLE,
+        GET_PROTECTED_CONTENT_SUPPORT,
+        CACHE_BUFFER,
+        UNCACHE_BUFFER,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index 8acfa7a..29ab026 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -52,12 +52,12 @@
     status_t readFromParcel(const Parcel* input) override;
 
     SurfaceStats() = default;
-    SurfaceStats(const sp<IBinder>& sc, nsecs_t time, bool releasePrevBuffer)
-          : surfaceControl(sc), acquireTime(time), releasePreviousBuffer(releasePrevBuffer) {}
+    SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence)
+          : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence) {}
 
     sp<IBinder> surfaceControl;
     nsecs_t acquireTime = -1;
-    bool releasePreviousBuffer = false;
+    sp<Fence> previousReleaseFence;
 };
 
 class TransactionStats : public Parcelable {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index e7564f5..af31420 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -84,6 +84,7 @@
         eInputInfoChanged = 0x40000000,
         eCornerRadiusChanged = 0x80000000,
         eFrameChanged = 0x1'00000000,
+        eCachedBufferChanged = 0x2'00000000,
     };
 
     layer_state_t()
@@ -125,6 +126,10 @@
         float dtdy{0};
         float dsdy{0};
     };
+    struct cached_buffer_t {
+        sp<IBinder> token = nullptr;
+        int32_t bufferId = -1;
+    };
     sp<IBinder> surface;
     uint64_t what;
     float x;
@@ -173,6 +178,8 @@
 #ifndef NO_INPUT
     InputWindowInfo inputInfo;
 #endif
+
+    cached_buffer_t cachedBuffer;
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index f16f781..db315c2 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -145,6 +145,12 @@
                                              ui::Dataspace* wideColorGamutDataspace,
                                              ui::PixelFormat* wideColorGamutPixelFormat);
 
+    /*
+     * Gets whether SurfaceFlinger can support protected content in GPU composition.
+     * Requires the ACCESS_SURFACE_FLINGER permission.
+     */
+    static bool getProtectedContentSupport();
+
     /**
      * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it
      * to null), but without needing an sp<SurfaceControl> to avoid infinite ressurection.
@@ -152,6 +158,12 @@
     static void doDropReferenceTransaction(const sp<IBinder>& handle,
             const sp<ISurfaceComposerClient>& client);
 
+    // Caches a buffer with the ISurfaceComposer so the buffer does not need to be resent across
+    // processes
+    static status_t cacheBuffer(const sp<GraphicBuffer>& buffer, int32_t* outBufferId);
+    // Uncaches a buffer set by cacheBuffer
+    static status_t uncacheBuffer(int32_t bufferId);
+
     // ------------------------------------------------------------------------
     // surface creation / destruction
 
@@ -237,6 +249,18 @@
         bool                        mAnimation = false;
         bool                        mEarlyWakeup = false;
 
+        // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction
+        // to be presented. When it is not possible to present at exactly that time, it will be
+        // presented after the time has passed.
+        //
+        // Desired present times that are more than 1 second in the future may be ignored.
+        // When a desired present time has already passed, the transaction will be presented as soon
+        // as possible.
+        //
+        // Transactions from the same process are presented in the same order that they are applied.
+        // The desired present time does not affect this ordering.
+        int64_t mDesiredPresentTime = -1;
+
         InputWindowCommands mInputWindowCommands;
         int mStatus = NO_ERROR;
 
@@ -317,6 +341,7 @@
         Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
         Transaction& setFrame(const sp<SurfaceControl>& sc, const Rect& frame);
         Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer);
+        Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId);
         Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence);
         Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
         Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata);
@@ -325,6 +350,7 @@
         Transaction& setApi(const sp<SurfaceControl>& sc, int32_t api);
         Transaction& setSidebandStream(const sp<SurfaceControl>& sc,
                                        const sp<NativeHandle>& sidebandStream);
+        Transaction& setDesiredPresentTime(nsecs_t desiredPresentTime);
 
         Transaction& addTransactionCompletedCallback(
                 TransactionCompletedCallbackTakesContext callback, void* callbackContext);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 7fc69ff..ac97733 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -489,5 +489,13 @@
     toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1);
     fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP);
 }
+
+TEST_F(InputSurfacesTest, input_respects_outscreen) {
+    std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+    surface->showAt(-1, -1);
+
+    injectTap(0, 0);
+    surface->expectTap(1, 1);
+}
 }
 }
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 60173dc..259ef9f 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -556,7 +556,9 @@
     void setTransactionState(const Vector<ComposerState>& /*state*/,
                              const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
                              const sp<IBinder>& /*applyToken*/,
-                             const InputWindowCommands& /*inputWindowCommands*/) override {}
+                             const InputWindowCommands& /*inputWindowCommands*/,
+                             int64_t /*desiredPresentTime*/) override {}
+
     void bootFinished() override {}
     bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& /*surface*/) const override {
@@ -655,7 +657,14 @@
         return NO_ERROR;
     }
 
-    virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; }
+    status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
+    status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
+
+    status_t cacheBuffer(const sp<IBinder>& /*token*/, const sp<GraphicBuffer>& /*buffer*/,
+                         int32_t* /*outBufferId*/) {
+        return NO_ERROR;
+    }
+    status_t uncacheBuffer(const sp<IBinder>& /*token*/, int32_t /*bufferId*/) { return NO_ERROR; }
 
 protected:
     IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index db86c8e..9fd25f9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -29,6 +29,17 @@
 
 namespace android {
 
+const char* motionClassificationToString(MotionClassification classification) {
+    switch (classification) {
+        case MotionClassification::NONE:
+            return "NONE";
+        case MotionClassification::AMBIGUOUS_GESTURE:
+            return "AMBIGUOUS_GESTURE";
+        case MotionClassification::DEEP_PRESS:
+            return "DEEP_PRESS";
+    }
+}
+
 // --- InputEvent ---
 
 void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 0ddee44..0f7a1f0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -157,6 +157,8 @@
             msg->body.motion.metaState = body.motion.metaState;
             // int32_t buttonState
             msg->body.motion.buttonState = body.motion.buttonState;
+            // MotionClassification classification
+            msg->body.motion.classification = body.motion.classification;
             // int32_t edgeFlags
             msg->body.motion.edgeFlags = body.motion.edgeFlags;
             // nsecs_t downTime
@@ -448,6 +450,7 @@
         int32_t edgeFlags,
         int32_t metaState,
         int32_t buttonState,
+        MotionClassification classification,
         float xOffset,
         float yOffset,
         float xPrecision,
@@ -461,13 +464,13 @@
     ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
             "displayId=%" PRId32 ", "
             "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
-            "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
+            "metaState=0x%x, buttonState=0x%x, classification=%s, xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
             "pointerCount=%" PRIu32,
             mChannel->getName().c_str(), seq,
             deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState,
-            buttonState, xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime,
-            pointerCount);
+            buttonState, motionClassificationToString(classification),
+            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
 #endif
 
     if (!seq) {
@@ -493,6 +496,7 @@
     msg.body.motion.edgeFlags = edgeFlags;
     msg.body.motion.metaState = metaState;
     msg.body.motion.buttonState = buttonState;
+    msg.body.motion.classification = classification;
     msg.body.motion.xOffset = xOffset;
     msg.body.motion.yOffset = yOffset;
     msg.body.motion.xPrecision = xPrecision;
@@ -1112,7 +1116,7 @@
             msg->body.motion.edgeFlags,
             msg->body.motion.metaState,
             msg->body.motion.buttonState,
-            MotionClassification::NONE,
+            msg->body.motion.classification,
             msg->body.motion.xOffset,
             msg->body.motion.yOffset,
             msg->body.motion.xPrecision,
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index 96c165c..f1675c0 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <array>
+
 #include "TestHelpers.h"
 
 #include <unistd.h>
@@ -155,5 +157,37 @@
             << "sendMessage should have returned DEAD_OBJECT";
 }
 
+TEST_F(InputChannelTest, SendAndReceive_MotionClassification) {
+    sp<InputChannel> serverChannel, clientChannel;
+    status_t result = InputChannel::openInputChannelPair("channel name",
+            serverChannel, clientChannel);
+    ASSERT_EQ(OK, result)
+            << "should have successfully opened a channel pair";
+
+    std::array<MotionClassification, 3> classifications = {
+        MotionClassification::NONE,
+        MotionClassification::AMBIGUOUS_GESTURE,
+        MotionClassification::DEEP_PRESS,
+    };
+
+    InputMessage serverMsg = {}, clientMsg;
+    serverMsg.header.type = InputMessage::TYPE_MOTION;
+    serverMsg.body.motion.seq = 1;
+    serverMsg.body.motion.pointerCount = 1;
+
+    for (MotionClassification classification : classifications) {
+        // Send and receive a message with classification
+        serverMsg.body.motion.classification = classification;
+        EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg))
+                << "server channel should be able to send message to client channel";
+
+        EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg))
+                << "client channel should be able to receive message from server channel";
+        EXPECT_EQ(serverMsg.header.type, clientMsg.header.type);
+        EXPECT_EQ(classification, clientMsg.body.motion.classification) <<
+                "Expected to receive " << motionClassificationToString(classification);
+    }
+}
+
 
 } // namespace android
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index e4c1514..2b75c82 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <array>
 #include <math.h>
 
 #include <binder/Parcel.h>
@@ -25,11 +26,7 @@
 // Default display id.
 static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
 
-class BaseTest : public testing::Test {
-protected:
-    virtual void SetUp() { }
-    virtual void TearDown() { }
-};
+class BaseTest : public testing::Test { };
 
 // --- PointerCoordsTest ---
 
@@ -316,6 +313,7 @@
     ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
     ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
     ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
+    ASSERT_EQ(MotionClassification::NONE, event->getClassification());
     ASSERT_EQ(X_OFFSET, event->getXOffset());
     ASSERT_EQ(Y_OFFSET, event->getYOffset());
     ASSERT_EQ(2.0f, event->getXPrecision());
@@ -609,4 +607,30 @@
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
 }
 
+TEST_F(MotionEventTest, Initialize_SetsClassification) {
+    std::array<MotionClassification, 3> classifications = {
+            MotionClassification::NONE,
+            MotionClassification::AMBIGUOUS_GESTURE,
+            MotionClassification::DEEP_PRESS,
+    };
+
+    MotionEvent event;
+    constexpr size_t pointerCount = 1;
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
+        pointerCoords[i].clear();
+    }
+
+    for (MotionClassification classification : classifications) {
+        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+                AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
+                classification, 0, 0, 0, 0, 0 /*downTime*/, 0 /*eventTime*/,
+                pointerCount, pointerProperties, pointerCoords);
+        ASSERT_EQ(classification, event.getClassification());
+    }
+}
+
 } // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 0788c89..f2cd1be 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -141,6 +141,7 @@
     constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
     constexpr int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
+    constexpr MotionClassification classification = MotionClassification::AMBIGUOUS_GESTURE;
     constexpr float xOffset = -10;
     constexpr float yOffset = -20;
     constexpr float xPrecision = 0.25;
@@ -168,8 +169,8 @@
     }
 
     status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
-            flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
-            downTime, eventTime, pointerCount,
+            flags, edgeFlags, metaState, buttonState, classification,
+            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount,
             pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
@@ -195,6 +196,7 @@
     EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
     EXPECT_EQ(metaState, motionEvent->getMetaState());
     EXPECT_EQ(buttonState, motionEvent->getButtonState());
+    EXPECT_EQ(classification, motionEvent->getClassification());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
@@ -264,7 +266,8 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -276,7 +279,8 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -293,7 +297,8 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 12a6782..62023fb 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -57,7 +57,8 @@
   CHECK_OFFSET(InputMessage::Body::Motion, flags, 36);
   CHECK_OFFSET(InputMessage::Body::Motion, metaState, 40);
   CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 44);
-  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, classification, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 52);
   CHECK_OFFSET(InputMessage::Body::Motion, downTime, 56);
   CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 64);
   CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
new file mode 100644
index 0000000..6fb149a
--- /dev/null
+++ b/libs/math/OWNERS
@@ -0,0 +1,6 @@
+jaesoo@google.com
+jiyong@google.com
+mathias@google.com
+pawin@google.com
+randolphs@google.com
+romainguy@google.com
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 2915bb8..f57bf9c 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -1280,7 +1280,7 @@
             std::lock_guard<std::mutex> lock(mMutex);
 
             mCondition.wait(mMutex,
-                            [&]() REQUIRES(mMutex) { return !mQueue.empty() && !mRunning; });
+                            [&]() REQUIRES(mMutex) { return !mQueue.empty() || !mRunning; });
 
             if (!mRunning) {
                 // if mRunning is false, then FlushTracer is being destroyed, so
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 6926f7f..324d443 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -57,15 +57,15 @@
             uint8_t b[16];
             int64_t i64[2];
         };
-        uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+        explicit uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
         uuid_t() : b{0} {}
     };
 
     Sensor(const Sensor&) = default;
     Sensor& operator=(const Sensor&) = default;
 
-    Sensor(const char * name = "");
-    Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+    explicit Sensor(const char * name = "");
+    explicit Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
     Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
     ~Sensor();
 
diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h
index baed2ee..8176578 100644
--- a/libs/sensor/include/sensor/SensorEventQueue.h
+++ b/libs/sensor/include/sensor/SensorEventQueue.h
@@ -64,7 +64,7 @@
     // Default sensor sample period
     static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
 
-    SensorEventQueue(const sp<ISensorEventConnection>& connection);
+    explicit SensorEventQueue(const sp<ISensorEventConnection>& connection);
     virtual ~SensorEventQueue();
     virtual void onFirstRef();
 
diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h
index 23f7a91..f09c9c6 100644
--- a/libs/sensor/include/sensor/SensorManager.h
+++ b/libs/sensor/include/sensor/SensorManager.h
@@ -71,7 +71,7 @@
     void sensorManagerDied();
     static status_t waitForSensorService(sp<ISensorServer> *server);
 
-    SensorManager(const String16& opPackageName);
+    explicit SensorManager(const String16& opPackageName);
     status_t assertStateLocked();
 
 private:
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index e8b038b..74450d7 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -60,7 +60,9 @@
         "Fence.cpp",
         "FenceTime.cpp",
         "FrameStats.cpp",
+        "Gralloc.cpp",
         "Gralloc2.cpp",
+        "Gralloc3.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
@@ -80,9 +82,11 @@
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore-utils",
         "libbase",
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 052e650..6310f29 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -319,11 +319,6 @@
             mMetadata.IsValid() && mBufferClient != nullptr;
 }
 
-// TODO(b/68770788): implement Poll() once we have event fd
-int BufferHubBuffer::Poll(int /* timeoutMs */) {
-    return -ENOSYS;
-}
-
 native_handle_t* BufferHubBuffer::Duplicate() {
     if (mBufferClient == nullptr) {
         ALOGE("%s: missing BufferClient!", __FUNCTION__);
diff --git a/libs/ui/Gralloc.cpp b/libs/ui/Gralloc.cpp
new file mode 100644
index 0000000..8e09a13
--- /dev/null
+++ b/libs/ui/Gralloc.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Gralloc"
+
+#include <ui/Gralloc.h>
+
+namespace android {
+
+GrallocMapper::~GrallocMapper() {}
+
+GrallocAllocator::~GrallocAllocator() {}
+
+} // namespace android
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 20f27c5..ea7321e 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -27,9 +27,15 @@
 #include <sync/sync.h>
 #pragma clang diagnostic pop
 
-namespace android {
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::graphics::common::V1_1::BufferUsage;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V2_0::Error;
+using android::hardware::graphics::mapper::V2_0::YCbCrLayout;
+using android::hardware::graphics::mapper::V2_1::IMapper;
 
-namespace Gralloc2 {
+namespace android {
 
 namespace {
 
@@ -59,17 +65,26 @@
     return valid11UsageBits;
 }
 
+static inline IMapper::Rect sGralloc2Rect(const Rect& rect) {
+    IMapper::Rect outRect{};
+    outRect.left = rect.left;
+    outRect.top = rect.top;
+    outRect.width = rect.width();
+    outRect.height = rect.height();
+    return outRect;
+}
+
 }  // anonymous namespace
 
-void Mapper::preload() {
+void Gralloc2Mapper::preload() {
     android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
 }
 
-Mapper::Mapper()
-{
+Gralloc2Mapper::Gralloc2Mapper() {
     mMapper = hardware::graphics::mapper::V2_0::IMapper::getService();
     if (mMapper == nullptr) {
-        LOG_ALWAYS_FATAL("gralloc-mapper is missing");
+        ALOGW("mapper 2.x is not supported");
+        return;
     }
     if (mMapper->isRemote()) {
         LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
@@ -79,30 +94,37 @@
     mMapperV2_1 = IMapper::castFrom(mMapper);
 }
 
-Gralloc2::Error Mapper::validateBufferDescriptorInfo(
-        const IMapper::BufferDescriptorInfo& descriptorInfo) const {
+bool Gralloc2Mapper::isSupported() const {
+    return mMapper != nullptr;
+}
+
+status_t Gralloc2Mapper::validateBufferDescriptorInfo(
+        IMapper::BufferDescriptorInfo* descriptorInfo) const {
     uint64_t validUsageBits = getValid10UsageBits();
     if (mMapperV2_1 != nullptr) {
         validUsageBits = validUsageBits | getValid11UsageBits();
     }
 
-    if (descriptorInfo.usage & ~validUsageBits) {
+    if (descriptorInfo->usage & ~validUsageBits) {
         ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
-              descriptorInfo.usage & ~validUsageBits);
-        return Error::BAD_VALUE;
+              descriptorInfo->usage & ~validUsageBits);
+        return BAD_VALUE;
     }
-    return Error::NONE;
+    return NO_ERROR;
 }
 
-Error Mapper::createDescriptor(
-        const IMapper::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor* outDescriptor) const
-{
-    Error error = validateBufferDescriptorInfo(descriptorInfo);
-    if (error != Error::NONE) {
-        return error;
+status_t Gralloc2Mapper::createDescriptor(void* bufferDescriptorInfo,
+                                          void* outBufferDescriptor) const {
+    IMapper::BufferDescriptorInfo* descriptorInfo =
+            static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
+    BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
+
+    status_t status = validateBufferDescriptorInfo(descriptorInfo);
+    if (status != NO_ERROR) {
+        return status;
     }
 
+    Error error;
     auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor)
                    {
                        error = tmpError;
@@ -115,24 +137,23 @@
 
     hardware::Return<void> ret;
     if (mMapperV2_1 != nullptr) {
-        ret = mMapperV2_1->createDescriptor_2_1(descriptorInfo, hidl_cb);
+        ret = mMapperV2_1->createDescriptor_2_1(*descriptorInfo, hidl_cb);
     } else {
         const hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo info = {
-            descriptorInfo.width,
-            descriptorInfo.height,
-            descriptorInfo.layerCount,
-            static_cast<hardware::graphics::common::V1_0::PixelFormat>(descriptorInfo.format),
-            descriptorInfo.usage,
+                descriptorInfo->width,
+                descriptorInfo->height,
+                descriptorInfo->layerCount,
+                static_cast<hardware::graphics::common::V1_0::PixelFormat>(descriptorInfo->format),
+                descriptorInfo->usage,
         };
         ret = mMapper->createDescriptor(info, hidl_cb);
     }
 
-    return (ret.isOk()) ? error : kTransactionError;
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
 }
 
-Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
-        buffer_handle_t* outBufferHandle) const
-{
+status_t Gralloc2Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+                                      buffer_handle_t* outBufferHandle) const {
     Error error;
     auto ret = mMapper->importBuffer(rawHandle,
             [&](const auto& tmpError, const auto& tmpBuffer)
@@ -145,11 +166,10 @@
                 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
             });
 
-    return (ret.isOk()) ? error : kTransactionError;
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
 }
 
-void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
-{
+void Gralloc2Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
     auto ret = mMapper->freeBuffer(buffer);
 
@@ -158,23 +178,29 @@
             buffer, error);
 }
 
-Error Mapper::validateBufferSize(buffer_handle_t bufferHandle,
-        const IMapper::BufferDescriptorInfo& descriptorInfo,
-        uint32_t stride) const
-{
+status_t Gralloc2Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
+                                            uint32_t height, android::PixelFormat format,
+                                            uint32_t layerCount, uint64_t usage,
+                                            uint32_t stride) const {
     if (mMapperV2_1 == nullptr) {
-        return Error::NONE;
+        return NO_ERROR;
     }
 
+    IMapper::BufferDescriptorInfo descriptorInfo = {};
+    descriptorInfo.width = width;
+    descriptorInfo.height = height;
+    descriptorInfo.layerCount = layerCount;
+    descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
+    descriptorInfo.usage = usage;
+
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
     auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride);
 
-    return (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+    return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
 }
 
-void Mapper::getTransportSize(buffer_handle_t bufferHandle,
-        uint32_t* outNumFds, uint32_t* outNumInts) const
-{
+void Gralloc2Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
+                                      uint32_t* outNumInts) const {
     *outNumFds = uint32_t(bufferHandle->numFds);
     *outNumInts = uint32_t(bufferHandle->numInts);
 
@@ -195,19 +221,17 @@
                 *outNumInts = tmpNumInts;
             });
 
-    if (!ret.isOk()) {
-        error = kTransactionError;
-    }
-    ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d",
-            buffer, error);
+    error = (ret.isOk()) ? error : kTransactionError;
+
+    ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
 }
 
-Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, void** outData) const
-{
+status_t Gralloc2Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                              int acquireFence, void** outData) const {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
+    IMapper::Rect accessRegion = sGralloc2Rect(bounds);
+
     // put acquireFence in a hidl_handle
     hardware::hidl_handle acquireFenceHandle;
     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
@@ -234,15 +258,19 @@
         close(acquireFence);
     }
 
-    return (ret.isOk()) ? error : kTransactionError;
+    error = (ret.isOk()) ? error : kTransactionError;
+
+    ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
+
+    return static_cast<status_t>(error);
 }
 
-Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
-        const IMapper::Rect& accessRegion,
-        int acquireFence, YCbCrLayout* outLayout) const
-{
+status_t Gralloc2Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                              int acquireFence, android_ycbcr* ycbcr) const {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
+    IMapper::Rect accessRegion = sGralloc2Rect(bounds);
+
     // put acquireFence in a hidl_handle
     hardware::hidl_handle acquireFenceHandle;
     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
@@ -252,6 +280,7 @@
         acquireFenceHandle = h;
     }
 
+    YCbCrLayout layout;
     Error error;
     auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
             acquireFenceHandle,
@@ -262,19 +291,27 @@
                     return;
                 }
 
-                *outLayout = tmpLayout;
+                layout = tmpLayout;
             });
 
+    if (error == Error::NONE) {
+        ycbcr->y = layout.y;
+        ycbcr->cb = layout.cb;
+        ycbcr->cr = layout.cr;
+        ycbcr->ystride = static_cast<size_t>(layout.yStride);
+        ycbcr->cstride = static_cast<size_t>(layout.cStride);
+        ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
+    }
+
     // we own acquireFence even on errors
     if (acquireFence >= 0) {
         close(acquireFence);
     }
 
-    return (ret.isOk()) ? error : kTransactionError;
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
 }
 
-int Mapper::unlock(buffer_handle_t bufferHandle) const
-{
+int Gralloc2Mapper::unlock(buffer_handle_t bufferHandle) const {
     auto buffer = const_cast<native_handle_t*>(bufferHandle);
 
     int releaseFence = -1;
@@ -299,10 +336,7 @@
                 }
             });
 
-    if (!ret.isOk()) {
-        error = kTransactionError;
-    }
-
+    error = (ret.isOk()) ? error : kTransactionError;
     if (error != Error::NONE) {
         ALOGE("unlock(%p) failed with %d", buffer, error);
     }
@@ -310,17 +344,19 @@
     return releaseFence;
 }
 
-Allocator::Allocator(const Mapper& mapper)
-    : mMapper(mapper)
-{
+Gralloc2Allocator::Gralloc2Allocator(const Gralloc2Mapper& mapper) : mMapper(mapper) {
     mAllocator = IAllocator::getService();
     if (mAllocator == nullptr) {
-        LOG_ALWAYS_FATAL("gralloc-alloc is missing");
+        ALOGW("allocator 2.x is not supported");
+        return;
     }
 }
 
-std::string Allocator::dumpDebugInfo() const
-{
+bool Gralloc2Allocator::isSupported() const {
+    return mAllocator != nullptr;
+}
+
+std::string Gralloc2Allocator::dumpDebugInfo() const {
     std::string debugInfo;
 
     mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
@@ -330,40 +366,51 @@
     return debugInfo;
 }
 
-Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
-        uint32_t* outStride, buffer_handle_t* outBufferHandles) const
-{
-    Error error;
-    auto ret = mAllocator->allocate(descriptor, count,
-            [&](const auto& tmpError, const auto& tmpStride,
-                const auto& tmpBuffers) {
-                error = tmpError;
-                if (tmpError != Error::NONE) {
-                    return;
-                }
+status_t Gralloc2Allocator::allocate(uint32_t width, uint32_t height, PixelFormat format,
+                                     uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
+                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
+    IMapper::BufferDescriptorInfo descriptorInfo = {};
+    descriptorInfo.width = width;
+    descriptorInfo.height = height;
+    descriptorInfo.layerCount = layerCount;
+    descriptorInfo.format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
+    descriptorInfo.usage = usage;
 
-                // import buffers
-                for (uint32_t i = 0; i < count; i++) {
-                    error = mMapper.importBuffer(tmpBuffers[i],
-                            &outBufferHandles[i]);
-                    if (error != Error::NONE) {
-                        for (uint32_t j = 0; j < i; j++) {
-                            mMapper.freeBuffer(outBufferHandles[j]);
-                            outBufferHandles[j] = nullptr;
-                        }
-                        return;
-                    }
-                }
+    BufferDescriptor descriptor;
+    status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
+                                              static_cast<void*>(&descriptor));
+    if (error != NO_ERROR) {
+        return error;
+    }
 
-                *outStride = tmpStride;
-            });
+    auto ret = mAllocator->allocate(descriptor, bufferCount,
+                                    [&](const auto& tmpError, const auto& tmpStride,
+                                        const auto& tmpBuffers) {
+                                        error = static_cast<status_t>(tmpError);
+                                        if (tmpError != Error::NONE) {
+                                            return;
+                                        }
+
+                                        // import buffers
+                                        for (uint32_t i = 0; i < bufferCount; i++) {
+                                            error = mMapper.importBuffer(tmpBuffers[i],
+                                                                         &outBufferHandles[i]);
+                                            if (error != NO_ERROR) {
+                                                for (uint32_t j = 0; j < i; j++) {
+                                                    mMapper.freeBuffer(outBufferHandles[j]);
+                                                    outBufferHandles[j] = nullptr;
+                                                }
+                                                return;
+                                            }
+                                        }
+
+                                        *outStride = tmpStride;
+                                    });
 
     // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
     hardware::IPCThreadState::self()->flushCommands();
 
-    return (ret.isOk()) ? error : kTransactionError;
+    return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
 }
 
-} // namespace Gralloc2
-
 } // namespace android
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
new file mode 100644
index 0000000..128200e
--- /dev/null
+++ b/libs/ui/Gralloc3.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Gralloc3"
+
+#include <hidl/ServiceManagement.h>
+#include <hwbinder/IPCThreadState.h>
+#include <ui/Gralloc3.h>
+
+#include <inttypes.h>
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+using android::hardware::graphics::allocator::V3_0::IAllocator;
+using android::hardware::graphics::common::V1_1::BufferUsage;
+using android::hardware::graphics::mapper::V3_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V3_0::Error;
+using android::hardware::graphics::mapper::V3_0::IMapper;
+using android::hardware::graphics::mapper::V3_0::YCbCrLayout;
+
+namespace android {
+
+namespace {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+uint64_t getValidUsageBits() {
+    static const uint64_t validUsageBits = []() -> uint64_t {
+        uint64_t bits = 0;
+        for (const auto bit :
+             hardware::hidl_enum_range<hardware::graphics::common::V1_0::BufferUsage>()) {
+            bits = bits | bit;
+        }
+        for (const auto bit :
+             hardware::hidl_enum_range<hardware::graphics::common::V1_1::BufferUsage>()) {
+            bits = bits | bit;
+        }
+        return bits;
+    }();
+    return validUsageBits;
+}
+
+static inline IMapper::Rect sGralloc3Rect(const Rect& rect) {
+    IMapper::Rect outRect{};
+    outRect.left = rect.left;
+    outRect.top = rect.top;
+    outRect.width = rect.width();
+    outRect.height = rect.height();
+    return outRect;
+}
+static inline void sBufferDescriptorInfo(uint32_t width, uint32_t height,
+                                         android::PixelFormat format, uint32_t layerCount,
+                                         uint64_t usage,
+                                         IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+    outDescriptorInfo->width = width;
+    outDescriptorInfo->height = height;
+    outDescriptorInfo->layerCount = layerCount;
+    outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_1::PixelFormat>(format);
+    outDescriptorInfo->usage = usage;
+}
+
+} // anonymous namespace
+
+void Gralloc3Mapper::preload() {
+    android::hardware::preloadPassthroughService<IMapper>();
+}
+
+Gralloc3Mapper::Gralloc3Mapper() {
+    mMapper = IMapper::getService();
+    if (mMapper == nullptr) {
+        ALOGW("mapper 3.x is not supported");
+        return;
+    }
+    if (mMapper->isRemote()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+    }
+}
+
+bool Gralloc3Mapper::isSupported() const {
+    return mMapper != nullptr;
+}
+
+status_t Gralloc3Mapper::validateBufferDescriptorInfo(
+        IMapper::BufferDescriptorInfo* descriptorInfo) const {
+    uint64_t validUsageBits = getValidUsageBits();
+
+    if (descriptorInfo->usage & ~validUsageBits) {
+        ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
+              descriptorInfo->usage & ~validUsageBits);
+        return BAD_VALUE;
+    }
+    return NO_ERROR;
+}
+
+status_t Gralloc3Mapper::createDescriptor(void* bufferDescriptorInfo,
+                                          void* outBufferDescriptor) const {
+    IMapper::BufferDescriptorInfo* descriptorInfo =
+            static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
+    BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
+
+    status_t status = validateBufferDescriptorInfo(descriptorInfo);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    Error error;
+    auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
+        error = tmpError;
+        if (error != Error::NONE) {
+            return;
+        }
+        *outDescriptor = tmpDescriptor;
+    };
+
+    hardware::Return<void> ret = mMapper->createDescriptor(*descriptorInfo, hidl_cb);
+
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
+}
+
+status_t Gralloc3Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+                                      buffer_handle_t* outBufferHandle) const {
+    Error error;
+    auto ret = mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+        error = tmpError;
+        if (error != Error::NONE) {
+            return;
+        }
+        *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+    });
+
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
+}
+
+void Gralloc3Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->freeBuffer(buffer);
+
+    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+    ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
+}
+
+status_t Gralloc3Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
+                                            uint32_t height, android::PixelFormat format,
+                                            uint32_t layerCount, uint64_t usage,
+                                            uint32_t stride) const {
+    IMapper::BufferDescriptorInfo descriptorInfo;
+    sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
+
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
+
+    return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
+}
+
+void Gralloc3Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
+                                      uint32_t* outNumInts) const {
+    *outNumFds = uint32_t(bufferHandle->numFds);
+    *outNumInts = uint32_t(bufferHandle->numInts);
+
+    Error error;
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+    auto ret = mMapper->getTransportSize(buffer,
+                                         [&](const auto& tmpError, const auto& tmpNumFds,
+                                             const auto& tmpNumInts) {
+                                             error = tmpError;
+                                             if (error != Error::NONE) {
+                                                 return;
+                                             }
+                                             *outNumFds = tmpNumFds;
+                                             *outNumInts = tmpNumInts;
+                                         });
+
+    error = (ret.isOk()) ? error : kTransactionError;
+
+    ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
+}
+
+status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                              int acquireFence, void** outData) const {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    IMapper::Rect accessRegion = sGralloc3Rect(bounds);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error;
+    auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+                             [&](const auto& tmpError, const auto& tmpData) {
+                                 error = tmpError;
+                                 if (error != Error::NONE) {
+                                     return;
+                                 }
+                                 *outData = tmpData;
+                             });
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    error = (ret.isOk()) ? error : kTransactionError;
+
+    ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
+
+    return static_cast<status_t>(error);
+}
+
+status_t Gralloc3Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                              int acquireFence, android_ycbcr* ycbcr) const {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    IMapper::Rect accessRegion = sGralloc3Rect(bounds);
+
+    // put acquireFence in a hidl_handle
+    hardware::hidl_handle acquireFenceHandle;
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    YCbCrLayout layout;
+    Error error;
+    auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion, acquireFenceHandle,
+                                  [&](const auto& tmpError, const auto& tmpLayout) {
+                                      error = tmpError;
+                                      if (error != Error::NONE) {
+                                          return;
+                                      }
+
+                                      layout = tmpLayout;
+                                  });
+
+    if (error == Error::NONE) {
+        ycbcr->y = layout.y;
+        ycbcr->cb = layout.cb;
+        ycbcr->cr = layout.cr;
+        ycbcr->ystride = static_cast<size_t>(layout.yStride);
+        ycbcr->cstride = static_cast<size_t>(layout.cStride);
+        ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
+    }
+
+    // we own acquireFence even on errors
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
+}
+
+int Gralloc3Mapper::unlock(buffer_handle_t bufferHandle) const {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    Error error;
+    auto ret = mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+        error = tmpError;
+        if (error != Error::NONE) {
+            return;
+        }
+
+        auto fenceHandle = tmpReleaseFence.getNativeHandle();
+        if (fenceHandle && fenceHandle->numFds == 1) {
+            int fd = dup(fenceHandle->data[0]);
+            if (fd >= 0) {
+                releaseFence = fd;
+            } else {
+                ALOGD("failed to dup unlock release fence");
+                sync_wait(fenceHandle->data[0], -1);
+            }
+        }
+    });
+
+    if (!ret.isOk()) {
+        error = kTransactionError;
+    }
+
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", buffer, error);
+    }
+
+    return releaseFence;
+}
+
+Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {
+    mAllocator = IAllocator::getService();
+    if (mAllocator == nullptr) {
+        ALOGW("allocator 3.x is not supported");
+        return;
+    }
+}
+
+bool Gralloc3Allocator::isSupported() const {
+    return mAllocator != nullptr;
+}
+
+std::string Gralloc3Allocator::dumpDebugInfo() const {
+    std::string debugInfo;
+
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+status_t Gralloc3Allocator::allocate(uint32_t width, uint32_t height, android::PixelFormat format,
+                                     uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
+                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {
+    IMapper::BufferDescriptorInfo descriptorInfo;
+    sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);
+
+    BufferDescriptor descriptor;
+    status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
+                                              static_cast<void*>(&descriptor));
+    if (error != NO_ERROR) {
+        return error;
+    }
+
+    auto ret = mAllocator->allocate(descriptor, bufferCount,
+                                    [&](const auto& tmpError, const auto& tmpStride,
+                                        const auto& tmpBuffers) {
+                                        error = static_cast<status_t>(tmpError);
+                                        if (tmpError != Error::NONE) {
+                                            return;
+                                        }
+
+                                        // import buffers
+                                        for (uint32_t i = 0; i < bufferCount; i++) {
+                                            error = mMapper.importBuffer(tmpBuffers[i],
+                                                                         &outBufferHandles[i]);
+                                            if (error != NO_ERROR) {
+                                                for (uint32_t j = 0; j < i; j++) {
+                                                    mMapper.freeBuffer(outBufferHandles[j]);
+                                                    outBufferHandles[j] = nullptr;
+                                                }
+                                                return;
+                                            }
+                                        }
+                                        *outStride = tmpStride;
+                                    });
+
+    // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
+    hardware::IPCThreadState::self()->flushCommands();
+
+    return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
+}
+
+} // namespace android
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index f56e6b9..efb5798 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -29,7 +29,9 @@
 #include <utils/Singleton.h>
 #include <utils/Trace.h>
 
+#include <ui/Gralloc.h>
 #include <ui/Gralloc2.h>
+#include <ui/Gralloc3.h>
 #include <ui/GraphicBufferMapper.h>
 
 namespace android {
@@ -43,11 +45,17 @@
 KeyedVector<buffer_handle_t,
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
-GraphicBufferAllocator::GraphicBufferAllocator()
-  : mMapper(GraphicBufferMapper::getInstance()),
-    mAllocator(std::make_unique<Gralloc2::Allocator>(
-                mMapper.getGrallocMapper()))
-{
+GraphicBufferAllocator::GraphicBufferAllocator() : mMapper(GraphicBufferMapper::getInstance()) {
+    mAllocator = std::make_unique<const Gralloc3Allocator>(
+            reinterpret_cast<const Gralloc3Mapper&>(mMapper.getGrallocMapper()));
+    if (!mAllocator->isSupported()) {
+        mAllocator = std::make_unique<const Gralloc2Allocator>(
+                reinterpret_cast<const Gralloc2Mapper&>(mMapper.getGrallocMapper()));
+    }
+
+    if (!mAllocator->isSupported()) {
+        LOG_ALWAYS_FATAL("gralloc-allocator is missing");
+    }
 }
 
 GraphicBufferAllocator::~GraphicBufferAllocator() {}
@@ -104,15 +112,9 @@
     // 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;
-    info.layerCount = layerCount;
-    info.format = static_cast<Gralloc2::PixelFormat>(format);
-    info.usage = usage;
-
-    Gralloc2::Error error = mAllocator->allocate(info, stride, handle);
-    if (error == Gralloc2::Error::NONE) {
+    status_t error =
+            mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle);
+    if (error == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
         uint32_t bpp = bytesPerPixel(format);
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 2d8e582..b049329 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -32,7 +32,9 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include <ui/Gralloc.h>
 #include <ui/Gralloc2.h>
+#include <ui/Gralloc3.h>
 #include <ui/GraphicBuffer.h>
 
 #include <system/graphics.h>
@@ -43,12 +45,19 @@
 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
 
 void GraphicBufferMapper::preloadHal() {
-    Gralloc2::Mapper::preload();
+    Gralloc2Mapper::preload();
+    Gralloc3Mapper::preload();
 }
 
-GraphicBufferMapper::GraphicBufferMapper()
-  : mMapper(std::make_unique<const Gralloc2::Mapper>())
-{
+GraphicBufferMapper::GraphicBufferMapper() {
+    mMapper = std::make_unique<const Gralloc3Mapper>();
+    if (!mMapper->isSupported()) {
+        mMapper = std::make_unique<const Gralloc2Mapper>();
+    }
+
+    if (!mMapper->isSupported()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper is missing");
+    }
 }
 
 status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
@@ -59,22 +68,15 @@
     ATRACE_CALL();
 
     buffer_handle_t bufferHandle;
-    Gralloc2::Error error = mMapper->importBuffer(
-            hardware::hidl_handle(rawHandle), &bufferHandle);
-    if (error != Gralloc2::Error::NONE) {
+    status_t error = mMapper->importBuffer(hardware::hidl_handle(rawHandle), &bufferHandle);
+    if (error != NO_ERROR) {
         ALOGW("importBuffer(%p) failed: %d", rawHandle, error);
-        return static_cast<status_t>(error);
+        return error;
     }
 
-    Gralloc2::IMapper::BufferDescriptorInfo info = {};
-    info.width = width;
-    info.height = height;
-    info.layerCount = layerCount;
-    info.format = static_cast<Gralloc2::PixelFormat>(format);
-    info.usage = usage;
-
-    error = mMapper->validateBufferSize(bufferHandle, info, stride);
-    if (error != Gralloc2::Error::NONE) {
+    error = mMapper->validateBufferSize(bufferHandle, width, height, format, layerCount, usage,
+                                        stride);
+    if (error != NO_ERROR) {
         ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error);
         freeBuffer(bufferHandle);
         return static_cast<status_t>(error);
@@ -100,15 +102,6 @@
     return NO_ERROR;
 }
 
-static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
-    Gralloc2::IMapper::Rect outRect{};
-    outRect.left = rect.left;
-    outRect.top = rect.top;
-    outRect.width = rect.width();
-    outRect.height = rect.height();
-    return outRect;
-}
-
 status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
         const Rect& bounds, void** vaddr)
 {
@@ -146,13 +139,7 @@
 
     const uint64_t usage = static_cast<uint64_t>(
             android_convertGralloc1To0Usage(producerUsage, consumerUsage));
-    Gralloc2::Error error = mMapper->lock(handle, usage,
-            asGralloc2Rect(bounds), fenceFd, vaddr);
-
-    ALOGW_IF(error != Gralloc2::Error::NONE, "lock(%p, ...) failed: %d",
-            handle, error);
-
-    return static_cast<status_t>(error);
+    return mMapper->lock(handle, usage, bounds, fenceFd, vaddr);
 }
 
 status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
@@ -160,19 +147,7 @@
 {
     ATRACE_CALL();
 
-    Gralloc2::YCbCrLayout layout;
-    Gralloc2::Error error = mMapper->lock(handle, usage,
-            asGralloc2Rect(bounds), fenceFd, &layout);
-    if (error == Gralloc2::Error::NONE) {
-        ycbcr->y = layout.y;
-        ycbcr->cb = layout.cb;
-        ycbcr->cr = layout.cr;
-        ycbcr->ystride = static_cast<size_t>(layout.yStride);
-        ycbcr->cstride = static_cast<size_t>(layout.cStride);
-        ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
-    }
-
-    return static_cast<status_t>(error);
+    return mMapper->lock(handle, usage, bounds, fenceFd, ycbcr);
 }
 
 status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
new file mode 100644
index 0000000..54405e6
--- /dev/null
+++ b/libs/ui/OWNERS
@@ -0,0 +1,5 @@
+lpy@google.com
+marissaw@google.com
+mathias@google.com
+romainguy@google.com
+stoza@google.com
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 44dfa95..c6a4a23 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -94,9 +94,6 @@
     // current cycle of the usage of the buffer.
     int Release();
 
-    // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
-    int Poll(int timeoutMs);
-
     // Creates a token that stands for this BufferHubBuffer client and could be used for Import to
     // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
     // gralloc buffer and ashmem region for metadata. Note that the caller owns the token and
diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h
new file mode 100644
index 0000000..92bf043
--- /dev/null
+++ b/libs/ui/include/ui/Gralloc.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC_H
+#define ANDROID_UI_GRALLOC_H
+
+#include <string>
+
+#include <hidl/HidlSupport.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+// A wrapper to IMapper
+class GrallocMapper {
+public:
+    virtual ~GrallocMapper();
+
+    virtual bool isSupported() const = 0;
+
+    virtual status_t createDescriptor(void* bufferDescriptorInfo,
+                                      void* outBufferDescriptor) const = 0;
+
+    // Import a buffer that is from another HAL, another process, or is
+    // cloned.
+    //
+    // The returned handle must be freed with freeBuffer.
+    virtual status_t importBuffer(const hardware::hidl_handle& rawHandle,
+                                  buffer_handle_t* outBufferHandle) const = 0;
+
+    virtual void freeBuffer(buffer_handle_t bufferHandle) const = 0;
+
+    virtual status_t validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
+                                        uint32_t height, android::PixelFormat format,
+                                        uint32_t layerCount, uint64_t usage,
+                                        uint32_t stride) const = 0;
+
+    virtual void getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
+                                  uint32_t* outNumInts) const = 0;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    virtual status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                          int acquireFence, void** outData) const = 0;
+
+    // The ownership of acquireFence is always transferred to the callee, even
+    // on errors.
+    virtual status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                          int acquireFence, android_ycbcr* ycbcr) const = 0;
+
+    // unlock returns a fence sync object (or -1) and the fence sync object is
+    // owned by the caller
+    virtual int unlock(buffer_handle_t bufferHandle) const = 0;
+};
+
+// A wrapper to IAllocator
+class GrallocAllocator {
+public:
+    virtual ~GrallocAllocator();
+
+    virtual bool isSupported() const = 0;
+
+    virtual std::string dumpDebugInfo() const = 0;
+
+    /*
+     * The returned buffers are already imported and must not be imported
+     * again.  outBufferHandles must point to a space that can contain at
+     * least "bufferCount" buffer_handle_t.
+     */
+    virtual status_t allocate(uint32_t width, uint32_t height, PixelFormat format,
+                              uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
+                              uint32_t* outStride, buffer_handle_t* outBufferHandles) const = 0;
+};
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC_H
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 5a8dbda..e03cb43 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -23,119 +23,71 @@
 #include <android/hardware/graphics/common/1.1/types.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <ui/Gralloc.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
 
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::common::V1_1::BufferUsage;
-using hardware::graphics::common::V1_1::PixelFormat;
-using hardware::graphics::mapper::V2_1::IMapper;
-using hardware::graphics::mapper::V2_0::BufferDescriptor;
-using hardware::graphics::mapper::V2_0::Error;
-using hardware::graphics::mapper::V2_0::YCbCrLayout;
-
-// A wrapper to IMapper
-class Mapper {
+class Gralloc2Mapper : public GrallocMapper {
 public:
     static void preload();
 
-    Mapper();
+    Gralloc2Mapper();
 
-    Error createDescriptor(
-            const IMapper::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor* outDescriptor) const;
+    bool isSupported() const override;
 
-    // Import a buffer that is from another HAL, another process, or is
-    // cloned.
-    //
-    // The returned handle must be freed with freeBuffer.
-    Error importBuffer(const hardware::hidl_handle& rawHandle,
-            buffer_handle_t* outBufferHandle) const;
+    status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override;
 
-    void freeBuffer(buffer_handle_t bufferHandle) const;
+    status_t importBuffer(const hardware::hidl_handle& rawHandle,
+                          buffer_handle_t* outBufferHandle) const override;
 
-    Error validateBufferSize(buffer_handle_t bufferHandle,
-            const IMapper::BufferDescriptorInfo& descriptorInfo,
-            uint32_t stride) const;
+    void freeBuffer(buffer_handle_t bufferHandle) const override;
 
-    void getTransportSize(buffer_handle_t bufferHandle,
-            uint32_t* outNumFds, uint32_t* outNumInts) const;
+    status_t validateBufferSize(buffer_handle_t bufferHandle, uint32_t width, uint32_t height,
+                                android::PixelFormat format, uint32_t layerCount, uint64_t usage,
+                                uint32_t stride) const override;
 
-    // The ownership of acquireFence is always transferred to the callee, even
-    // on errors.
-    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
-            const IMapper::Rect& accessRegion,
-            int acquireFence, void** outData) const;
+    void getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
+                          uint32_t* outNumInts) const override;
 
-    // The ownership of acquireFence is always transferred to the callee, even
-    // on errors.
-    Error lock(buffer_handle_t bufferHandle, uint64_t usage,
-            const IMapper::Rect& accessRegion,
-            int acquireFence, YCbCrLayout* outLayout) const;
+    status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                  int acquireFence, void** outData) const override;
 
-    // unlock returns a fence sync object (or -1) and the fence sync object is
-    // owned by the caller
-    int unlock(buffer_handle_t bufferHandle) const;
+    status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                  int acquireFence, android_ycbcr* ycbcr) const override;
+
+    int unlock(buffer_handle_t bufferHandle) const override;
 
 private:
     // Determines whether the passed info is compatible with the mapper.
-    Error validateBufferDescriptorInfo(
-            const IMapper::BufferDescriptorInfo& descriptorInfo) const;
+    status_t validateBufferDescriptorInfo(
+            hardware::graphics::mapper::V2_1::IMapper::BufferDescriptorInfo* descriptorInfo) const;
 
     sp<hardware::graphics::mapper::V2_0::IMapper> mMapper;
-    sp<IMapper> mMapperV2_1;
+    sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1;
 };
 
-// A wrapper to IAllocator
-class Allocator {
+class Gralloc2Allocator : public GrallocAllocator {
 public:
     // An allocator relies on a mapper, and that mapper must be alive at all
     // time.
-    Allocator(const Mapper& mapper);
+    Gralloc2Allocator(const Gralloc2Mapper& mapper);
 
-    std::string dumpDebugInfo() const;
+    bool isSupported() const override;
 
-    /*
-     * The returned buffers are already imported and must not be imported
-     * again.  outBufferHandles must point to a space that can contain at
-     * least "count" buffer_handle_t.
-     */
-    Error allocate(BufferDescriptor descriptor, uint32_t count,
-            uint32_t* outStride, buffer_handle_t* outBufferHandles) const;
+    std::string dumpDebugInfo() const override;
 
-    Error allocate(BufferDescriptor descriptor,
-            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
-    {
-        return allocate(descriptor, 1, outStride, outBufferHandle);
-    }
-
-    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
-            uint32_t* outStride, buffer_handle_t* outBufferHandles) const
-    {
-        BufferDescriptor descriptor;
-        Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
-        if (error == Error::NONE) {
-            error = allocate(descriptor, count, outStride, outBufferHandles);
-        }
-        return error;
-    }
-
-    Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-            uint32_t* outStride, buffer_handle_t* outBufferHandle) const
-    {
-        return allocate(descriptorInfo, 1, outStride, outBufferHandle);
-    }
+    status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
+                      uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
+                      buffer_handle_t* outBufferHandles) const override;
 
 private:
-    const Mapper& mMapper;
-    sp<IAllocator> mAllocator;
+    const Gralloc2Mapper& mMapper;
+    sp<hardware::graphics::allocator::V2_0::IAllocator> mAllocator;
 };
 
-} // namespace Gralloc2
-
 } // namespace android
 
 #endif // ANDROID_UI_GRALLOC2_H
diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h
new file mode 100644
index 0000000..510ce4a
--- /dev/null
+++ b/libs/ui/include/ui/Gralloc3.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC3_H
+#define ANDROID_UI_GRALLOC3_H
+
+#include <string>
+
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/common/1.1/types.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <ui/Gralloc.h>
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class Gralloc3Mapper : public GrallocMapper {
+public:
+    static void preload();
+
+    Gralloc3Mapper();
+
+    bool isSupported() const override;
+
+    status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override;
+
+    status_t importBuffer(const hardware::hidl_handle& rawHandle,
+                          buffer_handle_t* outBufferHandle) const override;
+
+    void freeBuffer(buffer_handle_t bufferHandle) const override;
+
+    status_t validateBufferSize(buffer_handle_t bufferHandle, uint32_t width, uint32_t height,
+                                android::PixelFormat format, uint32_t layerCount, uint64_t usage,
+                                uint32_t stride) const override;
+
+    void getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
+                          uint32_t* outNumInts) const override;
+
+    status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                  int acquireFence, void** outData) const override;
+
+    status_t lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
+                  int acquireFence, android_ycbcr* ycbcr) const override;
+
+    int unlock(buffer_handle_t bufferHandle) const override;
+
+private:
+    // Determines whether the passed info is compatible with the mapper.
+    status_t validateBufferDescriptorInfo(
+            hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo* descriptorInfo) const;
+
+    sp<hardware::graphics::mapper::V3_0::IMapper> mMapper;
+};
+
+class Gralloc3Allocator : public GrallocAllocator {
+public:
+    // An allocator relies on a mapper, and that mapper must be alive at all
+    // time.
+    Gralloc3Allocator(const Gralloc3Mapper& mapper);
+
+    bool isSupported() const override;
+
+    std::string dumpDebugInfo() const override;
+
+    status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
+                      uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
+                      buffer_handle_t* outBufferHandles) const override;
+
+private:
+    const Gralloc3Mapper& mMapper;
+    sp<hardware::graphics::allocator::V3_0::IAllocator> mAllocator;
+};
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC3_H
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 7e2b230..3a547b6 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -34,10 +34,7 @@
 
 namespace android {
 
-namespace Gralloc2 {
-class Allocator;
-}
-
+class GrallocAllocator;
 class GraphicBufferMapper;
 
 class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
@@ -75,7 +72,7 @@
     ~GraphicBufferAllocator();
 
     GraphicBufferMapper& mMapper;
-    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
+    std::unique_ptr<const GrallocAllocator> mAllocator;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 7cf003d..156bd7a 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -35,10 +35,7 @@
 
 // ---------------------------------------------------------------------------
 
-namespace Gralloc2 {
-class Mapper;
-}
-
+class GrallocMapper;
 class Rect;
 
 class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
@@ -80,9 +77,8 @@
 
     status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
 
-    const Gralloc2::Mapper& getGrallocMapper() const
-    {
-        return *mMapper;
+    const GrallocMapper& getGrallocMapper() const {
+        return reinterpret_cast<const GrallocMapper&>(*mMapper);
     }
 
 private:
@@ -90,7 +86,7 @@
 
     GraphicBufferMapper();
 
-    const std::unique_ptr<const Gralloc2::Mapper> mMapper;
+    std::unique_ptr<const GrallocMapper> mMapper;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
index f2c40fe..f5761d5 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -162,39 +162,6 @@
   void operator=(const BufferTraits&) = delete;
 };
 
-struct DetachedBufferRPC {
- private:
-  enum {
-    kOpDetachedBufferBase = 1000,
-
-    // Allocates a standalone DetachedBuffer not associated with any producer
-    // consumer set.
-    kOpCreate,
-
-    // Imports the given channel handle to a DetachedBuffer, taking ownership.
-    kOpImport,
-
-    // Creates a DetachedBuffer client from an existing one. The new client will
-    // share the same underlying gralloc buffer and ashmem region for metadata.
-    kOpDuplicate,
-  };
-
-  // Aliases.
-  using LocalChannelHandle = pdx::LocalChannelHandle;
-  using LocalHandle = pdx::LocalHandle;
-  using Void = pdx::rpc::Void;
-
- public:
-  PDX_REMOTE_METHOD(Create, kOpCreate,
-                    void(uint32_t width, uint32_t height, uint32_t layer_count,
-                         uint32_t format, uint64_t usage,
-                         size_t user_metadata_size));
-  PDX_REMOTE_METHOD(Import, kOpImport, BufferTraits<LocalHandle>(Void));
-  PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void));
-
-  PDX_REMOTE_API(API, Create, Import, Duplicate);
-};
-
 }  // namespace dvr
 }  // namespace android
 
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index dd8fbfc..f936ac0 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -375,12 +375,13 @@
                 auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
                 if (app_namespace && !android::base::StartsWith(layer, kSystemLayerLibraryDir)) {
                     bool native_bridge = false;
-                    std::string error_message;
-                    handle = OpenNativeLibrary(app_namespace, layer.c_str(), &native_bridge,
-                                               &error_message);
+                    char* error_message = nullptr;
+                    handle = OpenNativeLibraryInNamespace(
+                        app_namespace, layer.c_str(), &native_bridge, &error_message);
                     if (!handle) {
                         ALOGE("Failed to load layer %s with error: %s", layer.c_str(),
-                              error_message.c_str());
+                              error_message);
+                        android::NativeLoaderFreeErrorMessage(error_message);
                         return;
                     }
 
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index ad49cd6..a40443d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -216,7 +216,7 @@
     stream << " ";
     stream << std::setw(10) << "State";
     stream << " ";
-    stream << std::setw(10) << "Index";
+    stream << std::setw(8) << "Index";
     stream << std::endl;
 
     for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
@@ -251,6 +251,7 @@
         stream << " ";
         stream << "0x" << std::hex << std::setfill('0');
         stream << std::setw(8) << /*State=*/state;
+        stream << std::dec << std::setfill(' ');
         stream << " ";
         stream << std::setw(8) << /*Index=*/index;
         stream << std::endl;
diff --git a/services/displayservice/OWNERS b/services/displayservice/OWNERS
new file mode 100644
index 0000000..7a3e4c2
--- /dev/null
+++ b/services/displayservice/OWNERS
@@ -0,0 +1,2 @@
+smoreland@google.com
+lpy@google.com
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 9af189a..9d92435 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2155,7 +2155,7 @@
                     motionEntry->deviceId, motionEntry->source, motionEntry->displayId,
                     dispatchEntry->resolvedAction, motionEntry->actionButton,
                     dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
-                    motionEntry->metaState, motionEntry->buttonState,
+                    motionEntry->metaState, motionEntry->buttonState, motionEntry->classification,
                     xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
                     motionEntry->downTime, motionEntry->eventTime,
                     motionEntry->pointerCount, motionEntry->pointerProperties,
@@ -2491,6 +2491,7 @@
             originalMotionEntry->flags,
             originalMotionEntry->metaState,
             originalMotionEntry->buttonState,
+            originalMotionEntry->classification,
             originalMotionEntry->edgeFlags,
             originalMotionEntry->xPrecision,
             originalMotionEntry->yPrecision,
@@ -2707,7 +2708,7 @@
         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,
+                args->metaState, args->buttonState, args->classification,
                 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                 args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
 
@@ -2845,7 +2846,7 @@
                 policyFlags,
                 action, actionButton, motionEvent->getFlags(),
                 motionEvent->getMetaState(), motionEvent->getButtonState(),
-                motionEvent->getEdgeFlags(),
+                motionEvent->getClassification(), motionEvent->getEdgeFlags(),
                 motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                 motionEvent->getDownTime(),
                 uint32_t(pointerCount), pointerProperties, samplePointerCoords,
@@ -2860,7 +2861,7 @@
                     motionEvent->getDisplayId(), policyFlags,
                     action, actionButton, motionEvent->getFlags(),
                     motionEvent->getMetaState(), motionEvent->getButtonState(),
-                    motionEvent->getEdgeFlags(),
+                    motionEvent->getClassification(), motionEvent->getEdgeFlags(),
                     motionEvent->getXPrecision(), motionEvent->getYPrecision(),
                     motionEvent->getDownTime(),
                     uint32_t(pointerCount), pointerProperties, samplePointerCoords,
@@ -4404,8 +4405,8 @@
 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,
-        float xPrecision, float yPrecision, nsecs_t downTime,
+        int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+        int32_t edgeFlags, float xPrecision, float yPrecision, nsecs_t downTime,
         uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
         float xOffset, float yOffset) :
@@ -4413,7 +4414,8 @@
         eventTime(eventTime),
         deviceId(deviceId), source(source), displayId(displayId), action(action),
         actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
-        edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision),
+        classification(classification), edgeFlags(edgeFlags),
+        xPrecision(xPrecision), yPrecision(yPrecision),
         downTime(downTime), pointerCount(pointerCount) {
     for (uint32_t i = 0; i < pointerCount; i++) {
         this->pointerProperties[i].copyFrom(pointerProperties[i]);
@@ -4430,9 +4432,10 @@
 void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
     msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
             ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
-            "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[",
+            "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[",
             deviceId, source, displayId, motionActionToString(action).c_str(), actionButton, flags,
-            metaState, buttonState, edgeFlags, xPrecision, yPrecision);
+            metaState, buttonState, motionClassificationToString(classification), edgeFlags,
+            xPrecision, yPrecision);
 
     for (uint32_t i = 0; i < pointerCount; i++) {
         if (i) {
@@ -4733,15 +4736,15 @@
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (shouldCancelMotion(memento, options)) {
+            const int32_t action = memento.hovering ?
+                    AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
             outEvents.push(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
                     memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
-                    memento.hovering
-                            ? AMOTION_EVENT_ACTION_HOVER_EXIT
-                            : AMOTION_EVENT_ACTION_CANCEL,
-                    memento.flags, 0, 0, 0, 0,
+                    action, 0 /*actionButton*/, memento.flags, AMETA_NONE, 0 /*buttonState*/,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                     memento.xPrecision, memento.yPrecision, memento.downTime,
                     memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
-                    0, 0));
+                    0 /*xOffset*/, 0 /*yOffset*/));
         }
     }
 }
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 49de6f3..327dbbd 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -535,6 +535,7 @@
         int32_t flags;
         int32_t metaState;
         int32_t buttonState;
+        MotionClassification classification;
         int32_t edgeFlags;
         float xPrecision;
         float yPrecision;
@@ -546,8 +547,9 @@
         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,
-                float xPrecision, float yPrecision, nsecs_t downTime, uint32_t pointerCount,
+                int32_t metaState, int32_t buttonState, MotionClassification classification,
+                int32_t edgeFlags, float xPrecision, float yPrecision,
+                nsecs_t downTime, uint32_t pointerCount,
                 const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
                 float xOffset, float yOffset);
         virtual void appendDescription(std::string& msg) const;
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 5a35410..031744a 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,7 +25,7 @@
 
 class SensorService::SensorRecord {
 public:
-    SensorRecord(const sp<const SensorEventConnection>& connection);
+    explicit SensorRecord(const sp<const SensorEventConnection>& connection);
     bool addConnection(const sp<const SensorEventConnection>& connection);
     bool removeConnection(const wp<const SensorEventConnection>& connection);
     size_t getNumConnections() const { return mConnections.size(); }
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
index ddcee28..8d7a05b 100644
--- a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -43,7 +43,7 @@
 
 struct SensorManager final : public ISensorManager {
 
-    SensorManager(JavaVM* vm);
+    explicit SensorManager(JavaVM* vm);
     ~SensorManager();
 
     // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
diff --git a/services/sensorservice/mat.h b/services/sensorservice/mat.h
index 495c14e..934ae58 100644
--- a/services/sensorservice/mat.h
+++ b/services/sensorservice/mat.h
@@ -139,13 +139,13 @@
 
     mat() { }
     mat(const mat& rhs)  : base(rhs) { }
-    mat(const base& rhs) : base(rhs) { }  // NOLINT(implicit)
+    mat(const base& rhs) : base(rhs) { }  // NOLINT(google-explicit-constructor)
 
     // -----------------------------------------------------------------------
     // conversion constructors
 
     // sets the diagonal to the value, off-diagonal to zero
-    mat(pTYPE rhs) {  // NOLINT(implicit)
+    mat(pTYPE rhs) {  // NOLINT(google-explicit-constructor)
         helpers::doAssign(*this, rhs);
     }
 
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index 9e5d280..c195434 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -322,12 +322,12 @@
 
     vec() { }
     vec(const vec& rhs)  : base(rhs) { }
-    vec(const base& rhs) : base(rhs) { }  // NOLINT(implicit)
+    vec(const base& rhs) : base(rhs) { }  // NOLINT(google-explicit-constructor)
 
     // -----------------------------------------------------------------------
     // conversion constructors
 
-    vec(pTYPE rhs) {  // NOLINT(implicit)
+    vec(pTYPE rhs) {  // NOLINT(google-explicit-constructor)
         for (size_t i=0 ; i<SIZE ; i++)
             base::operator[](i) = rhs;
     }
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5b3bbca..d6ac88c 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -25,6 +25,7 @@
         "android.hardware.configstore@1.1",
         "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
@@ -77,6 +78,7 @@
     ],
     export_shared_lib_headers: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
@@ -114,6 +116,7 @@
         "BufferLayerConsumer.cpp",
         "BufferQueueLayer.cpp",
         "BufferStateLayer.cpp",
+        "BufferStateLayerCache.cpp",
         "Client.cpp",
         "ColorLayer.cpp",
         "ContainerLayer.cpp",
@@ -186,6 +189,7 @@
         "android.hardware.configstore@1.0",
         "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "libbinder",
         "libcutils",
         "libdisplayservicehidl",
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e0d9d23..2132f59 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -48,10 +48,28 @@
 // Interface implementation for Layer
 // -----------------------------------------------------------------------
 void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
-    // The transaction completed callback can only be sent if the release fence from the PREVIOUS
-    // frame has fired. In practice, we should never actually wait on the previous release fence
-    // but we should store it just in case.
-    mPreviousReleaseFence = releaseFence;
+    // The previous release fence notifies the client that SurfaceFlinger is done with the previous
+    // buffer that was presented on this layer. The first transaction that came in this frame that
+    // replaced the previous buffer on this layer needs this release fence, because the fence will
+    // let the client know when that previous buffer is removed from the screen.
+    //
+    // Every other transaction on this layer does not need a release fence because no other
+    // Transactions that were set on this layer this frame are going to have their preceeding buffer
+    // removed from the display this frame.
+    //
+    // For example, if we have 3 transactions this frame. The first transaction doesn't contain a
+    // buffer so it doesn't need a previous release fence because the layer still needs the previous
+    // buffer. The second transaction contains a buffer so it needs a previous release fence because
+    // the previous buffer will be released this frame. The third transaction also contains a
+    // buffer. It replaces the buffer in the second transaction. The buffer in the second
+    // transaction will now no longer be presented so it is released immediately and the third
+    // transaction doesn't need a previous release fence.
+    for (auto& handle : mDrawingState.callbackHandles) {
+        if (handle->releasePreviousBuffer) {
+            handle->previousReleaseFence = releaseFence;
+            break;
+        }
+    }
 }
 
 void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const {
@@ -60,7 +78,10 @@
 }
 
 void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
-    return;
+    mFlinger->getTransactionCompletedThread().addPresentedCallbackHandles(
+            mDrawingState.callbackHandles);
+
+    mDrawingState.callbackHandles = {};
 }
 
 bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
@@ -257,14 +278,14 @@
 
             // Notify the transaction completed thread that there is a pending latched callback
             // handle
-            mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle);
+            mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle);
 
             // Store so latched time and release fence can be set
             mCurrentState.callbackHandles.push_back(handle);
 
         } else { // If this layer will NOT need to be relatched and presented this frame
             // Notify the transaction completed thread this handle is done
-            mFlinger->getTransactionCompletedThread().addUnlatchedCallbackHandle(handle);
+            mFlinger->getTransactionCompletedThread().addUnpresentedCallbackHandle(handle);
         }
     }
 
@@ -504,9 +525,9 @@
         return BAD_VALUE;
     }
 
-    mFlinger->getTransactionCompletedThread()
-            .addLatchedCallbackHandles(getDrawingState().callbackHandles, latchTime,
-                                       mPreviousReleaseFence);
+    for (auto& handle : mDrawingState.callbackHandles) {
+        handle->latchTime = latchTime;
+    }
 
     // Handle sync fences
     if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp
new file mode 100644
index 0000000..c82ad7b
--- /dev/null
+++ b/services/surfaceflinger/BufferStateLayerCache.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BufferStateLayerCache"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BufferStateLayerCache.h"
+
+#define MAX_CACHE_SIZE 64
+
+namespace android {
+
+int32_t BufferStateLayerCache::add(const sp<IBinder>& processToken,
+                                   const sp<GraphicBuffer>& buffer) {
+    std::lock_guard lock(mMutex);
+
+    auto& processCache = getProccessCache(processToken);
+
+    int32_t slot = findSlot(processCache);
+    if (slot < 0) {
+        return slot;
+    }
+
+    processCache[slot] = buffer;
+
+    return slot;
+}
+
+void BufferStateLayerCache::release(const sp<IBinder>& processToken, int32_t id) {
+    if (id < 0) {
+        ALOGE("invalid buffer id");
+        return;
+    }
+
+    std::lock_guard lock(mMutex);
+    auto& processCache = getProccessCache(processToken);
+
+    if (id >= processCache.size()) {
+        ALOGE("invalid buffer id");
+        return;
+    }
+    processCache[id] = nullptr;
+}
+
+sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, int32_t id) {
+    if (id < 0) {
+        ALOGE("invalid buffer id");
+        return nullptr;
+    }
+
+    std::lock_guard lock(mMutex);
+    auto& processCache = getProccessCache(processToken);
+
+    if (id >= processCache.size()) {
+        ALOGE("invalid buffer id");
+        return nullptr;
+    }
+    return processCache[id];
+}
+
+std::vector<sp<GraphicBuffer>>& BufferStateLayerCache::getProccessCache(
+        const sp<IBinder>& processToken) {
+    return mBuffers[processToken];
+}
+
+int32_t BufferStateLayerCache::findSlot(std::vector<sp<GraphicBuffer>>& processCache) {
+    int32_t slot = 0;
+
+    for (const sp<GraphicBuffer> buffer : processCache) {
+        if (!buffer) {
+            return slot;
+        }
+        slot++;
+    }
+
+    if (processCache.size() < MAX_CACHE_SIZE) {
+        processCache.push_back(nullptr);
+        return slot;
+    }
+
+    return -1;
+}
+
+}; // namespace android
diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h
new file mode 100644
index 0000000..623f0c6
--- /dev/null
+++ b/services/surfaceflinger/BufferStateLayerCache.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 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
+
+#include <android-base/thread_annotations.h>
+#include <binder/IBinder.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/RefBase.h>
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+
+class BufferStateLayerCache {
+public:
+    int32_t add(const sp<IBinder>& processToken, const sp<GraphicBuffer>& buffer);
+    void release(const sp<IBinder>& processToken, int32_t id);
+
+    sp<GraphicBuffer> get(const sp<IBinder>& processToken, int32_t id);
+
+private:
+    std::mutex mMutex;
+
+    std::vector<sp<GraphicBuffer>>& getProccessCache(const sp<IBinder>& processToken)
+            REQUIRES(mMutex);
+
+    int32_t findSlot(std::vector<sp<GraphicBuffer>>& proccessCache) REQUIRES(mMutex);
+
+    struct IBinderHash {
+        std::size_t operator()(const sp<IBinder>& strongPointer) const {
+            return std::hash<IBinder*>{}(strongPointer.get());
+        }
+    };
+
+    std::unordered_map<sp<IBinder> /*caching process*/, std::vector<sp<GraphicBuffer>>, IBinderHash>
+            mBuffers GUARDED_BY(mMutex);
+};
+
+}; // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ee49610..aa9bc15 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2135,7 +2135,7 @@
     return mRemovedFromCurrentState;
 }
 
-InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
+InputWindowInfo Layer::fillInputInfo() {
     InputWindowInfo info = mDrawingState.inputInfo;
 
     ui::Transform t = getTransform();
@@ -2148,20 +2148,18 @@
     }
 
     // Transform layer size to screen space and inset it by surface insets.
-    Rect layerBounds = getCroppedBufferSize(getDrawingState());
+    Rect layerBounds = getBufferSize(getDrawingState());
+    if (!layerBounds.isValid()) {
+        layerBounds = getCroppedBufferSize(getDrawingState());
+    }
     layerBounds = t.transform(layerBounds);
     layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
 
-    // Intersect with screen bounds to shrink the frame by the surface insets. The surface insets
-    // are not set on the screen bounds directly since the surface inset region may already be
-    // cropped by a parent layer.
-    Rect frame;
-    screenBounds.intersect(layerBounds, &frame);
-
-    info.frameLeft = frame.left;
-    info.frameTop = frame.top;
-    info.frameRight = frame.right;
-    info.frameBottom = frame.bottom;
+    // Input coordinate should match the layer bounds.
+    info.frameLeft = layerBounds.left;
+    info.frameTop = layerBounds.top;
+    info.frameRight = layerBounds.right;
+    info.frameBottom = layerBounds.bottom;
 
     // Position the touchable region relative to frame screen location and restrict it to frame
     // bounds.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7bc7a82..95a8630 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -773,7 +773,7 @@
     bool mPendingHWCDestroy{false};
     void setInputInfo(const InputWindowInfo& info);
 
-    InputWindowInfo fillInputInfo(const Rect& screenBounds);
+    InputWindowInfo fillInputInfo();
     bool hasInput() const;
 
 protected:
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index b74b901..9b2a6fc 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -657,6 +657,9 @@
     Mutex::Autolock lock(mMutex);
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     nsecs_t phase = mReferenceTime + mPhase;
+    if (mPeriod == 0) {
+        return 0;
+    }
     return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
 }
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index bf925b2..7b25adb 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -43,8 +43,12 @@
 
 // ---------------------------------------------------------------------------
 
-EventThreadConnection::EventThreadConnection(EventThread* eventThread)
-      : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
+EventThreadConnection::EventThreadConnection(EventThread* eventThread,
+                                             ResyncCallback resyncCallback)
+      : resyncCallback(std::move(resyncCallback)),
+        count(-1),
+        mEventThread(eventThread),
+        mChannel(gui::BitTube::DefaultSize) {}
 
 EventThreadConnection::~EventThreadConnection() {
     // do nothing here -- clean-up will happen automatically
@@ -88,26 +92,21 @@
 namespace impl {
 
 EventThread::EventThread(std::unique_ptr<VSyncSource> src,
-                         const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
                          const InterceptVSyncsCallback& interceptVSyncsCallback,
                          const ResetIdleTimerCallback& resetIdleTimerCallback,
                          const char* threadName)
-      : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback,
-                    threadName) {
+      : EventThread(nullptr, std::move(src), interceptVSyncsCallback, threadName) {
     mResetIdleTimer = resetIdleTimerCallback;
 }
 
-EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
-                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
-      : EventThread(src, nullptr, resyncWithRateLimitCallback, interceptVSyncsCallback,
-                    threadName) {}
+EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
+                         const char* threadName)
+      : EventThread(src, nullptr, interceptVSyncsCallback, threadName) {}
 
 EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
-                         ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                          InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
       : mVSyncSource(src),
         mVSyncSourceUnique(std::move(uniqueSrc)),
-        mResyncWithRateLimitCallback(resyncWithRateLimitCallback),
         mInterceptVSyncsCallback(interceptVSyncsCallback) {
     if (src == nullptr) {
         mVSyncSource = mVSyncSourceUnique.get();
@@ -150,8 +149,8 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-sp<EventThreadConnection> EventThread::createEventConnection() const {
-    return new EventThreadConnection(const_cast<EventThread*>(this));
+sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
+    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -195,8 +194,9 @@
         ATRACE_NAME("resetIdleTimer");
         mResetIdleTimer();
     }
-    if (mResyncWithRateLimitCallback) {
-        mResyncWithRateLimitCallback();
+
+    if (connection->resyncCallback) {
+        connection->resyncCallback();
     }
 
     std::lock_guard<std::mutex> lock(mMutex);
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index e110488..a411885 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -44,6 +44,8 @@
 
 // ---------------------------------------------------------------------------
 
+using ResyncCallback = std::function<void()>;
+
 class VSyncSource {
 public:
     class Callback {
@@ -60,7 +62,7 @@
 
 class EventThreadConnection : public BnDisplayEventConnection {
 public:
-    explicit EventThreadConnection(EventThread* eventThread);
+    EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback);
     virtual ~EventThreadConnection();
 
     virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -72,6 +74,9 @@
     // in order to update the configs.
     void requestNextVsyncForHWC();
 
+    // Called in response to requestNextVsync.
+    const ResyncCallback resyncCallback;
+
     // count >= 1 : continuous event. count is the vsync rate
     // count == 0 : one-shot event that has not fired
     // count ==-1 : one-shot event that fired this round / disabled
@@ -90,7 +95,8 @@
 
     virtual ~EventThread();
 
-    virtual sp<EventThreadConnection> createEventConnection() const = 0;
+    virtual sp<EventThreadConnection> createEventConnection(
+            ResyncCallback resyncCallback) const = 0;
 
     // called before the screen is turned off from main thread
     virtual void onScreenReleased() = 0;
@@ -117,20 +123,18 @@
 
 class EventThread : public android::EventThread, private VSyncSource::Callback {
 public:
-    using ResyncWithRateLimitCallback = std::function<void()>;
     using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
     using ResetIdleTimerCallback = std::function<void()>;
 
     // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
-    EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
-                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+    EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
+                const char* threadName);
     EventThread(std::unique_ptr<VSyncSource> src,
-                const ResyncWithRateLimitCallback& resyncWithRateLimitCallback,
                 const InterceptVSyncsCallback& interceptVSyncsCallback,
                 const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
     ~EventThread();
 
-    sp<EventThreadConnection> createEventConnection() const override;
+    sp<EventThreadConnection> createEventConnection(ResyncCallback resyncCallback) const override;
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) override;
@@ -155,7 +159,6 @@
 
     // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
     EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
-                ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                 InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
 
 
@@ -179,7 +182,6 @@
     VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
     std::unique_ptr<VSyncSource> mVSyncSourceUnique GUARDED_BY(mMutex) = nullptr;
     // constants
-    const ResyncWithRateLimitCallback mResyncWithRateLimitCallback;
     const InterceptVSyncsCallback mInterceptVSyncsCallback;
 
     std::thread mThread;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 66f42bb..75a410b 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -85,7 +85,8 @@
     mHandler = new Handler(*this);
 }
 
-void MessageQueue::setEventThread(android::EventThread* eventThread) {
+void MessageQueue::setEventThread(android::EventThread* eventThread,
+                                  ResyncCallback resyncCallback) {
     if (mEventThread == eventThread) {
         return;
     }
@@ -95,7 +96,7 @@
     }
 
     mEventThread = eventThread;
-    mEvents = eventThread->createEventConnection();
+    mEvents = eventThread->createEventConnection(std::move(resyncCallback));
     mEvents->stealReceiveChannel(&mEventTube);
     mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                    this);
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 0bf00b0..56a00c0 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -29,12 +29,12 @@
 #include <private/gui/BitTube.h>
 
 #include "Barrier.h"
+#include "EventThread.h"
 
 #include <functional>
 
 namespace android {
 
-class EventThread;
 class SurfaceFlinger;
 
 // ---------------------------------------------------------------------------
@@ -86,7 +86,7 @@
 
     virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
     // TODO(akrulec): Remove this function once everything is migrated to Scheduler.
-    virtual void setEventThread(EventThread* events) = 0;
+    virtual void setEventThread(EventThread* events, ResyncCallback resyncCallback) = 0;
     virtual void setEventConnection(const sp<EventThreadConnection>& connection) = 0;
     virtual void waitMessage() = 0;
     virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
@@ -127,7 +127,7 @@
 public:
     ~MessageQueue() override = default;
     void init(const sp<SurfaceFlinger>& flinger) override;
-    void setEventThread(android::EventThread* events) override;
+    void setEventThread(android::EventThread* events, ResyncCallback resyncCallback) override;
     void setEventConnection(const sp<EventThreadConnection>& connection) override;
 
     void waitMessage() override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index fec53af..0d587dd 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -86,39 +86,38 @@
 Scheduler::~Scheduler() = default;
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const std::string& connectionName, int64_t phaseOffsetNs,
-        impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+        const std::string& connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
 
     std::unique_ptr<EventThread> eventThread =
-            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, resyncCallback,
+            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                             interceptCallback);
     auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
-                                                   eventThread->createEventConnection(),
+                                                   eventThread->createEventConnection(
+                                                           std::move(resyncCallback)),
                                                    std::move(eventThread));
+
     mConnections.insert(std::make_pair(id, std::move(connection)));
     return mConnections[id]->handle;
 }
 
 std::unique_ptr<EventThread> Scheduler::makeEventThread(
         const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
-        impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const std::string sourceName = connectionName + "Source";
     std::unique_ptr<VSyncSource> eventThreadSource =
             std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, sourceName.c_str());
     const std::string threadName = connectionName + "Thread";
-    return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
-                                               interceptCallback, [this] { resetIdleTimer(); },
-                                               threadName.c_str());
+    return std::make_unique<impl::EventThread>(std::move(eventThreadSource), interceptCallback,
+                                               [this] { resetIdleTimer(); }, threadName.c_str());
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle) {
+        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
     RETURN_VALUE_IF_INVALID(nullptr);
-    return mConnections[handle->id]->thread->createEventConnection();
+    return mConnections[handle->id]->thread->createEventConnection(std::move(resyncCallback));
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 3538f31..ba18d21 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -73,11 +73,11 @@
 
     /** Creates an EventThread connection. */
     sp<ConnectionHandle> createConnection(
-            const std::string& connectionName, int64_t phaseOffsetNs,
-            impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+            const std::string& connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
-    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
+    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
+                                                             ResyncCallback resyncCallback);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -122,7 +122,6 @@
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
             const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
-            impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0bbaf5c..5df2876 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -17,15 +17,16 @@
 // #define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <stdint.h>
 #include <sys/types.h>
-#include <algorithm>
 #include <errno.h>
-#include <math.h>
-#include <mutex>
 #include <dlfcn.h>
-#include <inttypes.h>
-#include <stdatomic.h>
+
+#include <algorithm>
+#include <cinttypes>
+#include <cmath>
+#include <cstdint>
+#include <functional>
+#include <mutex>
 #include <optional>
 
 #include <cutils/properties.h>
@@ -622,6 +623,8 @@
 
     Mutex::Autolock _l(mStateLock);
 
+    auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
+
     // start the EventThread
     if (mUseScheduler) {
         mScheduler = getFactory().createScheduler([this](bool enabled) {
@@ -630,12 +633,11 @@
 
         mAppConnectionHandle =
                 mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
-                                             [this] { resyncWithRateLimit(); },
+                                             resyncCallback,
                                              impl::EventThread::InterceptVSyncsCallback());
         mSfConnectionHandle =
                 mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
-                                             [this] { resyncWithRateLimit(); },
-                                             [this](nsecs_t timestamp) {
+                                             resyncCallback, [this](nsecs_t timestamp) {
                                                  mInterceptor->saveVSyncEvent(timestamp);
                                              });
 
@@ -648,7 +650,6 @@
                                                  SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
         mEventThread =
                 std::make_unique<impl::EventThread>(mEventThreadSource.get(),
-                                                    [this] { resyncWithRateLimit(); },
                                                     impl::EventThread::InterceptVSyncsCallback(),
                                                     "appEventThread");
         mSfEventThreadSource =
@@ -657,12 +658,11 @@
 
         mSFEventThread =
                 std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
-                                                    [this] { resyncWithRateLimit(); },
                                                     [this](nsecs_t timestamp) {
                                                         mInterceptor->saveVSyncEvent(timestamp);
                                                     },
                                                     "sfEventThread");
-        mEventQueue->setEventThread(mSFEventThread.get());
+        mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
         mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
     }
 
@@ -946,13 +946,15 @@
 
 status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
     ATRACE_NAME("setActiveConfigAsync");
-    postMessageAsync(new LambdaMessage([=] { setActiveConfigInternal(displayToken, mode); }));
+    postMessageAsync(new LambdaMessage(
+            [=]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
     return NO_ERROR;
 }
 
 status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
     ATRACE_NAME("setActiveConfigSync");
-    postMessageSync(new LambdaMessage([&] { setActiveConfigInternal(displayToken, mode); }));
+    postMessageSync(new LambdaMessage(
+            [&]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
     return NO_ERROR;
 }
 
@@ -993,7 +995,7 @@
     getHwComposer().setActiveConfig(*displayId, mode);
 
     ATRACE_INT("ActiveConfigMode", mode);
-    resyncToHardwareVsync(true);
+    resyncToHardwareVsync(true, getVsyncPeriod());
 }
 
 status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1128,6 +1130,28 @@
                                                      outStats);
 }
 
+status_t SurfaceFlinger::getProtectedContentSupport(bool* outSupported) const {
+    if (!outSupported) {
+        return BAD_VALUE;
+    }
+    *outSupported = getRenderEngine().supportsProtectedContent();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
+                                     int32_t* outBufferId) {
+    if (!outBufferId) {
+        return BAD_VALUE;
+    }
+    *outBufferId = mBufferStateLayerCache.add(token, buffer);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) {
+    mBufferStateLayerCache.release(token, bufferId);
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
     postMessageSync(new LambdaMessage([&] {
         Mutex::Autolock _l(mStateLock);
@@ -1136,6 +1160,8 @@
             return;
         }
 
+        auto resyncCallback = makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
+
         // TODO(akrulec): Part of the Injector should be refactored, so that it
         // can be passed to Scheduler.
         if (enable) {
@@ -1143,14 +1169,14 @@
             if (mVSyncInjector.get() == nullptr) {
                 mVSyncInjector = std::make_unique<InjectVSyncSource>();
                 mInjectorEventThread = std::make_unique<
-                        impl::EventThread>(mVSyncInjector.get(), [this] { resyncWithRateLimit(); },
+                        impl::EventThread>(mVSyncInjector.get(),
                                            impl::EventThread::InterceptVSyncsCallback(),
                                            "injEventThread");
             }
-            mEventQueue->setEventThread(mInjectorEventThread.get());
+            mEventQueue->setEventThread(mInjectorEventThread.get(), std::move(resyncCallback));
         } else {
             ALOGV("VSync Injections disabled");
-            mEventQueue->setEventThread(mSFEventThread.get());
+            mEventQueue->setEventThread(mSFEventThread.get(), std::move(resyncCallback));
         }
 
         mInjectVSyncs = enable;
@@ -1207,17 +1233,22 @@
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
         ISurfaceComposer::VsyncSource vsyncSource) {
+    auto resyncCallback = makeResyncCallback([this] {
+        Mutex::Autolock lock(mStateLock);
+        return getVsyncPeriod();
+    });
+
     if (mUseScheduler) {
         if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-            return mScheduler->createDisplayEventConnection(mSfConnectionHandle);
+            return mScheduler->createDisplayEventConnection(mSfConnectionHandle, resyncCallback);
         } else {
-            return mScheduler->createDisplayEventConnection(mAppConnectionHandle);
+            return mScheduler->createDisplayEventConnection(mAppConnectionHandle, resyncCallback);
         }
     } else {
         if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-            return mSFEventThread->createEventConnection();
+            return mSFEventThread->createEventConnection(resyncCallback);
         } else {
-            return mEventThread->createEventConnection();
+            return mEventThread->createEventConnection(resyncCallback);
         }
     }
 }
@@ -1261,6 +1292,16 @@
     } while (true);
 }
 
+nsecs_t SurfaceFlinger::getVsyncPeriod() const {
+    const auto displayId = getInternalDisplayId();
+    if (!displayId || !getHwComposer().isConnected(*displayId)) {
+        return 0;
+    }
+
+    const auto config = getHwComposer().getActiveConfig(*displayId);
+    return config ? config->getVsyncPeriod() : 0;
+}
+
 void SurfaceFlinger::enableHardwareVsync() {
     Mutex::Autolock _l(mHWVsyncLock);
     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
@@ -1270,7 +1311,7 @@
     }
 }
 
-void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
+void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
     Mutex::Autolock _l(mHWVsyncLock);
 
     if (makeAvailable) {
@@ -1285,14 +1326,10 @@
         return;
     }
 
-    const auto displayId = getInternalDisplayId();
-    if (!displayId || !getHwComposer().isConnected(*displayId)) {
+    if (period <= 0) {
         return;
     }
 
-    const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
-    const nsecs_t period = activeConfig->getVsyncPeriod();
-
     if (mUseScheduler) {
         mScheduler->setVsyncPeriod(period);
     } else {
@@ -1319,16 +1356,15 @@
     }
 }
 
-void SurfaceFlinger::resyncWithRateLimit() {
+void SurfaceFlinger::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
     static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
 
-    // No explicit locking is needed here since EventThread holds a lock while calling this method
-    static nsecs_t sLastResyncAttempted = 0;
     const nsecs_t now = systemTime();
-    if (now - sLastResyncAttempted > kIgnoreDelay) {
-        resyncToHardwareVsync(false);
+    const nsecs_t last = lastResyncTime.exchange(now);
+
+    if (now - last > kIgnoreDelay) {
+        flinger.resyncToHardwareVsync(false, getVsyncPeriod());
     }
-    sLastResyncAttempted = now;
 }
 
 void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -1528,9 +1564,8 @@
     setPowerModeInternal(display, currentDisplayPowerMode);
 
     // Reset the timing values to account for the period of the swapped in HWC
-    const auto activeConfig = getHwComposer().getActiveConfig(*display->getId());
-    const nsecs_t period = activeConfig->getVsyncPeriod();
-    mAnimFrameTracker.setDisplayRefreshPeriod(period);
+    const nsecs_t vsyncPeriod = getVsyncPeriod();
+    mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
 
     // The present fences returned from vr_hwc are not an accurate
     // representation of vsync times.
@@ -1544,10 +1579,10 @@
 
     // Use phase of 0 since phase is not known.
     // Use latency of 0, which will snap to the ideal latency.
-    DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+    DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
     setCompositorTimingSnapped(stats, 0);
 
-    resyncToHardwareVsync(false);
+    resyncToHardwareVsync(false, vsyncPeriod);
 
     mRepaintEverything = true;
     setTransactionFlags(eDisplayTransactionNeeded);
@@ -2927,8 +2962,7 @@
         if (layer->hasInput()) {
             // When calculating the screen bounds we ignore the transparent region since it may
             // result in an unwanted offset.
-            inputHandles.add(layer->fillInputInfo(
-                    layer->computeScreenBounds(false /* reduceTransparentRegion */)));
+            inputHandles.add(layer->fillInputInfo());
         }
     });
     mInputFlinger->setInputWindows(inputHandles);
@@ -3448,9 +3482,11 @@
         }
         if (parent == nullptr && addToCurrentState) {
             mCurrentState.layersSortedByZ.add(lbc);
-        } else if (parent == nullptr || parent->isRemovedFromCurrentState()) {
-                ALOGE("addClientLayer called with a removed parent");
-                lbc->onRemovedFromCurrentState();
+        } else if (parent == nullptr) {
+            lbc->onRemovedFromCurrentState();
+        } else if (parent->isRemovedFromCurrentState()) {
+            parent->addChild(lbc);
+            lbc->onRemovedFromCurrentState();
         } else {
             parent->addChild(lbc);
         }
@@ -3501,8 +3537,8 @@
         auto& [applyToken, transactionQueue] = *it;
 
         while (!transactionQueue.empty()) {
-            const auto& [states, displays, flags] = transactionQueue.front();
-            if (composerStateContainsUnsignaledFences(states)) {
+            const auto& [states, displays, flags, desiredPresentTime] = transactionQueue.front();
+            if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) {
                 break;
             }
             applyTransactionState(states, displays, flags, mInputWindowCommands);
@@ -3536,23 +3572,33 @@
     return false;
 }
 
-bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector<ComposerState>& states) {
+bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+                                                   const Vector<ComposerState>& states) {
+    const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+    // Do not present if the desiredPresentTime has not passed unless it is more than one second
+    // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
+    if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
+        desiredPresentTime < expectedPresentTime + s2ns(1)) {
+        return false;
+    }
+
     for (const ComposerState& state : states) {
         const layer_state_t& s = state.state;
         if (!(s.what & layer_state_t::eAcquireFenceChanged)) {
             continue;
         }
         if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
-            return true;
+            return false;
         }
     }
-    return false;
+    return true;
 }
 
 void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states,
                                          const Vector<DisplayState>& displays, uint32_t flags,
                                          const sp<IBinder>& applyToken,
-                                         const InputWindowCommands& inputWindowCommands) {
+                                         const InputWindowCommands& inputWindowCommands,
+                                         int64_t desiredPresentTime) {
     ATRACE_CALL();
     Mutex::Autolock _l(mStateLock);
 
@@ -3562,8 +3608,8 @@
 
     // If its TransactionQueue already has a pending TransactionState or if it is pending
     if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
-        composerStateContainsUnsignaledFences(states)) {
-        mTransactionQueues[applyToken].emplace(states, displays, flags);
+        !transactionIsReadyToBeApplied(desiredPresentTime, states)) {
+        mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime);
         setTransactionFlags(eTransactionNeeded);
         return;
     }
@@ -3925,6 +3971,11 @@
             callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
         }
     }
+    if (what & layer_state_t::eCachedBufferChanged) {
+        sp<GraphicBuffer> buffer =
+                mBufferStateLayerCache.get(s.cachedBuffer.token, s.cachedBuffer.bufferId);
+        if (layer->setBuffer(buffer)) flags |= eTraversalNeeded;
+    }
     if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded;
     // Do not put anything that updates layer state or modifies flags after
     // setTransactionCompletedListener
@@ -4133,8 +4184,11 @@
 // ---------------------------------------------------------------------------
 
 void SurfaceFlinger::onInitializeDisplays() {
-    const auto displayToken = getInternalDisplayToken();
-    if (!displayToken) return;
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display) return;
+
+    const sp<IBinder> token = display->getDisplayToken().promote();
+    LOG_ALWAYS_FATAL_IF(token == nullptr);
 
     // reset screen orientation and use primary layer stack
     Vector<ComposerState> state;
@@ -4142,7 +4196,7 @@
     DisplayState d;
     d.what = DisplayState::eDisplayProjectionChanged |
              DisplayState::eLayerStackChanged;
-    d.token = displayToken;
+    d.token = token;
     d.layerStack = 0;
     d.orientation = DisplayState::eOrientationDefault;
     d.frame.makeInvalid();
@@ -4150,26 +4204,23 @@
     d.width = 0;
     d.height = 0;
     displays.add(d);
-    setTransactionState(state, displays, 0, nullptr, mInputWindowCommands);
-
-    const auto display = getDisplayDevice(displayToken);
-    if (!display) return;
+    setTransactionState(state, displays, 0, nullptr, mInputWindowCommands, -1);
 
     setPowerModeInternal(display, HWC_POWER_MODE_NORMAL);
 
-    const auto activeConfig = getHwComposer().getActiveConfig(*display->getId());
-    const nsecs_t period = activeConfig->getVsyncPeriod();
-    mAnimFrameTracker.setDisplayRefreshPeriod(period);
+    const nsecs_t vsyncPeriod = getVsyncPeriod();
+    mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
 
     // Use phase of 0 since phase is not known.
     // Use latency of 0, which will snap to the ideal latency.
-    DisplayStatInfo stats{0 /* vsyncTime */, period /* vsyncPeriod */};
+    DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
     setCompositorTimingSnapped(stats, 0);
 }
 
 void SurfaceFlinger::initializeDisplays() {
     // Async since we may be called from the main thread.
-    postMessageAsync(new LambdaMessage([this] { onInitializeDisplays(); }));
+    postMessageAsync(
+            new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
 }
 
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
@@ -4203,7 +4254,7 @@
             } else {
                 mEventThread->onScreenAcquired();
             }
-            resyncToHardwareVsync(true);
+            resyncToHardwareVsync(true, getVsyncPeriod());
         }
 
         mVisibleRegionsDirty = true;
@@ -4248,7 +4299,7 @@
             } else {
                 mEventThread->onScreenAcquired();
             }
-            resyncToHardwareVsync(true);
+            resyncToHardwareVsync(true, getVsyncPeriod());
         }
     } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
         // Leave display going to doze
@@ -4278,7 +4329,7 @@
 }
 
 void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
-    postMessageSync(new LambdaMessage([&] {
+    postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
         const auto display = getDisplayDevice(displayToken);
         if (!display) {
             ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -4451,12 +4502,7 @@
         index++;
     }
 
-    if (const auto displayId = getInternalDisplayId();
-        displayId && getHwComposer().isConnected(*displayId)) {
-        const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
-        const nsecs_t period = activeConfig->getVsyncPeriod();
-        StringAppendF(&result, "%" PRId64 "\n", period);
-    }
+    StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriod());
 
     if (name.isEmpty()) {
         mAnimFrameTracker.dumpStats(result);
@@ -4760,22 +4806,16 @@
 
     const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
     const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
-    if (const auto displayId = getInternalDisplayId();
-        displayId && getHwComposer().isConnected(*displayId)) {
-        const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
-        StringAppendF(&result,
-                      "Display %s: app phase %" PRId64 " ns, "
-                      "sf phase %" PRId64 " ns, "
-                      "early app phase %" PRId64 " ns, "
-                      "early sf phase %" PRId64 " ns, "
-                      "early app gl phase %" PRId64 " ns, "
-                      "early sf gl phase %" PRId64 " ns, "
-                      "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
-                      to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
-                      appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
-                      dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
-    }
-    result.append("\n");
+    StringAppendF(&result,
+                  "app phase %" PRId64 " ns, "
+                  "sf phase %" PRId64 " ns, "
+                  "early app phase %" PRId64 " ns, "
+                  "early sf phase %" PRId64 " ns, "
+                  "early app gl phase %" PRId64 " ns, "
+                  "early sf gl phase %" PRId64 " ns, "
+                  "present offset %" PRId64 " ns (refresh %" PRId64 " ns)\n",
+                  vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, sfEarlyOffset,
+                  appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, getVsyncPeriod());
 
     // Dump static screen stats
     result.append("\n");
@@ -5021,7 +5061,10 @@
         case SET_TRANSACTION_STATE:
         case CREATE_CONNECTION:
         case GET_COLOR_MANAGEMENT:
-        case GET_COMPOSITION_PREFERENCE: {
+        case GET_COMPOSITION_PREFERENCE:
+        case GET_PROTECTED_CONTENT_SUPPORT:
+        case CACHE_BUFFER:
+        case UNCACHE_BUFFER: {
             return OK;
         }
         case CAPTURE_LAYERS:
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2434a31..499ebcd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -17,63 +17,59 @@
 #ifndef ANDROID_SURFACE_FLINGER_H
 #define ANDROID_SURFACE_FLINGER_H
 
-#include <memory>
-#include <stdint.h>
 #include <sys/types.h>
 
 /*
  * NOTE: Make sure this file doesn't include  anything from <gl/ > or <gl2/ >
  */
 
-#include <cutils/compiler.h>
+#include <android-base/thread_annotations.h>
 #include <cutils/atomic.h>
-
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-#include <utils/Trace.h>
-
-#include <ui/FenceTime.h>
-#include <ui/PixelFormat.h>
-#include <math/mat4.h>
-
+#include <cutils/compiler.h>
+#include <gui/BufferQueue.h>
 #include <gui/FrameTimestamps.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
-
 #include <gui/OccupancyTracker.h>
-#include <gui/BufferQueue.h>
-
 #include <hardware/hwcomposer_defs.h>
-
+#include <layerproto/LayerProtoHeader.h>
+#include <math/mat4.h>
 #include <serviceutils/PriorityDumper.h>
-
 #include <system/graphics.h>
+#include <ui/FenceTime.h>
+#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+#include <utils/threads.h>
 
 #include "Barrier.h"
+#include "BufferStateLayerCache.h"
 #include "DisplayDevice.h"
+#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/HWComposer.h"
+#include "Effects/Daltonizer.h"
 #include "FrameTracker.h"
 #include "LayerBE.h"
 #include "LayerStats.h"
 #include "LayerVector.h"
-#include "SurfaceFlingerFactory.h"
-#include "SurfaceInterceptor.h"
-#include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
-
-#include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/HWComposer.h"
-#include "Effects/Daltonizer.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/MessageQueue.h"
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
+#include "SurfaceFlingerFactory.h"
+#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
+#include "TransactionCompletedThread.h"
 
+#include <atomic>
+#include <cstdint>
 #include <map>
+#include <memory>
 #include <mutex>
 #include <queue>
 #include <set>
@@ -82,8 +78,6 @@
 #include <unordered_map>
 #include <utility>
 
-#include <layerproto/LayerProtoHeader.h>
-
 using namespace android::surfaceflinger;
 
 namespace android {
@@ -152,10 +146,6 @@
 
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 
-    // constant members (no synchronization needed for access)
-    EGLContext mEGLContext;
-    EGLDisplay mEGLDisplay;
-
     FenceTimeline mGlCompositionDoneTimeline;
     FenceTimeline mDisplayTimeline;
 
@@ -416,77 +406,79 @@
     /* ------------------------------------------------------------------------
      * IBinder interface
      */
-    virtual status_t onTransact(uint32_t code, const Parcel& data,
-        Parcel* reply, uint32_t flags);
-    virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+    status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
 
     /* ------------------------------------------------------------------------
      * ISurfaceComposer interface
      */
-    virtual sp<ISurfaceComposerClient> createConnection();
-    virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
-    virtual void destroyDisplay(const sp<IBinder>& displayToken);
-    virtual sp<IBinder> getBuiltInDisplay(int32_t id);
-    virtual void setTransactionState(const Vector<ComposerState>& state,
-                                     const Vector<DisplayState>& displays, uint32_t flags,
-                                     const sp<IBinder>& applyToken,
-                                     const InputWindowCommands& inputWindowCommands);
-    virtual void bootFinished();
-    virtual bool authenticateSurfaceTexture(
-        const sp<IGraphicBufferProducer>& bufferProducer) const;
-    virtual status_t getSupportedFrameTimestamps(
-            std::vector<FrameEvent>* outSupported) const;
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
-    virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
-                                   uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
-                                   ISurfaceComposer::Rotation rotation);
-    virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
-                                   float frameScale, bool childrenOnly);
-    virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
-    virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
-                                       Vector<DisplayInfo>* configs);
-    virtual int getActiveConfig(const sp<IBinder>& displayToken);
-    virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken,
-                                          Vector<ui::ColorMode>* configs);
-    virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken);
-    virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
-    virtual void setPowerMode(const sp<IBinder>& displayToken, int mode);
-    virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
-    virtual status_t clearAnimationFrameStats();
-    virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
-    virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken,
-                                        HdrCapabilities* outCapabilities) const;
-    virtual status_t enableVSyncInjections(bool enable);
-    virtual status_t injectVSync(nsecs_t when);
-    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
-    virtual status_t getColorManagement(bool* outGetColorManagement) const;
+    sp<ISurfaceComposerClient> createConnection() override;
+    sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
+    void destroyDisplay(const sp<IBinder>& displayToken) override;
+    sp<IBinder> getBuiltInDisplay(int32_t id) override;
+    void setTransactionState(const Vector<ComposerState>& state,
+                             const Vector<DisplayState>& displays, uint32_t flags,
+                             const sp<IBinder>& applyToken,
+                             const InputWindowCommands& inputWindowCommands,
+                             int64_t desiredPresentTime) override;
+    void bootFinished() override;
+    bool authenticateSurfaceTexture(
+            const sp<IGraphicBufferProducer>& bufferProducer) const override;
+    status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+    status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
+                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+                           Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                           bool useIdentityTransform, ISurfaceComposer::Rotation rotation) override;
+    status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+                           const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
+    status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
+    status_t getDisplayConfigs(const sp<IBinder>& displayToken,
+                               Vector<DisplayInfo>* configs) override;
+    int getActiveConfig(const sp<IBinder>& displayToken) override;
+    status_t getDisplayColorModes(const sp<IBinder>& displayToken,
+                                  Vector<ui::ColorMode>* configs) override;
+    ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override;
+    status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+    void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
+    status_t setActiveConfig(const sp<IBinder>& displayToken, int id) override;
+    status_t clearAnimationFrameStats() override;
+    status_t getAnimationFrameStats(FrameStats* outStats) const override;
+    status_t getHdrCapabilities(const sp<IBinder>& displayToken,
+                                HdrCapabilities* outCapabilities) const override;
+    status_t enableVSyncInjections(bool enable) override;
+    status_t injectVSync(nsecs_t when) override;
+    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const override;
+    status_t getColorManagement(bool* outGetColorManagement) const override;
     status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
                                       ui::Dataspace* outWideColorGamutDataspace,
                                       ui::PixelFormat* outWideColorGamutPixelFormat) const override;
-    virtual status_t getDisplayedContentSamplingAttributes(
-            const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace,
-            uint8_t* outComponentMask) const override;
-    virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
-                                                      uint8_t componentMask,
-                                                      uint64_t maxFrames) const override;
-    virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
-                                               uint64_t timestamp,
-                                               DisplayedFrameStats* outStats) const override;
+    status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+                                                   ui::PixelFormat* outFormat,
+                                                   ui::Dataspace* outDataspace,
+                                                   uint8_t* outComponentMask) const override;
+    status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+                                              uint8_t componentMask,
+                                              uint64_t maxFrames) const override;
+    status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+                                       uint64_t timestamp,
+                                       DisplayedFrameStats* outStats) const override;
+    status_t getProtectedContentSupport(bool* outSupported) const override;
+    status_t cacheBuffer(const sp<IBinder>& token, const sp<GraphicBuffer>& buffer,
+                         int32_t* outBufferId) override;
+    status_t uncacheBuffer(const sp<IBinder>& token, int32_t bufferId) override;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
      */
-    virtual void binderDied(const wp<IBinder>& who);
+    void binderDied(const wp<IBinder>& who) override;
 
     /* ------------------------------------------------------------------------
      * RefBase interface
      */
-    virtual void onFirstRef();
+    void onFirstRef() override;
 
     /* ------------------------------------------------------------------------
      * HWC2::ComposerCallback / HWComposer::EventHandler interface
@@ -508,13 +500,13 @@
     void signalRefresh();
 
     // called on the main thread in response to initializeDisplays()
-    void onInitializeDisplays();
+    void onInitializeDisplays() REQUIRES(mStateLock);
     // setActiveConfigInternal() posted on a main thread for async execution
     status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
     // called on the main thread in response to setActiveConfig()
-    void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode);
+    void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
     // called on the main thread in response to setPowerMode()
-    void setPowerModeInternal(const sp<DisplayDevice>& display, int mode);
+    void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
 
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
@@ -552,7 +544,8 @@
     void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction();
     bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
-    bool composerStateContainsUnsignaledFences(const Vector<ComposerState>& states);
+    bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+                                       const Vector<ComposerState>& states);
     uint32_t setClientStateLocked(const ComposerState& composerState);
     uint32_t setDisplayStateLocked(const DisplayState& s);
     uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands);
@@ -706,6 +699,7 @@
 
     void preComposition();
     void postComposition();
+    void getCompositorTiming(CompositorTiming* compositorTiming);
     void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
                                 std::shared_ptr<FenceTime>& presentFenceTime);
     void setCompositorTimingSnapped(const DisplayStatInfo& stats,
@@ -760,18 +754,38 @@
     /* ------------------------------------------------------------------------
      * VSync
      */
+    nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
     void enableHardwareVsync();
-    void resyncToHardwareVsync(bool makeAvailable);
+    void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
     void disableHardwareVsync(bool makeUnavailable);
 
-public:
-    void resyncWithRateLimit();
-    void getCompositorTiming(CompositorTiming* compositorTiming);
-private:
     // Sets the refresh rate to newFps by switching active configs, if they are available for
     // the desired refresh rate.
     void setRefreshRateTo(float newFps);
 
+    using GetVsyncPeriod = std::function<nsecs_t()>;
+
+    // Stores per-display state about VSYNC.
+    struct VsyncState {
+        explicit VsyncState(SurfaceFlinger& flinger) : flinger(flinger) {}
+
+        void resync(const GetVsyncPeriod&);
+
+        SurfaceFlinger& flinger;
+        std::atomic<nsecs_t> lastResyncTime = 0;
+    };
+
+    const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
+
+    auto makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod) {
+        std::weak_ptr<VsyncState> ptr = mPrimaryVsyncState;
+        return [ptr, getVsyncPeriod = std::move(getVsyncPeriod)]() {
+            if (const auto vsync = ptr.lock()) {
+                vsync->resync(getVsyncPeriod);
+            }
+        };
+    }
+
     /* ------------------------------------------------------------------------
      * Debugging & dumpsys
      */
@@ -817,9 +831,11 @@
     }
 
     void listLayersLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
-    void dumpStatsLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+    void dumpStatsLocked(const Vector<String16>& args, size_t& index, std::string& result) const
+            REQUIRES(mStateLock);
     void clearStatsLocked(const Vector<String16>& args, size_t& index, std::string& result);
-    void dumpAllLocked(const Vector<String16>& args, size_t& index, std::string& result) const;
+    void dumpAllLocked(const Vector<String16>& args, size_t& index, std::string& result) const
+            REQUIRES(mStateLock);
     bool startDdmConnection();
     void appendSfConfigString(std::string& result) const;
 
@@ -979,12 +995,17 @@
     };
     struct TransactionState {
         TransactionState(const Vector<ComposerState>& composerStates,
-                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags)
-              : states(composerStates), displays(displayStates), flags(transactionFlags) {}
+                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
+                         int64_t desiredPresentTime)
+              : states(composerStates),
+                displays(displayStates),
+                flags(transactionFlags),
+                time(desiredPresentTime) {}
 
         Vector<ComposerState> states;
         Vector<DisplayState> displays;
         uint32_t flags;
+        int64_t time;
     };
     std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
 
@@ -1024,6 +1045,8 @@
     sp<IInputFlinger> mInputFlinger;
 
     InputWindowCommands mInputWindowCommands;
+
+    BufferStateLayerCache mBufferStateLayerCache;
 };
 }; // namespace android
 
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index a1a8692..d2b7fe0 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -62,8 +62,7 @@
     mThread = std::thread(&TransactionCompletedThread::threadMain, this);
 }
 
-void TransactionCompletedThread::registerPendingLatchedCallbackHandle(
-        const sp<CallbackHandle>& handle) {
+void TransactionCompletedThread::registerPendingCallbackHandle(const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
 
     sp<IBinder> listener = IInterface::asBinder(handle->listener);
@@ -72,19 +71,10 @@
     mPendingTransactions[listener][callbackIds]++;
 }
 
-void TransactionCompletedThread::addLatchedCallbackHandles(
-        const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime,
-        const sp<Fence>& previousReleaseFence) {
+void TransactionCompletedThread::addPresentedCallbackHandles(
+        const std::deque<sp<CallbackHandle>>& handles) {
     std::lock_guard lock(mMutex);
 
-    // If the previous release fences have not signaled, something as probably gone wrong.
-    // Store the fences and check them again before sending a callback.
-    if (previousReleaseFence &&
-        previousReleaseFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) {
-        ALOGD("release fence from the previous frame has not signaled");
-        mPreviousReleaseFences.push_back(previousReleaseFence);
-    }
-
     for (const auto& handle : handles) {
         auto listener = mPendingTransactions.find(IInterface::asBinder(handle->listener));
         auto& pendingCallbacks = listener->second;
@@ -101,17 +91,16 @@
             ALOGE("there are more latched callbacks than there were registered callbacks");
         }
 
-        addCallbackHandle(handle, latchTime);
+        addCallbackHandle(handle);
     }
 }
 
-void TransactionCompletedThread::addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle) {
+void TransactionCompletedThread::addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle) {
     std::lock_guard lock(mMutex);
     addCallbackHandle(handle);
 }
 
-void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
-                                                   nsecs_t latchTime) {
+void TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle) {
     const sp<IBinder> listener = IInterface::asBinder(handle->listener);
 
     // If we don't already have a reference to this listener, linkToDeath so we get a notification
@@ -128,9 +117,9 @@
     listenerStats.listener = handle->listener;
 
     auto& transactionStats = listenerStats.transactionStats[handle->callbackIds];
-    transactionStats.latchTime = latchTime;
+    transactionStats.latchTime = handle->latchTime;
     transactionStats.surfaceStats.emplace_back(handle->surfaceControl, handle->acquireTime,
-                                               handle->releasePreviousBuffer);
+                                               handle->previousReleaseFence);
 }
 
 void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
@@ -151,15 +140,6 @@
     while (mKeepRunning) {
         mConditionVariable.wait(mMutex);
 
-        // We should never hit this case. The release fences from the previous frame should have
-        // signaled long before the current frame is presented.
-        for (const auto& fence : mPreviousReleaseFences) {
-            status_t status = fence->wait(100);
-            if (status != NO_ERROR) {
-                ALOGE("previous release fence has not signaled, err %d", status);
-            }
-        }
-
         // For each listener
         auto it = mListenerStats.begin();
         while (it != mListenerStats.end()) {
@@ -200,7 +180,6 @@
 
         if (mPresentFence) {
             mPresentFence.clear();
-            mPreviousReleaseFences.clear();
         }
     }
 }
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index 1612f69..f49306d 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -40,7 +40,9 @@
     sp<IBinder> surfaceControl;
 
     bool releasePreviousBuffer = false;
+    sp<Fence> previousReleaseFence;
     nsecs_t acquireTime = -1;
+    nsecs_t latchTime = -1;
 };
 
 class TransactionCompletedThread {
@@ -54,14 +56,13 @@
     // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send
     // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
     // presented.
-    void registerPendingLatchedCallbackHandle(const sp<CallbackHandle>& handle);
-    // Notifies the TransactionCompletedThread that a pending CallbackHandle has been latched.
-    void addLatchedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles, nsecs_t latchTime,
-                                   const sp<Fence>& previousReleaseFence);
+    void registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
+    // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
+    void addPresentedCallbackHandles(const std::deque<sp<CallbackHandle>>& handles);
 
     // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
     // presented this frame.
-    void addUnlatchedCallbackHandle(const sp<CallbackHandle>& handle);
+    void addUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
 
     void addPresentFence(const sp<Fence>& presentFence);
 
@@ -70,8 +71,7 @@
 private:
     void threadMain();
 
-    void addCallbackHandle(const sp<CallbackHandle>& handle, nsecs_t latchTime = -1)
-            REQUIRES(mMutex);
+    void addCallbackHandle(const sp<CallbackHandle>& handle) REQUIRES(mMutex);
 
     class ThreadDeathRecipient : public IBinder::DeathRecipient {
     public:
@@ -110,7 +110,6 @@
     bool mKeepRunning GUARDED_BY(mMutex) = true;
 
     sp<Fence> mPresentFence GUARDED_BY(mMutex);
-    std::vector<sp<Fence>> mPreviousReleaseFences GUARDED_BY(mMutex);
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 92ae87b..bdb3ac6 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -21,6 +21,7 @@
 #include <android/frameworks/displayservice/1.0/IDisplayService.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
@@ -41,10 +42,14 @@
         return OK;
     }
 
-    using android::hardware::graphics::allocator::V2_0::IAllocator;
+    status_t result = hardware::registerPassthroughServiceImplementation<
+            android::hardware::graphics::allocator::V3_0::IAllocator>();
+    if (result == OK) {
+        return OK;
+    }
 
-    status_t result =
-        hardware::registerPassthroughServiceImplementation<IAllocator>();
+    result = hardware::registerPassthroughServiceImplementation<
+            android::hardware::graphics::allocator::V2_0::IAllocator>();
     if (result != OK) {
         ALOGE("could not start graphics allocator service");
         return result;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index ef6999d..216532a 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2323,6 +2323,143 @@
     Transaction().setSidebandStream(layer, nullptr).apply();
 }
 
+TEST_F(LayerTransactionTest, CacheBuffer_BufferState) {
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+
+    int32_t bufferId = -1;
+    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
+    ASSERT_GE(bufferId, 0);
+
+    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
+}
+
+TEST_F(LayerTransactionTest, CacheBuffers_BufferState) {
+    std::vector<int32_t> bufferIds;
+    int32_t bufferCount = 20;
+
+    for (int i = 0; i < bufferCount; i++) {
+        sp<GraphicBuffer> buffer =
+                new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                                  BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                          BufferUsage::COMPOSER_OVERLAY,
+                                  "test");
+        int32_t bufferId = -1;
+        ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
+        if (bufferId < 0) {
+            EXPECT_GE(bufferId, 0);
+            break;
+        }
+        bufferIds.push_back(bufferId);
+    }
+
+    for (int32_t bufferId : bufferIds) {
+        ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
+    }
+}
+
+TEST_F(LayerTransactionTest, CacheBufferInvalid_BufferState) {
+    sp<GraphicBuffer> buffer = nullptr;
+
+    int32_t bufferId = -1;
+    ASSERT_NE(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
+    ASSERT_LT(bufferId, 0);
+}
+
+TEST_F(LayerTransactionTest, UncacheBufferTwice_BufferState) {
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+
+    int32_t bufferId = -1;
+    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
+    ASSERT_GE(bufferId, 0);
+
+    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
+    mClient->uncacheBuffer(bufferId);
+}
+
+TEST_F(LayerTransactionTest, UncacheBufferInvalidId_BufferState) {
+    mClient->uncacheBuffer(-1);
+    mClient->uncacheBuffer(0);
+    mClient->uncacheBuffer(1);
+    mClient->uncacheBuffer(5);
+    mClient->uncacheBuffer(1000);
+}
+
+TEST_F(LayerTransactionTest, SetCachedBuffer_BufferState) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+
+    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+    int32_t bufferId = -1;
+    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(buffer, &bufferId));
+    ASSERT_GE(bufferId, 0);
+
+    Transaction().setCachedBuffer(layer, bufferId).apply();
+
+    auto shot = screenshot();
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+
+    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
+}
+
+TEST_F(LayerTransactionTest, SetCachedBufferDelayed_BufferState) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    sp<GraphicBuffer> cachedBuffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+    int32_t bufferId = -1;
+    ASSERT_EQ(NO_ERROR, mClient->cacheBuffer(cachedBuffer, &bufferId));
+    ASSERT_GE(bufferId, 0);
+
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::BLUE);
+    Transaction().setBuffer(layer, buffer).apply();
+    {
+        SCOPED_TRACE("Uncached buffer");
+
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    fillGraphicBufferColor(cachedBuffer, Rect(0, 0, 32, 32), Color::RED);
+    Transaction().setCachedBuffer(layer, bufferId).apply();
+    {
+        SCOPED_TRACE("Cached buffer");
+
+        auto shot = screenshot();
+        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+    }
+
+    ASSERT_EQ(NO_ERROR, mClient->uncacheBuffer(bufferId));
+}
+
 class ColorTransformHelper {
 public:
     static void DegammaColorSingle(half& s) {
@@ -2542,6 +2679,7 @@
     enum PreviousBuffer {
         NOT_RELEASED = 0,
         RELEASED,
+        UNKNOWN,
     };
 
     void reset() {
@@ -2567,11 +2705,23 @@
         }
     }
 
+    void addExpectedPresentTime(nsecs_t expectedPresentTime) {
+        mExpectedPresentTime = expectedPresentTime;
+    }
+
     void verifyTransactionStats(const TransactionStats& transactionStats) const {
         const auto& [latchTime, presentFence, surfaceStats] = transactionStats;
         if (mTransactionResult == ExpectedResult::Transaction::PRESENTED) {
             ASSERT_GE(latchTime, 0) << "bad latch time";
             ASSERT_NE(presentFence, nullptr);
+            if (mExpectedPresentTime >= 0) {
+                ASSERT_EQ(presentFence->wait(3000), NO_ERROR);
+                ASSERT_GE(presentFence->getSignalTime(), mExpectedPresentTime - nsecs_t(5 * 1e6));
+                // if the panel is running at 30 hz, at the worst case, our expected time just
+                // misses vsync and we have to wait another 33.3ms
+                ASSERT_LE(presentFence->getSignalTime(),
+                          mExpectedPresentTime + nsecs_t(66.666666 * 1e6));
+            }
         } else {
             ASSERT_EQ(presentFence, nullptr) << "transaction shouldn't have been presented";
             ASSERT_EQ(latchTime, -1) << "unpresented transactions shouldn't be latched";
@@ -2596,14 +2746,19 @@
               : mBufferResult(bufferResult), mPreviousBufferResult(previousBufferResult) {}
 
         void verifySurfaceStats(const SurfaceStats& surfaceStats, nsecs_t latchTime) const {
-            const auto& [surfaceControl, acquireTime, releasePreviousBuffer] = surfaceStats;
+            const auto& [surfaceControl, acquireTime, previousReleaseFence] = surfaceStats;
 
             ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)
                     << "bad acquire time";
             ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time";
-            ASSERT_EQ(releasePreviousBuffer,
-                      mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED)
-                    << "bad previous buffer released";
+
+            if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) {
+                ASSERT_NE(previousReleaseFence, nullptr)
+                        << "failed to set release prev buffer fence";
+            } else if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::NOT_RELEASED) {
+                ASSERT_EQ(previousReleaseFence, nullptr)
+                        << "should not have set released prev buffer fence";
+            }
         }
 
     private:
@@ -2617,6 +2772,7 @@
         }
     };
     ExpectedResult::Transaction mTransactionResult = ExpectedResult::Transaction::NOT_PRESENTED;
+    nsecs_t mExpectedPresentTime = -1;
     std::unordered_map<sp<IBinder>, ExpectedSurfaceResult, IBinderHash> mExpectedSurfaceResults;
 };
 
@@ -3177,13 +3333,11 @@
     Transaction transaction;
     CallbackHelper callback;
     std::vector<ExpectedResult> expectedResults(50);
-    ExpectedResult::PreviousBuffer previousBufferResult =
-            ExpectedResult::PreviousBuffer::NOT_RELEASED;
     for (auto& expected : expectedResults) {
         expected.reset();
         expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
-                            ExpectedResult::Buffer::ACQUIRED, previousBufferResult);
-        previousBufferResult = ExpectedResult::PreviousBuffer::RELEASED;
+                            ExpectedResult::Buffer::ACQUIRED,
+                            ExpectedResult::PreviousBuffer::UNKNOWN);
 
         int err = fillTransaction(transaction, &callback, layer);
         if (err) {
@@ -3268,6 +3422,143 @@
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
 
+TEST_F(LayerCallbackTest, DesiredPresentTime) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 100ms in the future
+    nsecs_t time = systemTime() + (100 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    expected.addExpectedPresentTime(time);
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+    Transaction transaction;
+    CallbackHelper callback1;
+    int err = fillTransaction(transaction, &callback1, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 100ms in the future
+    nsecs_t time = systemTime() + (100 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected1;
+    expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    expected1.addExpectedPresentTime(time);
+
+    CallbackHelper callback2;
+    err = fillTransaction(transaction, &callback2, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 33ms after the first frame
+    time += (33.3 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected2;
+    expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+                         ExpectedResult::Buffer::ACQUIRED,
+                         ExpectedResult::PreviousBuffer::RELEASED);
+    expected2.addExpectedPresentTime(time);
+
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+    Transaction transaction;
+    CallbackHelper callback1;
+    int err = fillTransaction(transaction, &callback1, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 100ms in the future
+    nsecs_t time = systemTime() + (100 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected1;
+    expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    expected1.addExpectedPresentTime(time);
+
+    CallbackHelper callback2;
+    err = fillTransaction(transaction, &callback2, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 33ms before the previous frame
+    time -= (33.3 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected2;
+    expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+                         ExpectedResult::Buffer::ACQUIRED,
+                         ExpectedResult::PreviousBuffer::RELEASED);
+
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true));
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true));
+}
+
+TEST_F(LayerCallbackTest, DesiredPresentTime_Past) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+    Transaction transaction;
+    CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    // Try to present 100ms in the past
+    nsecs_t time = systemTime() - (100 * 1e6);
+
+    transaction.setDesiredPresentTime(time);
+    transaction.apply();
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    expected.addExpectedPresentTime(systemTime());
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
 class LayerUpdateTest : public LayerTransactionTest {
 protected:
     virtual void SetUp() {
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index a5b522e..a2c0611 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -11,6 +11,7 @@
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "android.hardware.power@1.3",
         "libbase",
         "libbinder",
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 2d26bb3..c18068f 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -47,10 +47,11 @@
 
 class EventThreadTest : public testing::Test {
 protected:
-    class MockEventThreadConnection : public android::EventThreadConnection {
+    class MockEventThreadConnection : public EventThreadConnection {
     public:
-        explicit MockEventThreadConnection(android::impl::EventThread* eventThread)
-              : android::EventThreadConnection(eventThread) {}
+        MockEventThreadConnection(android::impl::EventThread* eventThread,
+                                  ResyncCallback&& resyncCallback)
+              : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
     };
 
@@ -113,14 +114,14 @@
 void EventThreadTest::createThread() {
     mThread =
             std::make_unique<android::impl::EventThread>(&mVSyncSource,
-                                                         mResyncCallRecorder.getInvocable(),
                                                          mInterceptVSyncCallRecorder.getInvocable(),
                                                          "unit-test-event-thread");
 }
 
 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
         ConnectionEventRecorder& recorder) {
-    sp<MockEventThreadConnection> connection = new MockEventThreadConnection(mThread.get());
+    sp<MockEventThreadConnection> connection =
+            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
     return connection;
 }
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 4253ad8..3dd5143 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -8,12 +8,9 @@
 
 #include <mutex>
 
-#include "AsyncCallRecorder.h"
-#include "Scheduler/DispSync.h"
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/Scheduler.h"
-#include "mock/MockDispSync.h"
 #include "mock/MockEventThread.h"
 
 using testing::_;
@@ -26,7 +23,7 @@
     class MockEventThreadConnection : public android::EventThreadConnection {
     public:
         explicit MockEventThreadConnection(EventThread* eventThread)
-              : EventThreadConnection(eventThread) {}
+              : EventThreadConnection(eventThread, ResyncCallback()) {}
         ~MockEventThreadConnection() = default;
 
         MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -46,7 +43,6 @@
         std::unique_ptr<EventThread> makeEventThread(
                 const std::string& /* connectionName */, DispSync* /* dispSync */,
                 nsecs_t /* phaseOffsetNs */,
-                impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
                 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
             return std::move(mEventThread);
         }
@@ -61,13 +57,9 @@
     ~SchedulerTest() override;
 
     sp<Scheduler::ConnectionHandle> mConnectionHandle;
-    mock::DispSync* mPrimaryDispSync = new mock::DispSync();
     mock::EventThread* mEventThread;
     std::unique_ptr<MockScheduler> mScheduler;
     sp<MockEventThreadConnection> mEventThreadConnection;
-
-    AsyncCallRecorder<void (*)()> mResyncCallRecorder;
-    AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
 };
 
 SchedulerTest::SchedulerTest() {
@@ -84,12 +76,12 @@
 
     // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
     // sure that call gets executed and returns an EventThread::Connection object.
-    EXPECT_CALL(*mEventThread, createEventConnection())
+    EXPECT_CALL(*mEventThread, createEventConnection(_))
             .WillRepeatedly(Return(mEventThreadConnection));
 
-    mConnectionHandle =
-            mScheduler->createConnection("appConnection", 16, mResyncCallRecorder.getInvocable(),
-                                         mInterceptVSyncCallRecorder.getInvocable());
+    mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+                                                     impl::EventThread::InterceptVSyncsCallback());
+    EXPECT_TRUE(mConnectionHandle != nullptr);
 }
 
 SchedulerTest::~SchedulerTest() {
@@ -102,17 +94,13 @@
 /* ------------------------------------------------------------------------
  * Test cases
  */
-TEST_F(SchedulerTest, canCreateAndDestroyTest) {
-    EXPECT_FALSE(mResyncCallRecorder.waitForCall().has_value());
-    EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall().has_value());
-    EXPECT_EQ(0, mConnectionHandle->id);
-}
 
 TEST_F(SchedulerTest, testNullPtr) {
     // Passing a null pointer for ConnectionHandle is a valid argument. The code doesn't throw any
     // exceptions, just gracefully continues.
     sp<IDisplayEventConnection> returnedValue;
-    ASSERT_NO_FATAL_FAILURE(returnedValue = mScheduler->createDisplayEventConnection(nullptr));
+    ASSERT_NO_FATAL_FAILURE(
+            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -132,8 +120,9 @@
     sp<Scheduler::ConnectionHandle> connectionHandle = new Scheduler::ConnectionHandle(20);
 
     sp<IDisplayEventConnection> returnedValue;
-    ASSERT_NO_FATAL_FAILURE(returnedValue =
-                                    mScheduler->createDisplayEventConnection(connectionHandle));
+    ASSERT_NO_FATAL_FAILURE(
+            returnedValue =
+                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -160,8 +149,9 @@
 
 TEST_F(SchedulerTest, validConnectionHandle) {
     sp<IDisplayEventConnection> returnedValue;
-    ASSERT_NO_FATAL_FAILURE(returnedValue =
-                                    mScheduler->createDisplayEventConnection(mConnectionHandle));
+    ASSERT_NO_FATAL_FAILURE(
+            returnedValue =
+                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
     EXPECT_TRUE(returnedValue != nullptr);
     ASSERT_EQ(returnedValue, mEventThreadConnection);
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index c531427..687941a 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -235,9 +235,14 @@
 
     auto setDisplayStateLocked(const DisplayState& s) { return mFlinger->setDisplayStateLocked(s); }
 
-    auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); }
+    // Allow reading display state without locking, as if called on the SF main thread.
+    auto onInitializeDisplays() NO_THREAD_SAFETY_ANALYSIS {
+        return mFlinger->onInitializeDisplays();
+    }
 
-    auto setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
+    // Allow reading display state without locking, as if called on the SF main thread.
+    auto setPowerModeInternal(const sp<DisplayDevice>& display,
+                              int mode) NO_THREAD_SAFETY_ANALYSIS {
         return mFlinger->setPowerModeInternal(display, mode);
     }
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 48d45fa..3242ef1 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,7 @@
     EventThread();
     ~EventThread() override;
 
-    MOCK_CONST_METHOD0(createEventConnection, sp<EventThreadConnection>());
+    MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index 8c113e2..e22d3e8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -30,8 +30,8 @@
     ~MessageQueue() override;
 
     MOCK_METHOD1(init, void(const sp<SurfaceFlinger>&));
-    MOCK_METHOD1(setEventThread, void(android::EventThread*));
-    MOCK_METHOD1(setEventConnection, void(const sp<android::EventThreadConnection>& connection));
+    MOCK_METHOD2(setEventThread, void(android::EventThread*, ResyncCallback));
+    MOCK_METHOD1(setEventConnection, void(const sp<EventThreadConnection>& connection));
     MOCK_METHOD0(waitMessage, void());
     MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
     MOCK_METHOD0(invalidate, void());
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 7a7e437..ba7d7f9 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -28,7 +28,6 @@
 cc_library_static {
     name: "libbufferhubd",
     srcs: [
-        "buffer_channel.cpp",
         "buffer_hub.cpp",
         "consumer_channel.cpp",
         "consumer_queue_channel.cpp",
diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp
deleted file mode 100644
index 695396c..0000000
--- a/services/vr/bufferhubd/buffer_channel.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#include <errno.h>
-#include <private/dvr/buffer_channel.h>
-#include <private/dvr/producer_channel.h>
-
-using android::pdx::BorrowedHandle;
-using android::pdx::ErrorStatus;
-using android::pdx::Message;
-using android::pdx::RemoteChannelHandle;
-using android::pdx::Status;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
-                             uint32_t width, uint32_t height,
-                             uint32_t layer_count, uint32_t format,
-                             uint64_t usage, size_t user_metadata_size)
-    : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType) {
-  buffer_node_ = std::make_shared<BufferNode>(
-      width, height, layer_count, format, usage, user_metadata_size);
-  if (!buffer_node_->IsValid()) {
-    ALOGE("BufferChannel::BufferChannel: Failed to create BufferNode.");
-    return;
-  }
-  client_state_mask_ = buffer_node_->AddNewActiveClientsBitToMask();
-}
-
-BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
-                             int channel_id,
-                             std::shared_ptr<BufferNode> buffer_node)
-    : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
-      buffer_node_(buffer_node) {
-  client_state_mask_ = buffer_node_->AddNewActiveClientsBitToMask();
-  if (client_state_mask_ == 0U) {
-    ALOGE("BufferChannel::BufferChannel: %s", strerror(errno));
-    buffer_node_ = nullptr;
-  }
-}
-
-BufferChannel::~BufferChannel() {
-  ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.",
-           channel_id(), buffer_id());
-  if (client_state_mask_ != 0U) {
-    buffer_node_->RemoveClientsBitFromMask(client_state_mask_);
-  }
-  Hangup();
-}
-
-BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const {
-  return BufferInfo(
-      buffer_id(), /*consumer_count=*/0, buffer_node_->buffer_desc().width,
-      buffer_node_->buffer_desc().height, buffer_node_->buffer_desc().layers,
-      buffer_node_->buffer_desc().format, buffer_node_->buffer_desc().usage,
-      /*state=*/0, /*signaled_mask=*/0, /*index=*/0);
-}
-
-void BufferChannel::HandleImpulse(Message& /*message*/) {
-  ATRACE_NAME("BufferChannel::HandleImpulse");
-}
-
-bool BufferChannel::HandleMessage(Message& message) {
-  ATRACE_NAME("BufferChannel::HandleMessage");
-  switch (message.GetOp()) {
-    case DetachedBufferRPC::Import::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Import>(
-          *this, &BufferChannel::OnImport, message);
-      return true;
-
-    case DetachedBufferRPC::Duplicate::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Duplicate>(
-          *this, &BufferChannel::OnDuplicate, message);
-      return true;
-
-    default:
-      return false;
-  }
-}
-
-Status<BufferTraits<BorrowedHandle>> BufferChannel::OnImport(
-    Message& /*message*/) {
-  ATRACE_NAME("BufferChannel::OnImport");
-  ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.", buffer_id());
-
-  BorrowedHandle ashmem_handle =
-      BorrowedHandle(buffer_node_->metadata().ashmem_fd().get());
-
-  // TODO(b/112057680) Move away from the GraphicBuffer-based IonBuffer.
-  return BufferTraits<BorrowedHandle>{
-      /*buffer_handle=*/buffer_node_->buffer_handle(),
-      /*metadata_handle=*/ashmem_handle,
-      /*id=*/buffer_id(),
-      /*client_state_mask=*/client_state_mask_,
-      /*metadata_size=*/buffer_node_->metadata().metadata_size(),
-      /*width=*/buffer_node_->buffer_desc().width,
-      /*height=*/buffer_node_->buffer_desc().height,
-      /*layer_count=*/buffer_node_->buffer_desc().layers,
-      /*format=*/buffer_node_->buffer_desc().format,
-      /*usage=*/buffer_node_->buffer_desc().usage,
-      /*stride=*/buffer_node_->buffer_desc().stride,
-      /*acquire_fence_fd=*/BorrowedHandle{},
-      /*released_fence_fd=*/BorrowedHandle{}};
-}
-
-Status<RemoteChannelHandle> BufferChannel::OnDuplicate(Message& message) {
-  ATRACE_NAME("BufferChannel::OnDuplicate");
-  ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.", buffer_id());
-
-  int channel_id;
-  auto status = message.PushChannel(0, nullptr, &channel_id);
-  if (!status.ok()) {
-    ALOGE("BufferChannel::OnDuplicate: Failed to push buffer channel: %s",
-          status.GetErrorMessage().c_str());
-    return ErrorStatus(ENOMEM);
-  }
-
-  auto channel = std::shared_ptr<BufferChannel>(
-      new BufferChannel(service(), buffer_id(), channel_id, buffer_node_));
-  if (!channel->IsValid()) {
-    ALOGE("BufferChannel::OnDuplicate: Invalid buffer. %s", strerror(errno));
-    return ErrorStatus(EINVAL);
-  }
-
-  const auto channel_status =
-      service()->SetChannel(channel_id, std::move(channel));
-  if (!channel_status) {
-    // Technically, this should never fail, as we just pushed the channel. Note
-    // that LOG_FATAL will be stripped out in non-debug build.
-    LOG_FATAL(
-        "BufferChannel::OnDuplicate: Failed to set new buffer channel: %s.",
-        channel_status.GetErrorMessage().c_str());
-  }
-
-  return status;
-}
-
-}  // namespace dvr
-}  // namespace android
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index f50d292..6409265 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -10,7 +10,6 @@
 #include <log/log.h>
 #include <pdx/default_transport/service_endpoint.h>
 #include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/buffer_channel.h>
 #include <private/dvr/buffer_hub.h>
 #include <private/dvr/consumer_channel.h>
 #include <private/dvr/producer_channel.h>
@@ -242,11 +241,6 @@
           *this, &BufferHubService::OnCreateBuffer, message);
       return {};
 
-    case DetachedBufferRPC::Create::Opcode:
-      DispatchRemoteMethod<DetachedBufferRPC::Create>(
-          *this, &BufferHubService::OnCreateDetachedBuffer, message);
-      return {};
-
     case BufferHubRPC::CreateProducerQueue::Opcode:
       DispatchRemoteMethod<BufferHubRPC::CreateProducerQueue>(
           *this, &BufferHubService::OnCreateProducerQueue, message);
@@ -288,43 +282,6 @@
   }
 }
 
-pdx::Status<void> BufferHubService::OnCreateDetachedBuffer(
-    pdx::Message& message, uint32_t width, uint32_t height,
-    uint32_t layer_count, uint32_t format, uint64_t usage,
-    size_t user_metadata_size) {
-  // Use the producer channel id as the global buffer id.
-  const int buffer_id = message.GetChannelId();
-  ALOGD_IF(TRACE,
-           "BufferHubService::OnCreateDetachedBuffer: buffer_id=%d width=%u "
-           "height=%u layer_count=%u format=%u usage=%" PRIx64
-           " user_metadata_size=%zu",
-           buffer_id, width, height, layer_count, format, usage,
-           user_metadata_size);
-
-  // See if this channel is already attached to a buffer.
-  if (const auto channel = message.GetChannel<BufferHubChannel>()) {
-    ALOGE(
-        "BufferHubService::OnCreateDetachedBuffer: Buffer already created: "
-        "buffer=%d",
-        buffer_id);
-    return ErrorStatus(EALREADY);
-  }
-
-  std::unique_ptr<BufferChannel> channel =
-      BufferChannel::Create(this, buffer_id, width, height, layer_count, format,
-                            usage, user_metadata_size);
-  if (!channel) {
-    ALOGE(
-        "BufferHubService::OnCreateDetachedBuffer: Failed to allocate buffer, "
-        "buffer=%d.",
-        buffer_id);
-    return ErrorStatus(ENOMEM);
-  }
-
-  message.SetChannel(std::move(channel));
-  return {};
-}
-
 Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
     pdx::Message& message, const ProducerQueueConfig& producer_config,
     const UsagePolicy& usage_policy) {
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_channel.h b/services/vr/bufferhubd/include/private/dvr/buffer_channel.h
deleted file mode 100644
index 9888db6..0000000
--- a/services/vr/bufferhubd/include/private/dvr/buffer_channel.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
-#define ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
-
-#include <pdx/channel_handle.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/buffer_hub.h>
-#include <private/dvr/buffer_hub_defs.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-class BufferChannel : public BufferHubChannel {
- public:
-  ~BufferChannel() override;
-
-  template <typename... Args>
-  static std::unique_ptr<BufferChannel> Create(Args&&... args) {
-    auto buffer = std::unique_ptr<BufferChannel>(
-        new BufferChannel(std::forward<Args>(args)...));
-    return buffer->IsValid() ? std::move(buffer) : nullptr;
-  }
-
-  // Returns whether the object holds a valid graphic buffer.
-  bool IsValid() const {
-    return buffer_node_ != nullptr && buffer_node_->IsValid();
-  }
-
-  // Captures buffer info for use by BufferHubService::DumpState().
-  BufferInfo GetBufferInfo() const override;
-
-  bool HandleMessage(pdx::Message& message) override;
-  void HandleImpulse(pdx::Message& message) override;
-
- private:
-
-  // Allocates a new detached buffer.
-  BufferChannel(BufferHubService* service, int buffer_id, uint32_t width,
-                uint32_t height, uint32_t layer_count, uint32_t format,
-                uint64_t usage, size_t user_metadata_size);
-
-  // Creates a detached buffer from an existing BufferNode. This method is used
-  // in OnDuplicate method.
-  BufferChannel(BufferHubService* service, int buffer_id, int channel_id,
-                std::shared_ptr<BufferNode> buffer_node);
-
-  pdx::Status<BufferTraits<pdx::BorrowedHandle>> OnImport(
-      pdx::Message& message);
-  pdx::Status<pdx::RemoteChannelHandle> OnDuplicate(pdx::Message& message);
-
-  // The concrete implementation of the Buffer object.
-  std::shared_ptr<BufferNode> buffer_node_ = nullptr;
-
-  // The state bit of this buffer.
-  uint32_t client_state_mask_ = 0U;
-};
-
-}  // namespace dvr
-}  // namespace android
-
-#endif  // ANDROID_DVR_BUFFERHUBD_BUFFER_CHANNEL_H_
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
index 01520fc..909d69b 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
@@ -144,11 +144,6 @@
   pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width,
                                    uint32_t height, uint32_t format,
                                    uint64_t usage, size_t meta_size_bytes);
-  pdx::Status<void> OnCreateDetachedBuffer(pdx::Message& message,
-                                           uint32_t width, uint32_t height,
-                                           uint32_t layer_count,
-                                           uint32_t format, uint64_t usage,
-                                           size_t user_metadata_size);
   pdx::Status<QueueInfo> OnCreateProducerQueue(
       pdx::Message& message, const ProducerQueueConfig& producer_config,
       const UsagePolicy& usage_policy);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 409bce9..895dee0 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -7,7 +7,6 @@
 #include <thread>
 
 #include <log/log.h>
-#include <private/dvr/buffer_channel.h>
 #include <private/dvr/bufferhub_rpc.h>
 #include <private/dvr/consumer_channel.h>
 #include <private/dvr/producer_channel.h>
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 258b45b..d9df204 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -15,6 +15,7 @@
     "android.frameworks.vr.composer@1.0",
     "android.hardware.graphics.composer@2.1",
     "android.hardware.graphics.mapper@2.0",
+    "android.hardware.graphics.mapper@3.0",
     "libbase",
     "libbufferhubqueue",
     "libbinder",
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 009b257..ba4cf00 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -139,12 +139,12 @@
         auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
         if (app_namespace &&
             !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
-            std::string error_msg;
-            dlhandle_ = OpenNativeLibrary(
+            char* error_msg = nullptr;
+            dlhandle_ = OpenNativeLibraryInNamespace(
                 app_namespace, path_.c_str(), &native_bridge_, &error_msg);
             if (!dlhandle_) {
-                ALOGE("failed to load layer library '%s': %s", path_.c_str(),
-                      error_msg.c_str());
+                ALOGE("failed to load layer library '%s': %s", path_.c_str(), error_msg);
+                android::NativeLoaderFreeErrorMessage(error_msg);
                 refcount_ = 0;
                 return false;
             }
@@ -165,9 +165,10 @@
     std::lock_guard<std::mutex> lock(mutex_);
     if (--refcount_ == 0) {
         ALOGV("closing layer library '%s'", path_.c_str());
-        std::string error_msg;
+        char* error_msg = nullptr;
         if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
-            ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg.c_str());
+            ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg);
+            android::NativeLoaderFreeErrorMessage(error_msg);
             refcount_++;
         } else {
            dlhandle_ = nullptr;