Merge "libui: use uint64_t in dump and getTotalSize to avoid overflow issues"
diff --git a/Android.bp b/Android.bp
index bf4cf5d..9829c7f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,6 +7,7 @@
 }
 
 subdirs = [
+    "adbd_auth",
     "cmds/*",
     "headers",
     "libs/*",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4f7cdf3..36a53bb 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,6 +4,7 @@
 [Builtin Hooks Options]
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+               cmds/idlcli/
                include/input/
                libs/binder/ndk/
                libs/graphicsenv/
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..8173c89
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,63 @@
+{
+  "presubmit": [
+    {
+      "name": "SurfaceFlinger_test",
+      "options": [
+        {
+          "include-filter": "*CredentialsTest.*"
+        },
+        {
+          "include-filter": "*SurfaceFlingerStress.*"
+        },
+        {
+          "include-filter": "*SurfaceInterceptorTest.*"
+        },
+        {
+          "include-filter": "*LayerTransactionTest.*"
+        },
+        {
+          "include-filter": "*LayerTypeTransactionTest.*"
+        },
+        {
+          "include-filter": "*LayerUpdateTest.*"
+        },
+        {
+          "include-filter": "*GeometryLatchingTest.*"
+        },
+        {
+          "include-filter": "*CropLatchingTest.*"
+        },
+        {
+          "include-filter": "*ChildLayerTest.*"
+        },
+        {
+          "include-filter": "*ScreenCaptureTest.*"
+        },
+        {
+          "include-filter": "*ScreenCaptureChildOnlyTest.*"
+        },
+        {
+          "include-filter": "*DereferenceSurfaceControlTest.*"
+        },
+        {
+          "include-filter": "*BoundlessLayerTest.*"
+        },
+        {
+          "include-filter": "*MultiDisplayLayerBoundsTest.*"
+        },
+        {
+          "include-filter": "*InvalidHandleTest.*"
+        },
+        {
+          "include-filter": "*VirtualDisplayTest.*"
+        },
+        {
+          "include-filter": "*RelativeZTest.*"
+        }
+      ]
+    },
+    {
+      "name": "libsurfaceflinger_unittest"
+    }
+  ]
+}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 67f12e8..c5bfb42 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -154,6 +154,7 @@
 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
 #define WLUTIL "/vendor/xbin/wlutil"
 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
+#define OTA_METADATA_DIR "/metadata/ota"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -960,6 +961,7 @@
     }
 
     RunCommand("LPDUMP", {"lpdump", "--all"});
+    RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
 }
 
 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
@@ -1556,6 +1558,7 @@
     add_mountinfo();
     DumpIpTablesAsRoot();
     DumpDynamicPartitionInfo();
+    ds.AddDir(OTA_METADATA_DIR, true);
 
     // Capture any IPSec policies in play. No keys are exposed here.
     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index cf4e0b5..b9395ba 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -54,6 +54,7 @@
     MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
     MOCK_METHOD1(listServices, Vector<String16>(int));
     MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
+    MOCK_METHOD1(isDeclared, bool(const String16&));
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 40b8dc7..5476319 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -20,9 +20,11 @@
         "android.hardware.vibrator@1.2",
         "android.hardware.vibrator@1.3",
         "libbase",
+        "libbinder",
         "libhidlbase",
         "liblog",
         "libutils",
+        "vintf-vibrator-cpp",
     ],
     cflags: [
         "-DLOG_TAG=\"idlcli\"",
@@ -34,6 +36,10 @@
     defaults: ["idlcli-defaults"],
     srcs: [
         "CommandVibrator.cpp",
+        "vibrator/CommandCompose.cpp",
+        "vibrator/CommandGetCapabilities.cpp",
+        "vibrator/CommandGetCompositionDelayMax.cpp",
+        "vibrator/CommandGetCompositionSizeMax.cpp",
         "vibrator/CommandOff.cpp",
         "vibrator/CommandOn.cpp",
         "vibrator/CommandPerform.cpp",
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
index bcb207b..2f11923 100644
--- a/cmds/idlcli/vibrator.h
+++ b/cmds/idlcli/vibrator.h
@@ -18,6 +18,8 @@
 #define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
 
 #include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
 
 #include "utils.h"
 
@@ -31,9 +33,25 @@
 
 // Creates a Return<R> with STATUS::EX_NULL_POINTER.
 template <class R>
-inline Return<R> NullptrStatus() {
+inline R NullptrStatus() {
     using ::android::hardware::Status;
-    return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
+    return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template <>
+inline binder::Status NullptrStatus() {
+    using binder::Status;
+    return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+}
+
+template <typename I>
+inline sp<I> getService() {
+    return I::getService();
+}
+
+template <>
+inline sp<hardware::vibrator::IVibrator> getService() {
+    return waitForVintfService<hardware::vibrator::IVibrator>();
 }
 
 template <typename I>
@@ -42,12 +60,12 @@
     static std::unique_ptr<HalWrapper> Create() {
         // Assume that if getService returns a nullptr, HAL is not available on the
         // device.
-        auto hal = I::getService();
+        auto hal = getService<I>();
         return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
     }
 
     template <class R, class... Args0, class... Args1>
-    Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+    R call(R (I::*fn)(Args0...), Args1&&... args1) {
         return (*mHal.*fn)(std::forward<Args1>(args1)...);
     }
 
@@ -65,7 +83,7 @@
 }
 
 template <class R, class I, class... Args0, class... Args1>
-Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+R halCall(R (I::*fn)(Args0...), Args1&&... args1) {
     auto hal = getHal<I>();
     return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
 }
@@ -77,6 +95,7 @@
 namespace V1_1 = ::android::hardware::vibrator::V1_1;
 namespace V1_2 = ::android::hardware::vibrator::V1_2;
 namespace V1_3 = ::android::hardware::vibrator::V1_3;
+namespace aidl = ::android::hardware::vibrator;
 
 } // namespace vibrator
 } // namespace idlcli
diff --git a/cmds/idlcli/vibrator/CommandCompose.cpp b/cmds/idlcli/vibrator/CommandCompose.cpp
new file mode 100644
index 0000000..705e40b
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandCompose.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::CompositeEffect;
+
+class CommandCompose : public Command {
+    std::string getDescription() const override { return "Compose vibration."; }
+
+    std::string getUsageSummary() const override { return "<delay> <primitive> <scale> ..."; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{
+                {"<delay>", {"In milliseconds"}},
+                {"<primitive>", {"Primitive ID."}},
+                {"<scale>", {"0.0 (exclusive) - 1.0 (inclusive)."}},
+                {"...", {"May repeat multiple times."}},
+        };
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        while (!args.empty()) {
+            CompositeEffect effect;
+            if (auto delay = args.pop<decltype(effect.delayMs)>()) {
+                effect.delayMs = *delay;
+                std::cout << "Delay: " << effect.delayMs << std::endl;
+            } else {
+                std::cerr << "Missing or Invalid Delay!" << std::endl;
+                return USAGE;
+            }
+            // TODO: Use range validation when supported by AIDL
+            if (auto primitive = args.pop<std::underlying_type_t<decltype(effect.primitive)>>()) {
+                effect.primitive = static_cast<decltype(effect.primitive)>(*primitive);
+                std::cout << "Primitive: " << toString(effect.primitive) << std::endl;
+            } else {
+                std::cerr << "Missing or Invalid Primitive!" << std::endl;
+                return USAGE;
+            }
+            if (auto scale = args.pop<decltype(effect.scale)>();
+                scale && *scale > 0.0 && scale <= 1.0) {
+                effect.scale = *scale;
+                std::cout << "Scale: " << effect.scale << std::endl;
+            } else {
+                std::cerr << "Missing or Invalid Scale!" << std::endl;
+                return USAGE;
+            }
+            mComposite.emplace_back(std::move(effect));
+        }
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        Status ret;
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::compose, mComposite, nullptr);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+
+        return ret;
+    }
+
+    std::vector<CompositeEffect> mComposite;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandCompose>("compose");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetCapabilities.cpp b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
new file mode 100644
index 0000000..30d8587
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetCapabilities.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetCapabilities : public Command {
+    std::string getDescription() const override { return "Retrieves vibrator capabilities."; }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        int32_t cap;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getCapabilities, &cap);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Capabilities: " << std::bitset<32>(cap) << std::endl;
+
+        return ret;
+    }
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandGetCapabilities>("getCapabilities");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp b/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp
new file mode 100644
index 0000000..b414307
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetCompositionDelayMax.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetCompositionDelayMax : public Command {
+    std::string getDescription() const override {
+        return "Retrieves vibrator composition delay max.";
+    }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        int32_t maxDelayMs;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getCompositionDelayMax, &maxDelayMs);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Max Delay: " << maxDelayMs << " ms" << std::endl;
+
+        return ret;
+    }
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandGetCompositionDelayMax>(
+                "getCompositionDelayMax");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp b/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp
new file mode 100644
index 0000000..360fc9d
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetCompositionSizeMax.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetCompositionSizeMax : public Command {
+    std::string getDescription() const override {
+        return "Retrieves vibrator composition size max.";
+    }
+
+    std::string getUsageSummary() const override { return ""; }
+
+    UsageDetails getUsageDetails() const override {
+        UsageDetails details{};
+        return details;
+    }
+
+    Status doArgs(Args &args) override {
+        if (!args.empty()) {
+            std::cerr << "Unexpected Arguments!" << std::endl;
+            return USAGE;
+        }
+        return OK;
+    }
+
+    Status doMain(Args && /*args*/) override {
+        std::string statusStr;
+        int32_t maxSize;
+        Status ret;
+
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::getCompositionSizeMax, &maxSize);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else {
+            return UNAVAILABLE;
+        }
+
+        std::cout << "Status: " << statusStr << std::endl;
+        std::cout << "Max Size: " << maxSize << std::endl;
+
+        return ret;
+    }
+};
+
+static const auto Command =
+        CommandRegistry<CommandVibrator>::Register<CommandGetCompositionSizeMax>(
+                "getCompositionSizeMax");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
index a674f01..53fada0 100644
--- a/cmds/idlcli/vibrator/CommandOff.cpp
+++ b/cmds/idlcli/vibrator/CommandOff.cpp
@@ -42,15 +42,24 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::off);
+        std::string statusStr;
+        Status ret;
 
-        if (!ret.isOk()) {
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::off);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else if (auto hal = getHal<V1_0::IVibrator>()) {
+            auto status = hal->call(&V1_0::IVibrator::off);
+            statusStr = toString(status);
+            ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+        } else {
             return UNAVAILABLE;
         }
 
-        std::cout << "Status: " << toString(ret) << std::endl;
+        std::cout << "Status: " << statusStr << std::endl;
 
-        return ret == V1_0::Status::OK ? OK : ERROR;
+        return ret;
     }
 };
 
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
index 2164b7d..ccb3c19 100644
--- a/cmds/idlcli/vibrator/CommandOn.cpp
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -50,15 +50,24 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::on, mDuration);
+        std::string statusStr;
+        Status ret;
 
-        if (!ret.isOk()) {
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::on, mDuration, nullptr);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else if (auto hal = getHal<V1_0::IVibrator>()) {
+            auto status = hal->call(&V1_0::IVibrator::on, mDuration);
+            statusStr = toString(status);
+            ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+        } else {
             return UNAVAILABLE;
         }
 
-        std::cout << "Status: " << toString(ret) << std::endl;
+        std::cout << "Status: " << statusStr << std::endl;
 
-        return ret == V1_0::Status::OK ? OK : ERROR;
+        return ret;
     }
 
     uint32_t mDuration;
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
index 688cbd8..58d4e0a 100644
--- a/cmds/idlcli/vibrator/CommandPerform.cpp
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -23,6 +23,34 @@
 
 namespace vibrator {
 
+/*
+ * The following static asserts are only relevant here because the argument
+ * parser uses a single implementation for determining the string names.
+ */
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
+              static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
+              static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
+static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
+              static_cast<uint8_t>(aidl::EffectStrength::STRONG));
+static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
+              static_cast<uint8_t>(aidl::Effect::CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
+              static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD));
+static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP));
+static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
+              static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
+              static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
+              static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
+static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
+              static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
+static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
+              static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
+
 using V1_0::EffectStrength;
 using V1_3::Effect;
 
@@ -62,38 +90,50 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        Return<void> ret;
-        V1_0::Status status;
+        std::string statusStr;
         uint32_t lengthMs;
-        auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
-            status = retStatus;
-            lengthMs = retLengthMs;
-        };
+        Status ret;
 
-        if (auto hal = getHal<V1_3::IVibrator>()) {
-            ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_2::IVibrator>()) {
-            ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_1::IVibrator>()) {
-            ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
-                            mStrength, callback);
-        } else if (auto hal = getHal<V1_0::IVibrator>()) {
-            ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
-                            mStrength, callback);
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            int32_t aidlLengthMs;
+            auto status =
+                    hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
+                              static_cast<aidl::EffectStrength>(mStrength), nullptr, &aidlLengthMs);
+            statusStr = status.toString8();
+            lengthMs = static_cast<uint32_t>(aidlLengthMs);
+            ret = status.isOk() ? OK : ERROR;
         } else {
-            ret = NullptrStatus<void>();
+            Return<void> hidlRet;
+            V1_0::Status status;
+            auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
+                status = retStatus;
+                lengthMs = retLengthMs;
+            };
+
+            if (auto hal = getHal<V1_3::IVibrator>()) {
+                hidlRet = hal->call(&V1_3::IVibrator::perform_1_3,
+                                    static_cast<V1_3::Effect>(mEffect), mStrength, callback);
+            } else if (auto hal = getHal<V1_2::IVibrator>()) {
+                hidlRet = hal->call(&V1_2::IVibrator::perform_1_2,
+                                    static_cast<V1_2::Effect>(mEffect), mStrength, callback);
+            } else if (auto hal = getHal<V1_1::IVibrator>()) {
+                hidlRet = hal->call(&V1_1::IVibrator::perform_1_1,
+                                    static_cast<V1_1::Effect_1_1>(mEffect), mStrength, callback);
+            } else if (auto hal = getHal<V1_0::IVibrator>()) {
+                hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
+                                    mStrength, callback);
+            } else {
+                return UNAVAILABLE;
+            }
+
+            statusStr = toString(status);
+            ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
         }
 
-        if (!ret.isOk()) {
-            return UNAVAILABLE;
-        }
-
-        std::cout << "Status: " << toString(status) << std::endl;
+        std::cout << "Status: " << statusStr << std::endl;
         std::cout << "Length: " << lengthMs << std::endl;
 
-        return status == V1_0::Status::OK ? OK : ERROR;
+        return ret;
     }
 
     Effect mEffect;
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
index 38a1dc2..33d7eed 100644
--- a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
+++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
@@ -50,15 +50,25 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
+        std::string statusStr;
+        Status ret;
 
-        if (!ret.isOk()) {
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::setAmplitude,
+                                    static_cast<float>(mAmplitude) / UINT8_MAX);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else if (auto hal = getHal<V1_0::IVibrator>()) {
+            auto status = hal->call(&V1_0::IVibrator::setAmplitude, mAmplitude);
+            statusStr = toString(status);
+            ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+        } else {
             return UNAVAILABLE;
         }
 
-        std::cout << "Status: " << toString(ret) << std::endl;
+        std::cout << "Status: " << statusStr << std::endl;
 
-        return ret == V1_0::Status::OK ? OK : ERROR;
+        return ret;
     }
 
     uint8_t mAmplitude;
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
index 5fb1fac..5bc827e 100644
--- a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
+++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
@@ -48,15 +48,24 @@
     }
 
     Status doMain(Args && /*args*/) override {
-        auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
+        std::string statusStr;
+        Status ret;
 
-        if (!ret.isOk()) {
+        if (auto hal = getHal<aidl::IVibrator>()) {
+            auto status = hal->call(&aidl::IVibrator::setExternalControl, mEnable);
+            statusStr = status.toString8();
+            ret = status.isOk() ? OK : ERROR;
+        } else if (auto hal = getHal<V1_3::IVibrator>()) {
+            auto status = hal->call(&V1_3::IVibrator::setExternalControl, mEnable);
+            statusStr = toString(status);
+            ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR;
+        } else {
             return UNAVAILABLE;
         }
 
-        std::cout << "Status: " << toString(ret) << std::endl;
+        std::cout << "Status: " << statusStr << std::endl;
 
-        return ret == V1_0::Status::OK ? OK : ERROR;
+        return ret;
     }
 
     bool mEnable;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4026f29..b23d69c 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -101,6 +101,7 @@
 static constexpr int kVerityPageSize = 4096;
 static constexpr size_t kSha256Size = 32;
 static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";
+static constexpr const char* kFuseProp = "persist.sys.fuse";
 
 namespace {
 
@@ -592,12 +593,21 @@
         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
         for (const auto& n : mStorageMounts) {
             auto extPath = n.second;
-            if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
-                extPath += StringPrintf("/%d", userId);
-            } else if (userId != 0) {
-                // TODO: support devices mounted under secondary users
-                continue;
+
+            if (android::base::GetBoolProperty(kFuseProp, false)) {
+                std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
+                if (std::regex_match(extPath, re)) {
+                    extPath += "/" + std::to_string(userId);
+                }
+            } else {
+                if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
+                    extPath += StringPrintf("/%d", userId);
+                } else if (userId != 0) {
+                    // TODO: support devices mounted under secondary users
+                    continue;
+                }
             }
+
             if (flags & FLAG_CLEAR_CACHE_ONLY) {
                 // Clear only cached data from shared storage
                 auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
@@ -688,16 +698,26 @@
         std::lock_guard<std::recursive_mutex> lock(mMountsLock);
         for (const auto& n : mStorageMounts) {
             auto extPath = n.second;
-            if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
-                extPath += StringPrintf("/%d", userId);
-            } else if (userId != 0) {
-                // TODO: support devices mounted under secondary users
-                continue;
+
+            if (android::base::GetBoolProperty(kFuseProp, false)) {
+                std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
+                if (std::regex_match(extPath, re)) {
+                    extPath += "/" + std::to_string(userId);
+                }
+            } else {
+                if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
+                    extPath += StringPrintf("/%d", userId);
+                } else if (userId != 0) {
+                    // TODO: support devices mounted under secondary users
+                    continue;
+                }
             }
+
             auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
             if (delete_dir_contents_and_dir(path, true) != 0) {
                 res = error("Failed to delete contents of " + path);
             }
+
             path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
             if (delete_dir_contents_and_dir(path, true) != 0) {
                 res = error("Failed to delete contents of " + path);
@@ -2778,12 +2798,19 @@
         std::getline(in, target, ' ');
         std::getline(in, ignored);
 
+        if (android::base::GetBoolProperty(kFuseProp, false)) {
+            if (target.compare(0, 17, "/mnt/pass_through") == 0) {
+                LOG(DEBUG) << "Found storage mount " << source << " at " << target;
+                mStorageMounts[source] = target;
+            }
+        } else {
 #if !BYPASS_SDCARDFS
-        if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
-            LOG(DEBUG) << "Found storage mount " << source << " at " << target;
-            mStorageMounts[source] = target;
-        }
+            if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
+                LOG(DEBUG) << "Found storage mount " << source << " at " << target;
+                mStorageMounts[source] = target;
+            }
 #endif
+        }
     }
     return ok();
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 838d11d..f95e445 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -339,6 +339,10 @@
                 ? "dalvik.vm.dex2oat-threads"
                 : "dalvik.vm.boot-dex2oat-threads";
         std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
+        const char* cpu_set_property = post_bootcomplete
+                ? "dalvik.vm.dex2oat-cpu-set"
+                : "dalvik.vm.boot-dex2oat-cpu-set";
+        std::string dex2oat_cpu_set_arg = MapPropertyToArg(cpu_set_property, "--cpu-set=%s");
 
         std::string bootclasspath;
         char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
@@ -518,6 +522,7 @@
         AddArg(image_block_size_arg);
         AddArg(dex2oat_compiler_filter_arg);
         AddArg(dex2oat_threads_arg);
+        AddArg(dex2oat_cpu_set_arg);
         AddArg(dex2oat_swap_fd);
         AddArg(dex2oat_image_fd);
 
@@ -708,11 +713,13 @@
     }
 }
 
-static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
-static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
-static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
-static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
-static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
+static constexpr int PROFMAN_BIN_RETURN_CODE_SUCCESS = 0;
+static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 1;
+static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 2;
+static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 3;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 4;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 5;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS = 6;
 
 class RunProfman : public ExecVHelper {
   public:
@@ -720,7 +727,9 @@
                   const unique_fd& reference_profile_fd,
                   const std::vector<unique_fd>& apk_fds,
                   const std::vector<std::string>& dex_locations,
-                  bool copy_and_update) {
+                  bool copy_and_update,
+                  bool for_snapshot,
+                  bool for_boot_image) {
 
         // TODO(calin): Assume for now we run in the bg compile job (which is in
         // most of the invocation). With the current data flow, is not very easy or
@@ -752,6 +761,14 @@
             AddArg("--copy-and-update-profile-key");
         }
 
+        if (for_snapshot) {
+            AddArg("--force-merge");
+        }
+
+        if (for_boot_image) {
+            AddArg("--boot-image-merge");
+        }
+
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
@@ -759,12 +776,16 @@
     void SetupMerge(const std::vector<unique_fd>& profiles_fd,
                     const unique_fd& reference_profile_fd,
                     const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
-                    const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
+                    const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+                    bool for_snapshot = false,
+                    bool for_boot_image = false) {
         SetupArgs(profiles_fd,
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false);
+                  /*copy_and_update=*/ false,
+                  for_snapshot,
+                  for_boot_image);
     }
 
     void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -781,7 +802,9 @@
                   reference_profile_fd_,
                   apk_fds_,
                   dex_locations,
-                  /*copy_and_update=*/true);
+                  /*copy_and_update=*/true,
+                  /*for_snapshot*/false,
+                  /*for_boot_image*/false);
     }
 
     void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -795,7 +818,9 @@
                   reference_profile_fd,
                   apk_fds,
                   dex_locations,
-                  /*copy_and_update=*/false);
+                  /*copy_and_update=*/false,
+                  /*for_snapshot*/false,
+                  /*for_boot_image*/false);
     }
 
     void Exec() {
@@ -870,9 +895,14 @@
                 should_clear_current_profiles = false;
                 should_clear_reference_profile = false;
                 break;
+            case PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS:
+                need_to_compile = false;
+                should_clear_current_profiles = true;
+                should_clear_reference_profile = true;
+                break;
            default:
                 // Unknown return code or error. Unlink profiles.
-                LOG(WARNING) << "Unknown error code while processing profiles for location "
+                LOG(WARNING) << "Unexpected error code while processing profiles for location "
                         << location << ": " << return_code;
                 need_to_compile = false;
                 should_clear_current_profiles = true;
@@ -2741,7 +2771,7 @@
     }
 
     RunProfman args;
-    args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations);
+    args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations, /*for_snapshot=*/true);
     pid_t pid = fork();
     if (pid == 0) {
         /* child -- drop privileges before continuing */
@@ -2756,6 +2786,13 @@
         return false;
     }
 
+    // Verify that profman finished successfully.
+    int profman_code = WEXITSTATUS(return_code);
+    if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
+        LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
+                << ":" << profman_code;
+        return false;
+    }
     return true;
 }
 
@@ -2818,19 +2855,29 @@
     // We do this to avoid opening a huge a amount of files.
     static constexpr size_t kAggregationBatchSize = 10;
 
-    std::vector<unique_fd> profiles_fd;
     for (size_t i = 0; i < profiles.size(); )  {
+        std::vector<unique_fd> profiles_fd;
         for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
             unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
             if (fd.get() >= 0) {
                 profiles_fd.push_back(std::move(fd));
             }
         }
+
+        // We aggregate (read & write) into the same fd multiple times in a row.
+        // We need to reset the cursor every time to ensure we read the whole file every time.
+        if (TEMP_FAILURE_RETRY(lseek(snapshot_fd, 0, SEEK_SET)) == static_cast<off_t>(-1)) {
+            PLOG(ERROR) << "Cannot reset position for snapshot profile";
+            return false;
+        }
+
         RunProfman args;
         args.SetupMerge(profiles_fd,
                         snapshot_fd,
                         apk_fds,
-                        dex_locations);
+                        dex_locations,
+                        /*for_snapshot=*/true,
+                        /*for_boot_image=*/true);
         pid_t pid = fork();
         if (pid == 0) {
             /* child -- drop privileges before continuing */
@@ -2843,12 +2890,21 @@
 
         /* parent */
         int return_code = wait_child(pid);
+
         if (!WIFEXITED(return_code)) {
             PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
             return false;
         }
-        return true;
+
+        // Verify that profman finished successfully.
+        int profman_code = WEXITSTATUS(return_code);
+        if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
+            LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
+                    << ":" << profman_code;
+            return false;
+        }
     }
+
     return true;
 }
 
diff --git a/cmds/installd/migrate_legacy_obb_data.sh b/cmds/installd/migrate_legacy_obb_data.sh
index 1075688..7399681 100644
--- a/cmds/installd/migrate_legacy_obb_data.sh
+++ b/cmds/installd/migrate_legacy_obb_data.sh
@@ -15,17 +15,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-rm -rf /sdcard/Android/obb/test_probe
-mkdir -p /sdcard/Android/obb/
-touch /sdcard/Android/obb/test_probe
+rm -rf /data/media/0/Android/obb/test_probe
+mkdir -p /data/media/0/Android/obb/
+touch /data/media/0/Android/obb/test_probe
 if ! test -f /data/media/0/Android/obb/test_probe ; then
   log -p i -t migrate_legacy_obb_data "No support for 'unshared_obb'. Not migrating"
-  rm -rf /sdcard/Android/obb/test_probe
+  rm -rf /data/media/0/Android/obb/test_probe
   exit 0
 fi
 
 # Delete the test file, and remove the obb folder if it is empty
-rm -rf /sdcard/Android/obb/test_probe
+rm -rf /data/media/0/Android/obb/test_probe
 rmdir /data/media/obb
 
 if ! test -d /data/media/obb ; then
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index db36ce3..eefbe4f 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -480,6 +480,10 @@
                 "-j",
                 false,
                 cmd);
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-cpu-set",
+                "--cpu-set=",
+                false,
+                cmd);
         AddCompilerOptionFromSystemProperty(
                 StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
                 "--instruction-set-variant=",
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 0212bc5..69fefa1 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -897,7 +897,9 @@
         std::string expected_profile_content = snap_profile_ + ".expected";
         run_cmd("rm -f " + expected_profile_content);
         run_cmd("touch " + expected_profile_content);
-        run_cmd("profman --profile-file=" + cur_profile_ +
+        // We force merging when creating the expected profile to make sure
+        // that the random profiles do not affect the output.
+        run_cmd("profman --force-merge --profile-file=" + cur_profile_ +
                 " --profile-file=" + ref_profile_ +
                 " --reference-profile-file=" + expected_profile_content +
                 " --apk=" + apk_path_);
@@ -1130,16 +1132,60 @@
 
 class BootProfileTest : public ProfileTest {
   public:
-    virtual void setup() {
+    std::vector<const std::string> extra_apps_;
+    std::vector<int64_t> extra_ce_data_inodes_;
+
+    virtual void SetUp() {
+
         ProfileTest::SetUp();
         intial_android_profiles_dir = android_profiles_dir;
+        // Generate profiles for some extra apps.
+        // When merging boot profile we split profiles into small groups to avoid
+        // opening a lot of file descriptors at the same time.
+        // (Currently the group size for aggregation is 10)
+        //
+        // To stress test that works fine, create profile for more apps.
+        createAppProfilesForBootMerge(21);
     }
 
     virtual void TearDown() {
         android_profiles_dir = intial_android_profiles_dir;
+        deleteAppProfilesForBootMerge();
         ProfileTest::TearDown();
     }
 
+    void createAppProfilesForBootMerge(size_t number_of_profiles) {
+        for (size_t i = 0; i < number_of_profiles; i++) {
+            int64_t ce_data_inode;
+            std::string package_name = "dummy_test_pkg" + std::to_string(i);
+            LOG(INFO) << package_name;
+            ASSERT_BINDER_SUCCESS(service_->createAppData(
+                    volume_uuid_,
+                    package_name,
+                    kTestUserId,
+                    kAppDataFlags,
+                    kTestAppUid,
+                    se_info_,
+                    kOSdkVersion,
+                    &ce_data_inode));
+            extra_apps_.push_back(package_name);
+            extra_ce_data_inodes_.push_back(ce_data_inode);
+            std::string profile = create_current_profile_path(
+                    kTestUserId, package_name, kPrimaryProfile, /*is_secondary_dex*/ false);
+            SetupProfile(profile, kTestAppUid, kTestAppGid, 0600, 1);
+        }
+    }
+
+    void deleteAppProfilesForBootMerge() {
+        if (kDebug) {
+            return;
+        }
+        for (size_t i = 0; i < extra_apps_.size(); i++) {
+            service_->destroyAppData(
+                volume_uuid_, extra_apps_[i], kTestUserId, kAppDataFlags, extra_ce_data_inodes_[i]);
+        }
+    }
+
     void UpdateAndroidProfilesDir(const std::string& profile_dir) {
         android_profiles_dir = profile_dir;
         // We need to create the reference profile directory in the new profile dir.
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 9344368..141171b 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -34,11 +34,7 @@
 namespace android {
 
 #ifndef VENDORSERVICEMANAGER
-static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
-    if (!Stability::requiresVintfDeclaration(binder)) {
-        return true;
-    }
-
+static bool isVintfDeclared(const std::string& name) {
     size_t firstSlash = name.find('/');
     size_t lastDot = name.rfind('.', firstSlash);
     if (firstSlash == std::string::npos || lastDot == std::string::npos) {
@@ -54,7 +50,7 @@
             vintf::VintfObject::GetDeviceHalManifest(),
             vintf::VintfObject::GetFrameworkHalManifest()
         }) {
-        if (manifest->hasAidlInstance(package, iface, instance)) {
+        if (manifest != nullptr && manifest->hasAidlInstance(package, iface, instance)) {
             return true;
         }
     }
@@ -62,9 +58,25 @@
                << " in the VINTF manifest.";
     return false;
 }
+
+static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) {
+    if (!Stability::requiresVintfDeclaration(binder)) {
+        return true;
+    }
+
+    return isVintfDeclared(name);
+}
 #endif  // !VENDORSERVICEMANAGER
 
-ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
+ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {
+#ifndef VENDORSERVICEMANAGER
+    // can process these at any times, don't want to delay first VINTF client
+    std::thread([] {
+        vintf::VintfObject::GetDeviceHalManifest();
+        vintf::VintfObject::GetFrameworkHalManifest();
+    }).detach();
+#endif  // !VENDORSERVICEMANAGER
+}
 ServiceManager::~ServiceManager() {
     // this should only happen in tests
 
@@ -165,7 +177,7 @@
 #endif  // !VENDORSERVICEMANAGER
 
     // implicitly unlinked when the binder is removed
-    if (OK != binder->linkToDeath(this)) {
+    if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
         LOG(ERROR) << "Could not linkToDeath when adding " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -270,6 +282,21 @@
     return Status::ok();
 }
 
+Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {
+    auto ctx = mAccess->getCallingContext();
+
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    *outReturn = false;
+
+#ifndef VENDORSERVICEMANAGER
+    *outReturn = isVintfDeclared(name);
+#endif
+    return Status::ok();
+}
+
 void ServiceManager::removeCallback(const wp<IBinder>& who,
                                     CallbackMap::iterator* it,
                                     bool* found) {
@@ -287,7 +314,7 @@
     if (listeners.empty()) {
         *it = mNameToCallback.erase(*it);
     } else {
-        it++;
+        (*it)++;
     }
 }
 
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 006e519..7dcdaa4 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -40,6 +40,7 @@
                                             const sp<IServiceCallback>& callback) override;
     binder::Status unregisterForNotifications(const std::string& name,
                                               const sp<IServiceCallback>& callback) override;
+    binder::Status isDeclared(const std::string& name, bool* outReturn) override;
 
     void binderDied(const wp<IBinder>& who) override;
 
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index 11d43a6..4b12fc6 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -23,11 +23,12 @@
 #include "Access.h"
 #include "ServiceManager.h"
 
-using ::android::sp;
-using ::android::ProcessState;
-using ::android::IPCThreadState;
-using ::android::ServiceManager;
 using ::android::Access;
+using ::android::IPCThreadState;
+using ::android::ProcessState;
+using ::android::ServiceManager;
+using ::android::os::IServiceManager;
+using ::android::sp;
 
 int main(int argc, char** argv) {
     if (argc > 2) {
@@ -41,6 +42,10 @@
     ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
 
     sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
+    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
+        LOG(ERROR) << "Could not self register servicemanager";
+    }
+
     IPCThreadState::self()->setTheContextObject(manager);
     ps->becomeContextManager(nullptr, nullptr);
 
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index ad7791e..50f117d 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -40,7 +40,6 @@
     <feature name="android.software.voice_recognizers" notLowRam="true" />
     <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
-    <feature name="android.software.print" />
     <feature name="android.software.companion_device_setup" />
     <feature name="android.software.autofill" />
     <feature name="android.software.cant_save_state" />
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index c87ee56..8cc9d36 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -56,6 +56,11 @@
         size_t size,
         const CasSessionId *sessionId);
 
+typedef void (*CasPluginStatusCallback)(
+        void *appData,
+        int32_t event,
+        int32_t arg);
+
 struct CasFactory {
     CasFactory() {}
     virtual ~CasFactory() {}
@@ -91,6 +96,10 @@
     CasPlugin() {}
     virtual ~CasPlugin() {}
 
+    // Provide a callback to report plugin status
+    virtual status_t setStatusCallback(
+            CasPluginStatusCallback callback) = 0;
+
     // Provide the CA private data from a CA_descriptor in the conditional
     // access table to a CasPlugin.
     virtual status_t setPrivateData(
@@ -100,6 +109,11 @@
     // streams.
     virtual status_t openSession(CasSessionId *sessionId) = 0;
 
+    // Open a session with intend and mode for descrambling a program, or one
+    // or more elementary streams.
+    virtual status_t openSession(uint32_t intent, uint32_t mode,
+                                     CasSessionId *sessionId) = 0;
+
     // Close a previously opened session.
     virtual status_t closeSession(const CasSessionId &sessionId) = 0;
 
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index b6edaa9..81ee5fb 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -90,6 +90,7 @@
     OMX_VIDEO_CodingHEVC,       /**< ITU H.265/HEVC */
     OMX_VIDEO_CodingDolbyVision,/**< Dolby Vision */
     OMX_VIDEO_CodingImageHEIC,  /**< HEIF image encoded with HEVC */
+    OMX_VIDEO_CodingAV1,        /**< AV1 */
     OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_VIDEO_CodingMax = 0x7FFFFFFF
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 44883cc..346861f 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -59,6 +59,8 @@
 /**
  * Get the AChoreographer instance for the current thread. This must be called
  * on an ALooper thread.
+ *
+ * Available since API level 24.
  */
 AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
 
@@ -82,6 +84,8 @@
 /**
  * Power a callback to be run on the next frame.  The data pointer provided will
  * be passed to the callback function when it's called.
+ *
+ * Available since API level 29.
  */
 void AChoreographer_postFrameCallback64(AChoreographer* chroreographer,
                 AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29);
@@ -90,6 +94,8 @@
  * Post a callback to be run on the frame following the specified delay.  The
  * data pointer provided will be passed to the callback function when it's
  * called.
+ *
+ * Available since API level 29.
  */
 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
                 AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29);
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ef6c5a2..3310722 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -675,50 +675,52 @@
  */
 void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
 
-#if __ANDROID_API__ >= 13
 /**
  * Return the current configuration screen width in dp units, or
  * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
 
 /**
  * Return the current configuration screen height in dp units, or
  * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
 
 /**
  * Return the configuration's smallest screen width in dp units, or
  * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
 
 /**
  * Set the configuration's smallest screen width in dp units.
  */
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
-#endif /* __ANDROID_API__ >= 13 */
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
 
 #if __ANDROID_API__ >= 17
 /**
  * Return the configuration's layout direction, or
  * ACONFIGURATION_LAYOUTDIR_ANY if not set.
+ *
+ * Available since API level 17.
  */
 int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
 
 /**
  * Set the configuration's layout direction.
+ *
+ * Available since API level 17.
  */
 void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
 #endif /* __ANDROID_API__ >= 17 */
diff --git a/include/android/font.h b/include/android/font.h
index 8001ee1..1618096 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -96,6 +96,8 @@
 /**
  * Close an AFont.
  *
+ * Available since API level 29.
+ *
  * \param font a font returned by ASystemFontIterator_next or AFontMatchert_match.
  *        Do nothing if NULL is passed.
  */
@@ -116,6 +118,8 @@
  * The font file returned is guaranteed to be opend with O_RDONLY.
  * Note that the returned pointer is valid until AFont_close() is called for the given font.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return a string of the font file path.
  */
@@ -184,6 +188,8 @@
  *
  * For more information about font weight, read [OpenType usWeightClass](https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass)
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
  */
@@ -192,6 +198,8 @@
 /**
  * Return true if the current font is italic, otherwise returns false.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return true if italic, otherwise false.
  */
@@ -204,6 +212,8 @@
  *
  * Note that the returned pointer is valid until AFont_close() is called.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return a IETF BCP47 compliant language tag or nullptr if not available.
  */
@@ -216,6 +226,8 @@
  * returns a non-negative value as an font offset in the collection. This
  * always returns 0 if the target font file is a regular font.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return a font collection index.
  */
@@ -247,6 +259,8 @@
  *
  * For more information about font variation settings, read [Font Variations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar)
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \return a number of font variation settings.
  */
@@ -258,6 +272,8 @@
  *
  * See AFont_getAxisCount for more details.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
  *        equal to {@link AFont_getAxisCount} is not allowed.
@@ -271,6 +287,8 @@
  *
  * See AFont_getAxisCount for more details.
  *
+ * Available since API level 29.
+ *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
  *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index 0b8f892..d4bd892 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -130,13 +130,17 @@
  */
 
 /**
- * Creates a new AFontMatcher object
+ * Creates a new AFontMatcher object.
+ *
+ * Available since API level 29.
  */
 AFontMatcher* _Nonnull AFontMatcher_create() __INTRODUCED_IN(29);
 
 /**
  * Destroy the matcher object.
  *
+ * Available since API level 29.
+ *
  * \param matcher a matcher object. Passing NULL is not allowed.
  */
 void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29);
@@ -147,6 +151,8 @@
  * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
  * with non-italic style.
  *
+ * Available since API level 29.
+ *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param weight a font weight value. Only from 0 to 1000 value is valid
  * \param italic true if italic, otherwise false.
@@ -161,6 +167,8 @@
  *
  * If this function is not called, the matcher performs with empty locale list.
  *
+ * Available since API level 29.
+ *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param languageTags a null character terminated comma separated IETF BCP47 compliant language
  *                     tags.
@@ -174,6 +182,8 @@
  *
  * If this function is not called, the matcher performs with {@link AFAMILY_VARIANT_DEFAULT}.
  *
+ * Available since API level 29.
+ *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param familyVariant Must be one of {@link AFAMILY_VARIANT_DEFAULT},
  *                      {@link AFAMILY_VARIANT_COMPACT} or {@link AFAMILY_VARIANT_ELEGANT} is valid.
@@ -190,6 +200,8 @@
  * Even if no font can render the given text, this function will return a non-null result for
  * drawing Tofu character.
  *
+ * Available since API level 29.
+ *
  * \param matcher a matcher object. Passing NULL is not allowed.
  * \param familyName a null character terminated font family name
  * \param text a UTF-16 encoded text buffer to be rendered. Do not pass empty string.
diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h
index aedf369..293e5ac 100644
--- a/include/android/hardware_buffer_jni.h
+++ b/include/android/hardware_buffer_jni.h
@@ -42,6 +42,8 @@
  * that is returned. To keep the AHardwareBuffer live after the Java
  * HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire()
  * to acquire an additional reference.
+ *
+ * Available since API level 26.
  */
 AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
         jobject hardwareBufferObj) __INTRODUCED_IN(26);
@@ -49,6 +51,8 @@
 /**
  * Return a new Java HardwareBuffer object that wraps the passed native
  * AHardwareBuffer object.
+ *
+ * Available since API level 26.
  */
 jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
         AHardwareBuffer* hardwareBuffer) __INTRODUCED_IN(26);
diff --git a/include/android/input.h b/include/android/input.h
index cfade6c..ce439c6 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -986,10 +986,8 @@
  */
 int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
 
-#if __ANDROID_API__ >= 14
 /** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
-#endif
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
 
 /**
  * Get a bitfield indicating which edges, if any, were touched by this motion event.
@@ -1054,14 +1052,12 @@
  */
 int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
 
-#if __ANDROID_API__ >= 14
 /**
  * Get the tool type of a pointer for the given pointer index.
  * The tool type indicates the type of tool used to make contact such as a
  * finger or stylus, if known.
  */
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
-#endif
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
 
 /**
  * Get the original raw X coordinate of this event.
@@ -1151,11 +1147,9 @@
  */
 float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
 
-#if __ANDROID_API__ >= 13
 /** Get the value of the request axis for the given pointer index. */
 float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
-#endif
+        int32_t axis, size_t pointer_index);
 
 /**
  * Get the number of historical points in this event.  These are movements that
@@ -1286,14 +1280,12 @@
 float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
         size_t history_index);
 
-#if __ANDROID_API__ >= 13
 /**
  * Get the historical value of the request axis for the given pointer index
  * that occurred between this event and the previous motion event.
  */
 float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
-#endif
+        int32_t axis, size_t pointer_index, size_t history_index);
 
 
 struct AInputQueue;
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index d31d1f1..59b1deb 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -69,6 +69,7 @@
  *
  * This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
  *
+ * Available since API level 23.
  */
 int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
 
@@ -86,6 +87,7 @@
  *
  * This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
  *
+ * Available since API level 23.
  */
 int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
 
@@ -103,6 +105,7 @@
  *
  * This is the equivalent of: [android.net.Network#getAllByName()](https://developer.android.com/reference/android/net/Network.html#getAllByName(java.lang.String))
  *
+ * Available since API level 23.
  */
 int android_getaddrinfofornetwork(net_handle_t network,
         const char *node, const char *service,
@@ -144,6 +147,8 @@
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
+ *
+ * Available since API level 29.
  */
 int android_res_nquery(net_handle_t network,
         const char *dname, int ns_class, int ns_type, uint32_t flags) __INTRODUCED_IN(29);
@@ -155,6 +160,8 @@
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
+ *
+ * Available since API level 29.
  */
 int android_res_nsend(net_handle_t network,
         const uint8_t *msg, size_t msglen, uint32_t flags) __INTRODUCED_IN(29);
@@ -163,6 +170,8 @@
  * Read a result for the query associated with the |fd| descriptor.
  * Closes |fd| before returning.
  *
+ * Available since 29.
+ *
  * Returns:
  *     < 0: negative POSIX error code (see errno.h for possible values). |rcode| is not set.
  *     >= 0: length of |answer|. |rcode| is the resolver return code (e.g., ns_r_nxdomain)
@@ -173,6 +182,8 @@
 /**
  * Attempts to cancel the in-progress query associated with the |nsend_fd|
  * descriptor.
+ *
+ * Available since API level 29.
  */
 void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
 
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 0c196b9..3a77ffe 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -51,6 +51,8 @@
  * the ANativeWindow; maintains it through general Java object's life cycle;
  * and will automatically release the reference when the Java object gets garbage
  * collected.
+ *
+ * Available since API level 26.
  */
 jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
 #endif
diff --git a/include/android/sensor.h b/include/android/sensor.h
index e9d5c16..3ebe79f 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -564,6 +564,7 @@
  *
  *     ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
  *
+ * Available since API level 26.
  */
 ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
 #endif
@@ -583,6 +584,8 @@
 /**
  * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
  * of this type and wakeUp properties exists.
+ *
+ * Available since API level 21.
  */
 ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
 #endif
@@ -609,6 +612,8 @@
  * Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY} to be used
  * for configuring sensor direct report.
  *
+ * Available since API level 26.
+ *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param fd      file descriptor representing a shared memory created by
@@ -627,6 +632,8 @@
  * Create a direct channel of {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER} type to be used
  * for configuring sensor direct report.
  *
+ * Available since API level 26.
+ *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param buffer  {@link AHardwareBuffer} instance created by {@link AHardwareBuffer_allocate}.
@@ -646,6 +653,8 @@
  * The buffer used for creating direct channel does not get destroyed with
  * {@link ASensorManager_destroy} and has to be close or released separately.
  *
+ * Available since API level 26.
+ *
  * \param manager the {@link ASensorManager} instance obtained from
  *                {@link ASensorManager_getInstanceForPackage}.
  * \param channelId channel id (a positive integer) returned from
@@ -678,6 +687,8 @@
  *
  *     ASensorManager_configureDirectReport(manager, sensor, channel_id, ASENSOR_DIRECT_RATE_FAST);
  *
+ * Available since API level 26.
+ *
  * \param manager   the {@link ASensorManager} instance obtained from
  *                  {@link ASensorManager_getInstanceForPackage}.
  * \param sensor    a {@link ASensor} to denote which sensor to be operate. It can be NULL if rate
@@ -780,7 +791,7 @@
  */
 ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
 
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 /**
  * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
  * the given {@link ASensorEventQueue}.
@@ -796,13 +807,15 @@
  * {@link AAdditionalInfoEvent#type}, as new values may be defined in the future
  * and may delivered to the client.
  *
+ * Available since API level 29.
+ *
  * \param queue {@link ASensorEventQueue} to configure
  * \param enable true to request {@link ASENSOR_TYPE_ADDITIONAL_INFO} events,
  *        false to stop receiving events
  * \return 0 on success or a negative error code on failure
  */
-int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable);
-#endif /* __ANDROID_API__ >= __ANDRDOID_API_Q__ */
+int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
+#endif /* __ANDROID_API__ >= 29 */
 
 /*****************************************************************************/
 
@@ -837,26 +850,36 @@
 /**
  * Returns the maximum size of batches for this sensor. Batches will often be
  * smaller, as the hardware fifo might be used for other sensors.
+ *
+ * Available since API level 21.
  */
 int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the hardware batch fifo size reserved to this sensor.
+ *
+ * Available since API level 21.
  */
 int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns this sensor's string type.
+ *
+ * Available since API level 21.
  */
 const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
+ *
+ * Available since API level 21.
  */
 int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns true if this is a wake up sensor, false otherwise.
+ *
+ * Available since API level 21.
  */
 bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
 #endif /* __ANDROID_API__ >= 21 */
@@ -865,6 +888,8 @@
 /**
  * Test if sensor supports a certain type of direct channel.
  *
+ * Available since API level 26.
+ *
  * \param sensor  a {@link ASensor} to denote the sensor to be checked.
  * \param channelType  Channel type constant, either
  *                     {@ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY}
@@ -874,7 +899,9 @@
 bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
 
 /**
- * Get the highest direct rate level that a sensor support.
+ * Get the highest direct rate level that a sensor supports.
+ *
+ * Available since API level 26.
  *
  * \param sensor  a {@link ASensor} to denote the sensor to be checked.
  *
@@ -885,7 +912,7 @@
 int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
 #endif /* __ANDROID_API__ >= 26 */
 
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 /**
  * Returns the sensor's handle.
  *
@@ -899,9 +926,11 @@
  * 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.
+ *
+ * Available since API level 29.
  */
-int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(__ANDROID_API_Q__);
-#endif /* __ANDROID_API__ >= ANDROID_API_Q__ */
+int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
+#endif /* __ANDROID_API__ >= 29 */
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 7f5177b..6efa4f7 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -21,7 +21,7 @@
 
 /**
  * @file sharedmem.h
- * @brief Shared memory buffers that can be shared across process.
+ * @brief Shared memory buffers that can be shared between processes.
  */
 
 #ifndef ANDROID_SHARED_MEMORY_H
@@ -61,11 +61,15 @@
  *
  * Use close() to release the shared memory region.
  *
+ * Use {@link android.os.ParcelFileDescriptor} to pass the file descriptor to
+ * another process. File descriptors may also be sent to other processes over a Unix domain
+ * socket with sendmsg and SCM_RIGHTS. See sendmsg(3) and cmsg(3) man pages for more information.
+ *
  * Available since API level 26.
  *
  * \param name an optional name.
  * \param size size of the shared memory region
- * \return file descriptor that denotes the shared memory; error code on failure.
+ * \return file descriptor that denotes the shared memory; -1 and sets errno on failure, or -EINVAL if the error is that size was 0.
  */
 int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
 
@@ -109,7 +113,7 @@
  * \param fd   file descriptor of the shared memory region.
  * \param prot any bitwise-or'ed combination of PROT_READ, PROT_WRITE, PROT_EXEC denoting
  *             updated access. Note access can only be removed, but not added back.
- * \return 0 for success, error code on failure.
+ * \return 0 for success, -1 and sets errno on failure.
  */
 int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
 
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index ef2ad99..90e5653 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -46,7 +46,7 @@
  */
 typedef struct ASurfaceControl ASurfaceControl;
 
-/*
+/**
  * Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
  * |debug_name| is a debug name associated with this surface. It can be used to
  * identify this surface in the SurfaceFlinger's layer tree. It must not be
@@ -54,10 +54,17 @@
  *
  * The caller takes ownership of the ASurfaceControl returned and must release it
  * using ASurfaceControl_release below.
+ *
+ * Available since API level 29.
  */
 ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
                                                   __INTRODUCED_IN(29);
 
+/**
+ * See ASurfaceControl_createFromWindow.
+ *
+ * Available since API level 29.
+ */
 ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
                                         __INTRODUCED_IN(29);
 
@@ -65,6 +72,8 @@
  * Releases the |surface_control| object. After releasing the ASurfaceControl the caller no longer
  * has ownership of the AsurfaceControl. The surface and it's children may remain on display as long
  * as their parent remains on display.
+ *
+ * Available since API level 29.
  */
 void ASurfaceControl_release(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
 
@@ -79,11 +88,15 @@
 /**
  * The caller takes ownership of the transaction and must release it using
  * ASurfaceControl_delete below.
+ *
+ * Available since API level 29.
  */
 ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
 
 /**
  * Destroys the |transaction| object.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
 
@@ -93,6 +106,8 @@
  * Note that the transaction is guaranteed to be applied atomically. The
  * transactions which are applied on the same thread are also guaranteed to be
  * applied in order.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
 
@@ -116,6 +131,8 @@
  *
  * THREADING
  * The transaction completed callback can be invoked on any thread.
+ *
+ * Available since API level 29.
  */
 typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactionStats* stats)
                                                __INTRODUCED_IN(29);
@@ -123,6 +140,8 @@
 /**
  * Returns the timestamp of when the frame was latched by the framework. Once a frame is
  * latched by the framework, it is presented at the following hardware vsync.
+ *
+ * Available since API level 29.
  */
 int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_transaction_stats)
                                               __INTRODUCED_IN(29);
@@ -131,6 +150,8 @@
  * Returns a sync fence that signals when the transaction has been presented.
  * The recipient of the callback takes ownership of the fence and is responsible for closing
  * it.
+ *
+ * Available since API level 29.
  */
 int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
                                                __INTRODUCED_IN(29);
@@ -141,6 +162,8 @@
  * When the client is done using the array, it must release it by calling
  * ASurfaceTransactionStats_releaseASurfaceControls.
  *
+ * Available since API level 29.
+ *
  * |outASurfaceControlsSize| returns the size of the ASurfaceControls array.
  */
 void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surface_transaction_stats,
@@ -150,6 +173,8 @@
 /**
  * Releases the array of ASurfaceControls that were returned by
  * ASurfaceTransactionStats_getASurfaceControls.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_controls)
                                                       __INTRODUCED_IN(29);
@@ -158,6 +183,8 @@
  * Returns the timestamp of when the CURRENT buffer was acquired. A buffer is considered
  * acquired when its acquire_fence_fd has signaled. A buffer cannot be latched or presented until
  * it is acquired. If no acquire_fence_fd was provided, this timestamp will be set to -1.
+ *
+ * Available since API level 29.
  */
 int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surface_transaction_stats,
                                                 ASurfaceControl* surface_control)
@@ -180,6 +207,8 @@
  *
  * The client must ensure that all pending refs on a buffer are released before attempting to reuse
  * this buffer, otherwise synchronization errors may occur.
+ *
+ * Available since API level 29.
  */
 int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
                                                 ASurfaceTransactionStats* surface_transaction_stats,
@@ -190,6 +219,8 @@
  * Sets the callback that will be invoked when the updates from this transaction
  * are presented. For details on the callback semantics and data, see the
  * comments on the ASurfaceTransaction_OnComplete declaration above.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
                                        ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
@@ -199,6 +230,8 @@
  * Any children of the* reparented |surface_control| will remain children of the |surface_control|.
  *
  * The |new_parent| can be null. Surface controls with a null parent do not appear on the display.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_reparent(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, ASurfaceControl* new_parent)
@@ -213,6 +246,8 @@
  * Updates the visibility of |surface_control|. If show is set to
  * ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
  * be hidden.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
                                        ASurfaceControl* surface_control, int8_t visibility)
@@ -224,6 +259,8 @@
  * the same z order is undefined.
  *
  * Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
                                    ASurfaceControl* surface_control, int32_t z_order)
@@ -236,6 +273,8 @@
  *
  * The frameworks takes ownership of the |acquire_fence_fd| passed and is responsible
  * for closing it.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
                                    ASurfaceControl* surface_control, AHardwareBuffer* buffer,
@@ -246,6 +285,8 @@
  * ASurfaceControl visible in transparent regions of the surface.  Colors |r|, |g|,
  * and |b| must be within the range that is valid for |dataspace|.  |dataspace| and |alpha|
  * will be the dataspace and alpha set for the background color layer.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
                                   ASurfaceControl* surface_control, float r, float g, float b,
@@ -264,6 +305,8 @@
  * |transform| the transform applied after the source rect is applied to the buffer. This parameter
  * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
  * enum.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
                                      ASurfaceControl* surface_control, const ARect& source,
@@ -281,6 +324,8 @@
  * Updates whether the content for the buffer associated with this surface is
  * completely opaque. If true, every pixel of content inside the buffer must be
  * opaque or visual errors can occur.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
                                                ASurfaceControl* surface_control,
@@ -290,6 +335,8 @@
 /**
  * Updates the region for the content on this surface updated in this
  * transaction. If unspecified, the complete surface is assumed to be damaged.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
                                          ASurfaceControl* surface_control, const ARect rects[],
@@ -304,6 +351,8 @@
  *
  * If an earlier transaction has a desired present time of x, and a later transaction has a desired
  * present time that is before x, the later transaction will not preempt the earlier transaction.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
                                                int64_t desiredPresentTime) __INTRODUCED_IN(29);
@@ -312,6 +361,8 @@
  * Sets the alpha for the buffer. It uses a premultiplied blending.
  *
  * The |alpha| must be between 0.0 and 1.0.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
                                         ASurfaceControl* surface_control, float alpha)
@@ -321,6 +372,8 @@
  * Sets the data space of the surface_control's buffers.
  *
  * If no data space is set, the surface control defaults to ADATASPACE_SRGB.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
                                             ASurfaceControl* surface_control, ADataSpace data_space)
@@ -331,6 +384,8 @@
  *
  * When |metadata| is set to null, the framework does not use any smpte2086 metadata when rendering
  * the surface's buffer.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transaction,
                                                   ASurfaceControl* surface_control,
@@ -342,6 +397,8 @@
  *
  * When |metadata| is set to null, the framework does not use any cta861.3 metadata when rendering
  * the surface's buffer.
+ *
+ * Available since API level 29.
  */
 void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transaction,
                                                  ASurfaceControl* surface_control,
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index 540d23a..dde7eaa 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -65,6 +65,9 @@
  * Release the reference to the native ASurfaceTexture acquired with
  * ASurfaceTexture_fromSurfaceTexture().
  * Failing to do so will result in leaked memory and graphic resources.
+ *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
 void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
@@ -73,6 +76,8 @@
  * Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
  * This is equivalent to Java's: Surface sur = new Surface(surfaceTexture);
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * @return A reference to an ANativeWindow. This reference MUST BE released when no longer needed
  * using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
@@ -90,6 +95,8 @@
  * contexts.  Note, however, that the image contents are only accessible from one OpenGL ES
  * context at a time.
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \param texName The name of the OpenGL ES texture that will be created.  This texture name
  * must be unusued in the OpenGL ES context that is current on the calling thread.
@@ -108,6 +115,8 @@
  * contexts.  Note, however, that the image contents are only accessible from one OpenGL ES
  * context at a time.
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
@@ -118,6 +127,8 @@
  * called while the OpenGL ES context that owns the texture is current on the calling thread.
  * It will implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
@@ -135,6 +146,8 @@
  * The matrix is stored in column-major order so that it may be passed directly to OpenGL ES via
  * the glLoadMatrixf or glUniformMatrix4fv functions.
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \param mtx the array into which the 4x4 matrix will be stored.  The array must have exactly
  *     16 elements.
@@ -156,6 +169,8 @@
  * For EGL/Vulkan producers, this timestamp is the desired present time set with the
  * EGL_ANDROID_presentation_time or VK_GOOGLE_display_timing extensions
  *
+ * Available since API level 28.
+ *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
 int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index b0e1edd..2266d54 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,6 +32,8 @@
 
 __BEGIN_DECLS
 
+#if __ANDROID_API__ >= 28
+
 /**
  * Get a reference to the native ASurfaceTexture from the corresponding java object.
  *
@@ -40,13 +42,17 @@
  * properly once the Java object gets finalized.
  * However, this will not result in program termination.
  *
+ * Available since API level 28.
+ *
  * \param env JNI environment
  * \param surfacetexture Instance of Java SurfaceTexture object
  * \return native ASurfaceTexture reference or nullptr if the java object is not a SurfaceTexture.
  *         The returned reference MUST BE released when it's no longer needed using
  *         ASurfaceTexture_release().
  */
-ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture);
+ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
+
+#endif
 
 __END_DECLS
 
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index f0485a1..6fd7d2c 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -102,6 +102,8 @@
  *
  * Use ASystemFont_close() to close the iterator.
  *
+ * Available since API level 29.
+ *
  * \return a pointer for a newly allocated iterator, nullptr on failure.
  */
 ASystemFontIterator* _Nullable ASystemFontIterator_open() __INTRODUCED_IN(29);
@@ -109,6 +111,8 @@
 /**
  * Close an opened system font iterator, freeing any related resources.
  *
+ * Available since API level 29.
+ *
  * \param iterator a pointer of an iterator for the system fonts. Do nothing if NULL is passed.
  */
 void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTRODUCED_IN(29);
@@ -116,6 +120,8 @@
 /**
  * Move to the next system font.
  *
+ * Available since API level 29.
+ *
  * \param iterator an iterator for the system fonts. Passing NULL is not allowed.
  * \return a font. If no more font is available, returns nullptr. You need to release the returned
  *         font by ASystemFont_close when it is no longer needed.
diff --git a/include/android/trace.h b/include/android/trace.h
index bb7ff28..d59690a 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -74,7 +74,7 @@
 
 #endif /* __ANDROID_API__ >= 23 */
 
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 
 /**
  * Writes a trace message to indicate that a given section of code has
@@ -83,6 +83,8 @@
  * asynchronous events do not need to be nested. The name and cookie used to
  * begin an event must be used to end it.
  *
+ * Available since API level 29.
+ *
  * \param sectionName The method name to appear in the trace.
  * \param cookie Unique identifier for distinguishing simultaneous events
  */
@@ -93,6 +95,8 @@
  * Must be called exactly once for each call to {@link ATrace_beginAsyncSection}
  * using the same name and cookie.
  *
+ * Available since API level 29.
+ *
  * \param methodName The method name to appear in the trace.
  * \param cookie Unique identifier for distinguishing simultaneous events
  */
@@ -101,6 +105,8 @@
 /**
  * Writes trace message to indicate the value of a given counter.
  *
+ * Available since API level 29.
+ *
  * \param counterName The counter name to appear in the trace.
  * \param counterValue The counter value.
  */
diff --git a/include/binder b/include/binder
deleted file mode 120000
index 35a022a..0000000
--- a/include/binder
+++ /dev/null
@@ -1 +0,0 @@
-../libs/binder/include/binder/
\ No newline at end of file
diff --git a/include/binder/Binder.h b/include/binder/Binder.h
new file mode 120000
index 0000000..0fc6db7
--- /dev/null
+++ b/include/binder/Binder.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Binder.h
\ No newline at end of file
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
new file mode 120000
index 0000000..370b260
--- /dev/null
+++ b/include/binder/BinderService.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/BinderService.h
\ No newline at end of file
diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h
new file mode 120000
index 0000000..93a6219
--- /dev/null
+++ b/include/binder/IBinder.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/IBinder.h
\ No newline at end of file
diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h
new file mode 120000
index 0000000..8579878
--- /dev/null
+++ b/include/binder/IInterface.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/IInterface.h
\ No newline at end of file
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
new file mode 120000
index 0000000..5171c08
--- /dev/null
+++ b/include/binder/IMemory.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/IMemory.h
\ No newline at end of file
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
new file mode 120000
index 0000000..ecd4f81
--- /dev/null
+++ b/include/binder/IPCThreadState.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/IPCThreadState.h
\ No newline at end of file
diff --git a/include/binder/IServiceManager.h b/include/binder/IServiceManager.h
new file mode 120000
index 0000000..33d18cc
--- /dev/null
+++ b/include/binder/IServiceManager.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/IServiceManager.h
\ No newline at end of file
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
new file mode 120000
index 0000000..71881fb
--- /dev/null
+++ b/include/binder/MemoryDealer.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/MemoryDealer.h
\ No newline at end of file
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
new file mode 120000
index 0000000..8fb51cc
--- /dev/null
+++ b/include/binder/MemoryHeapBase.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/MemoryHeapBase.h
\ No newline at end of file
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
new file mode 120000
index 0000000..23492be
--- /dev/null
+++ b/include/binder/Parcel.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Parcel.h
\ No newline at end of file
diff --git a/include/binder/ParcelFileDescriptor.h b/include/binder/ParcelFileDescriptor.h
new file mode 120000
index 0000000..777bd49
--- /dev/null
+++ b/include/binder/ParcelFileDescriptor.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/ParcelFileDescriptor.h
\ No newline at end of file
diff --git a/include/binder/Parcelable.h b/include/binder/Parcelable.h
new file mode 120000
index 0000000..438e223
--- /dev/null
+++ b/include/binder/Parcelable.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Parcelable.h
\ No newline at end of file
diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h
new file mode 120000
index 0000000..e910c12
--- /dev/null
+++ b/include/binder/PermissionCache.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/PermissionCache.h
\ No newline at end of file
diff --git a/include/binder/PersistableBundle.h b/include/binder/PersistableBundle.h
new file mode 120000
index 0000000..785f2b4
--- /dev/null
+++ b/include/binder/PersistableBundle.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/PersistableBundle.h
\ No newline at end of file
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
new file mode 120000
index 0000000..4cbe7a5
--- /dev/null
+++ b/include/binder/ProcessState.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/ProcessState.h
\ No newline at end of file
diff --git a/include/binder/Stability.h b/include/binder/Stability.h
new file mode 120000
index 0000000..9b431d2
--- /dev/null
+++ b/include/binder/Stability.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Stability.h
\ No newline at end of file
diff --git a/include/binder/Status.h b/include/binder/Status.h
new file mode 120000
index 0000000..ccb994e
--- /dev/null
+++ b/include/binder/Status.h
@@ -0,0 +1 @@
+../../libs/binder/include/binder/Status.h
\ No newline at end of file
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
new file mode 100644
index 0000000..9cf0143
--- /dev/null
+++ b/libs/adbd_auth/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 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.
+
+cc_library {
+    name: "libadbd_auth",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wthread-safety",
+        "-Werror",
+    ],
+    srcs: ["adbd_auth.cpp"],
+    export_include_dirs: ["include"],
+
+    version_script: "libadbd_auth.map.txt",
+    stubs: {
+        symbol_file: "libadbd_auth.map.txt",
+    },
+
+    host_supported: true,
+    recovery_available: true,
+    target: {
+        darwin: {
+            enabled: false,
+        }
+    },
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+}
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
new file mode 100644
index 0000000..6479109
--- /dev/null
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 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 ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
+
+#include "include/adbd_auth.h"
+
+#include <inttypes.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/uio.h>
+
+#include <chrono>
+#include <deque>
+#include <string>
+#include <string_view>
+#include <tuple>
+#include <unordered_map>
+#include <utility>
+#include <variant>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
+#include <android-base/unique_fd.h>
+#include <cutils/sockets.h>
+
+using android::base::unique_fd;
+
+struct AdbdAuthPacketAuthenticated {
+    std::string public_key;
+};
+
+struct AdbdAuthPacketDisconnected {
+    std::string public_key;
+};
+
+struct AdbdAuthPacketRequestAuthorization {
+    std::string public_key;
+};
+
+using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated, AdbdAuthPacketDisconnected,
+                                    AdbdAuthPacketRequestAuthorization>;
+
+struct AdbdAuthContext {
+    static constexpr uint64_t kEpollConstSocket = 0;
+    static constexpr uint64_t kEpollConstEventFd = 1;
+    static constexpr uint64_t kEpollConstFramework = 2;
+
+public:
+    explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
+        epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
+        if (epoll_fd_ == -1) {
+            PLOG(FATAL) << "failed to create epoll fd";
+        }
+
+        event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+        if (event_fd_ == -1) {
+            PLOG(FATAL) << "failed to create eventfd";
+        }
+
+        sock_fd_.reset(android_get_control_socket("adbd"));
+        if (sock_fd_ == -1) {
+            PLOG(ERROR) << "failed to get adbd authentication socket";
+        } else {
+            if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
+                PLOG(FATAL) << "failed to make adbd authentication socket cloexec";
+            }
+
+            if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
+                PLOG(FATAL) << "failed to make adbd authentication socket nonblocking";
+            }
+
+            if (listen(sock_fd_.get(), 4) != 0) {
+                PLOG(FATAL) << "failed to listen on adbd authentication socket";
+            }
+        }
+    }
+
+    AdbdAuthContext(const AdbdAuthContext& copy) = delete;
+    AdbdAuthContext(AdbdAuthContext&& move) = delete;
+    AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
+    AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
+
+    uint64_t NextId() { return next_id_++; }
+
+    void DispatchPendingPrompt() REQUIRES(mutex_) {
+        if (dispatched_prompt_) {
+            LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
+            return;
+        }
+
+        if (pending_prompts_.empty()) {
+            LOG(INFO) << "adbd_auth: no prompts to send";
+            return;
+        }
+
+        LOG(INFO) << "adbd_auth: prompting user for adb authentication";
+        auto [id, public_key, arg] = std::move(pending_prompts_.front());
+        pending_prompts_.pop_front();
+
+        this->output_queue_.emplace_back(
+                AdbdAuthPacketRequestAuthorization{.public_key = public_key});
+
+        Interrupt();
+        dispatched_prompt_ = std::make_tuple(id, public_key, arg);
+    }
+
+    void UpdateFrameworkWritable() REQUIRES(mutex_) {
+        // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
+        // at the same time as a framework connection, but that's unlikely and this doesn't need to
+        // be fast anyway.
+        if (framework_fd_ != -1) {
+            struct epoll_event event;
+            event.events = EPOLLIN;
+            if (!output_queue_.empty()) {
+                LOG(INFO) << "marking framework writable";
+                event.events |= EPOLLOUT;
+            }
+            event.data.u64 = kEpollConstFramework;
+            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
+        }
+    }
+
+    void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
+        LOG(INFO) << "received new framework fd " << new_fd.get()
+                  << " (current = " << framework_fd_.get() << ")";
+
+        // If we already had a framework fd, clean up after ourselves.
+        if (framework_fd_ != -1) {
+            output_queue_.clear();
+            dispatched_prompt_.reset();
+            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
+            framework_fd_.reset();
+        }
+
+        if (new_fd != -1) {
+            struct epoll_event event;
+            event.events = EPOLLIN;
+            if (!output_queue_.empty()) {
+                LOG(INFO) << "marking framework writable";
+                event.events |= EPOLLOUT;
+            }
+            event.data.u64 = kEpollConstFramework;
+            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
+            framework_fd_ = std::move(new_fd);
+        }
+    }
+
+    void HandlePacket(std::string_view packet) REQUIRES(mutex_) {
+        LOG(INFO) << "received packet: " << packet;
+
+        if (packet.length() < 2) {
+          LOG(ERROR) << "received packet of invalid length";
+          ReplaceFrameworkFd(unique_fd());
+        }
+
+        if (packet[0] == 'O' && packet[1] == 'K') {
+          CHECK(this->dispatched_prompt_.has_value());
+          auto& [id, key, arg] = *this->dispatched_prompt_;
+          keys_.emplace(id, std::move(key));
+
+          this->callbacks_.key_authorized(arg, id);
+          this->dispatched_prompt_ = std::nullopt;
+        } else if (packet[0] == 'N' && packet[1] == 'O') {
+          CHECK_EQ(2UL, packet.length());
+          // TODO: Do we want a callback if the key is denied?
+          this->dispatched_prompt_ = std::nullopt;
+          DispatchPendingPrompt();
+        } else {
+          LOG(ERROR) << "unhandled packet: " << packet;
+          ReplaceFrameworkFd(unique_fd());
+        }
+    }
+
+    bool SendPacket() REQUIRES(mutex_) {
+        if (output_queue_.empty()) {
+            return false;
+        }
+
+        CHECK_NE(-1, framework_fd_.get());
+
+        auto& packet = output_queue_.front();
+        struct iovec iovs[2];
+        if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
+            iovs[0].iov_base = const_cast<char*>("CK");
+            iovs[0].iov_len = 2;
+            iovs[1].iov_base = p->public_key.data();
+            iovs[1].iov_len = p->public_key.size();
+        } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
+            iovs[0].iov_base = const_cast<char*>("DC");
+            iovs[0].iov_len = 2;
+            iovs[1].iov_base = p->public_key.data();
+            iovs[1].iov_len = p->public_key.size();
+        } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
+            iovs[0].iov_base = const_cast<char*>("PK");
+            iovs[0].iov_len = 2;
+            iovs[1].iov_base = p->public_key.data();
+            iovs[1].iov_len = p->public_key.size();
+        } else {
+            LOG(FATAL) << "unhandled packet type?";
+        }
+
+        output_queue_.pop_front();
+
+        ssize_t rc = writev(framework_fd_.get(), iovs, 2);
+        if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
+            PLOG(ERROR) << "failed to write to framework fd";
+            ReplaceFrameworkFd(unique_fd());
+            return false;
+        }
+
+        return true;
+    }
+
+    void Run() {
+        if (sock_fd_ == -1) {
+            LOG(ERROR) << "adbd authentication socket unavailable, disabling user prompts";
+        } else {
+            struct epoll_event event;
+            event.events = EPOLLIN;
+            event.data.u64 = kEpollConstSocket;
+            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
+        }
+
+        {
+            struct epoll_event event;
+            event.events = EPOLLIN;
+            event.data.u64 = kEpollConstEventFd;
+            CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
+        }
+
+        while (true) {
+            struct epoll_event events[3];
+            int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
+            if (rc == -1) {
+                PLOG(FATAL) << "epoll_wait failed";
+            } else if (rc == 0) {
+                LOG(FATAL) << "epoll_wait returned 0";
+            }
+
+            bool restart = false;
+            for (int i = 0; i < rc; ++i) {
+                if (restart) {
+                    break;
+                }
+
+                struct epoll_event& event = events[i];
+                switch (event.data.u64) {
+                    case kEpollConstSocket: {
+                        unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
+                                                           SOCK_CLOEXEC | SOCK_NONBLOCK));
+                        if (new_framework_fd == -1) {
+                            PLOG(FATAL) << "failed to accept framework fd";
+                        }
+
+                        LOG(INFO) << "adbd_auth: received a new framework connection";
+                        std::lock_guard<std::mutex> lock(mutex_);
+                        ReplaceFrameworkFd(std::move(new_framework_fd));
+
+                        // Stop iterating over events: one of the later ones might be the old
+                        // framework fd.
+                        restart = false;
+                        break;
+                    }
+
+                    case kEpollConstEventFd: {
+                        // We were woken up to write something.
+                        uint64_t dummy;
+                        int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
+                        if (rc != 8) {
+                            PLOG(FATAL) << "failed to read from eventfd (rc = " << rc << ")";
+                        }
+
+                        std::lock_guard<std::mutex> lock(mutex_);
+                        UpdateFrameworkWritable();
+                        break;
+                    }
+
+                    case kEpollConstFramework: {
+                        char buf[4096];
+                        if (event.events & EPOLLIN) {
+                            int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
+                            if (rc == -1) {
+                                LOG(FATAL) << "failed to read from framework fd";
+                            } else if (rc == 0) {
+                                LOG(INFO) << "hit EOF on framework fd";
+                                std::lock_guard<std::mutex> lock(mutex_);
+                                ReplaceFrameworkFd(unique_fd());
+                            } else {
+                                std::lock_guard<std::mutex> lock(mutex_);
+                                HandlePacket(std::string_view(buf, rc));
+                            }
+                        }
+
+                        if (event.events & EPOLLOUT) {
+                            std::lock_guard<std::mutex> lock(mutex_);
+                            while (SendPacket()) {
+                                continue;
+                            }
+                            UpdateFrameworkWritable();
+                        }
+
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
+    void IteratePublicKeys(bool (*callback)(const char*, size_t, void*), void* arg) {
+        for (const auto& path : key_paths) {
+            if (access(path, R_OK) == 0) {
+                LOG(INFO) << "Loading keys from " << path;
+                std::string content;
+                if (!android::base::ReadFileToString(path, &content)) {
+                    PLOG(ERROR) << "Couldn't read " << path;
+                    continue;
+                }
+                for (const auto& line : android::base::Split(content, "\n")) {
+                    if (!callback(line.data(), line.size(), arg)) {
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
+        uint64_t id = NextId();
+
+        std::lock_guard<std::mutex> lock(mutex_);
+        pending_prompts_.emplace_back(id, public_key, arg);
+        DispatchPendingPrompt();
+        return id;
+    }
+
+    uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
+        uint64_t id = NextId();
+        std::lock_guard<std::mutex> lock(mutex_);
+        keys_.emplace(id, public_key);
+        output_queue_.emplace_back(
+                AdbdAuthPacketDisconnected{.public_key = std::string(public_key)});
+        return id;
+    }
+
+    void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
+        std::lock_guard<std::mutex> lock(mutex_);
+        auto it = keys_.find(id);
+        if (it == keys_.end()) {
+            LOG(DEBUG) << "couldn't find public key to notify disconnection, skipping";
+            return;
+        }
+        output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
+        keys_.erase(it);
+    }
+
+    // Interrupt the worker thread to do some work.
+    void Interrupt() {
+        uint64_t value = 1;
+        ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
+        if (rc == -1) {
+            PLOG(FATAL) << "write to eventfd failed";
+        } else if (rc != sizeof(value)) {
+            LOG(FATAL) << "write to eventfd returned short (" << rc << ")";
+        }
+    }
+
+    unique_fd epoll_fd_;
+    unique_fd event_fd_;
+    unique_fd sock_fd_;
+    unique_fd framework_fd_;
+
+    std::atomic<uint64_t> next_id_;
+    AdbdAuthCallbacksV1 callbacks_;
+
+    std::mutex mutex_;
+    std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
+
+    // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
+    // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
+    std::deque<AdbdAuthPacket> output_queue_;
+
+    std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
+    std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
+};
+
+AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
+    if (callbacks->version != 1) {
+      LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version;
+      return nullptr;
+    }
+
+    return new AdbdAuthContext(&callbacks->callbacks.v1);
+}
+
+void adbd_auth_delete(AdbdAuthContext* ctx) {
+    delete ctx;
+}
+
+void adbd_auth_run(AdbdAuthContext* ctx) {
+    return ctx->Run();
+}
+
+void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
+                               bool (*callback)(const char* public_key, size_t len, void* arg),
+                               void* arg) {
+    ctx->IteratePublicKeys(callback, arg);
+}
+
+uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
+    return ctx->NotifyAuthenticated(std::string_view(public_key, len));
+}
+
+void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
+    return ctx->NotifyDisconnected(id);
+}
+
+void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
+                               void* arg) {
+    ctx->PromptUser(std::string_view(public_key, len), arg);
+}
+
+bool adbd_auth_supports_feature(AdbdAuthFeature) {
+    return false;
+}
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
new file mode 100644
index 0000000..b7c1cb8
--- /dev/null
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/*
+ * Copyright (C) 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.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+extern "C" {
+
+struct AdbdAuthCallbacksV1 {
+    // Callback for a successful user authorization.
+    void (*key_authorized)(void* arg, uint64_t id);
+};
+
+struct AdbdAuthCallbacks {
+    uint32_t version;
+    union {
+        AdbdAuthCallbacksV1 v1;
+    } callbacks;
+};
+
+struct AdbdAuthContext;
+
+AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks);
+void adbd_auth_delete(AdbdAuthContext* ctx);
+
+void adbd_auth_run(AdbdAuthContext* ctx);
+
+// Iterate through the list of authorized public keys.
+// Return false from the callback to stop iteration.
+void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
+                               bool (*callback)(const char* public_key, size_t len, void* arg),
+                               void* arg);
+
+// Let system_server know that a key has been successfully used for authentication.
+uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len);
+
+// Let system_server know that a connection has been closed.
+void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id);
+
+// Prompt the user to authorize a public key.
+// When this happens, a callback will be run on the auth thread with the result.
+void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* arg);
+
+enum AdbdAuthFeature {
+};
+
+bool adbd_auth_supports_feature(AdbdAuthFeature f);
+
+}
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
new file mode 100644
index 0000000..d01233c
--- /dev/null
+++ b/libs/adbd_auth/libadbd_auth.map.txt
@@ -0,0 +1,13 @@
+LIBADBD_AUTH {
+  global:
+    adbd_auth_new; # apex
+    adbd_auth_delete; # apex
+    adbd_auth_run; # apex
+    adbd_auth_get_public_keys; #apex
+    adbd_auth_notify_auth; # apex
+    adbd_auth_notify_disconnect; # apex
+    adbd_auth_prompt_user; # apex
+    adbd_auth_supports_feature; # apex
+  local:
+    *;
+};
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index ad8287c..2518b14 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -13,13 +13,18 @@
 // limitations under the License.
 
 ndk_headers {
-    name: "libarect_headers",
+    name: "libarect_headers_for_ndk",
     from: "include/android",
     to: "android",
     srcs: ["include/android/*.h"],
     license: "NOTICE",
 }
 
+cc_library_headers {
+    name: "libarect_headers",
+    export_include_dirs: ["include"],
+}
+
 cc_library_static {
     name: "libarect",
     host_supported: true,
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 643a956..7ee4882 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,6 +73,7 @@
     // or dessert updates. Instead, apex users should use libbinder_ndk.
     apex_available: [
         "//apex_available:platform",
+        "com.android.vndk.current",
         // TODO(b/139016109) remove these three
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
@@ -164,3 +165,16 @@
     ],
     path: "aidl",
 }
+
+aidl_interface {
+    name: "libbinder_aidl_test_stub",
+    local_include_dir: "aidl",
+    srcs: [":libbinder_aidl"],
+    visibility: [":__subpackages__"],
+    vendor_available: true,
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index a30df14..bac8b66 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -72,6 +72,7 @@
                         bool allowIsolated, int dumpsysPriority) override;
     Vector<String16> listServices(int dumpsysPriority) override;
     sp<IBinder> waitForService(const String16& name16) override;
+    bool isDeclared(const String16& name) override;
 
     // for legacy ABI
     const String16& getInterfaceDescriptor() const override {
@@ -279,19 +280,31 @@
         std::condition_variable mCv;
     };
 
+    // Simple RAII object to ensure a function call immediately before going out of scope
+    class Defer {
+    public:
+        Defer(std::function<void()>&& f) : mF(std::move(f)) {}
+        ~Defer() { mF(); }
+    private:
+        std::function<void()> mF;
+    };
+
     const std::string name = String8(name16).c_str();
 
     sp<IBinder> out;
     if (!mTheRealServiceManager->getService(name, &out).isOk()) {
         return nullptr;
     }
-    if(out != nullptr) return out;
+    if (out != nullptr) return out;
 
     sp<Waiter> waiter = new Waiter;
     if (!mTheRealServiceManager->registerForNotifications(
             name, waiter).isOk()) {
         return nullptr;
     }
+    Defer unregister ([&] {
+        mTheRealServiceManager->unregisterForNotifications(name, waiter);
+    });
 
     while(true) {
         {
@@ -315,10 +328,18 @@
         if (!mTheRealServiceManager->getService(name, &out).isOk()) {
             return nullptr;
         }
-        if(out != nullptr) return out;
+        if (out != nullptr) return out;
 
         ALOGW("Waited one second for %s", name.c_str());
     }
 }
 
+bool ServiceManagerShim::isDeclared(const String16& name) {
+    bool declared;
+    if (!mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared).isOk()) {
+        return false;
+    }
+    return declared;
+}
+
 } // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 6345640..9be06cd 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -505,7 +505,7 @@
     }
 }
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
 constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
 #else
 constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
@@ -1449,41 +1449,38 @@
     return err;
 }
 
-status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
-    if (size_t(size) > dataAvail()) {
-      return BAD_VALUE;
-    }
-    return read(data, size);
-}
-
 status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
-    return readByteVectorInternal(val->data(), val->size());
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+    return readByteVectorInternal(val, size);
 }
 
 status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
-    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+    return readByteVectorInternal(val, size);
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
     if (val->get() == nullptr) {
-        // resizeOutVector does not create the out vector if size is < 0.
+        // reserveOutVector does not create the out vector if size is < 0.
         // This occurs when writing a null byte vector.
         return OK;
     }
-    return readByteVectorInternal((*val)->data(), (*val)->size());
+    return readByteVectorInternal(val->get(), size);
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
     if (val->get() == nullptr) {
-        // resizeOutVector does not create the out vector if size is < 0.
+        // reserveOutVector does not create the out vector if size is < 0.
         // This occurs when writing a null byte vector.
         return OK;
     }
-    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+    return readByteVectorInternal(val->get(), size);
 }
 
 status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 0336d3e..ce2cd99 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -188,6 +188,30 @@
     return count;
 }
 
+// Queries the driver for the current strong reference count of the node
+// that the handle points to. Can only be used by the servicemanager.
+//
+// Returns -1 in case of failure, otherwise the strong reference count.
+ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) {
+    binder_node_info_for_ref info;
+    memset(&info, 0, sizeof(binder_node_info_for_ref));
+
+    info.handle = handle;
+
+    status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
+
+    if (result != OK) {
+        static bool logged = false;
+        if (!logged) {
+          ALOGW("Kernel does not support BINDER_GET_NODE_INFO_FOR_REF.");
+          logged = true;
+        }
+        return -1;
+    }
+
+    return info.strong_count;
+}
+
 void ProcessState::setCallRestriction(CallRestriction restriction) {
     LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull() != nullptr,
         "Call restrictions must be set before the threadpool is started.");
@@ -361,6 +385,12 @@
     , mThreadPoolSeq(1)
     , mCallRestriction(CallRestriction::NONE)
 {
+
+// TODO(b/139016109): enforce in build system
+#if defined(__ANDROID_APEX__) && !defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__)
+    LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
+#endif
+
     if (mDriverFD >= 0) {
         // mmap the binder, providing a chunk of virtual address space to receive transactions.
         mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 0ad99ce..674f065 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -232,9 +232,10 @@
         ret.append("No error");
     } else {
         ret.appendFormat("Status(%d, %s): '", mException, exceptionToString(mException).c_str());
-        if (mException == EX_SERVICE_SPECIFIC ||
-            mException == EX_TRANSACTION_FAILED) {
+        if (mException == EX_SERVICE_SPECIFIC) {
             ret.appendFormat("%d: ", mErrorCode);
+        } else if (mException == EX_TRANSACTION_FAILED) {
+            ret.appendFormat("%s: ", statusToString(mErrorCode).c_str());
         }
         ret.append(String8(mMessage));
         ret.append("'");
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 60c2cce..b965881 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -31,22 +31,22 @@
      * Must update values in IServiceManager.h
      */
     /* Allows services to dump sections according to priorities. */
-    const int DUMP_FLAG_PRIORITY_CRITICAL = 1; // 1 << 0
-    const int DUMP_FLAG_PRIORITY_HIGH = 2; // 1 << 1
-    const int DUMP_FLAG_PRIORITY_NORMAL = 4; // 1 << 2
+    const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
+    const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
+    const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
     /**
      * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
      * same priority as NORMAL priority but the services are not called with dump priority
      * arguments.
      */
-    const int DUMP_FLAG_PRIORITY_DEFAULT = 8; // 1 << 3
+    const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
 
     const int DUMP_FLAG_PRIORITY_ALL = 15;
              // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
              // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
 
     /* Allows services to dump sections in protobuf format. */
-    const int DUMP_FLAG_PROTO = 16; // 1 << 4
+    const int DUMP_FLAG_PROTO = 1 << 4;
 
     /**
      * Retrieve an existing service called @a name from the
@@ -58,7 +58,7 @@
      * Returns null if the service does not exist.
      */
     @UnsupportedAppUsage
-    IBinder getService(@utf8InCpp String name);
+    @nullable IBinder getService(@utf8InCpp String name);
 
     /**
      * Retrieve an existing service called @a name from the service
@@ -66,7 +66,7 @@
      * exist.
      */
     @UnsupportedAppUsage
-    IBinder checkService(@utf8InCpp String name);
+    @nullable IBinder checkService(@utf8InCpp String name);
 
     /**
      * Place a new @a service called @a name into the service
@@ -89,4 +89,11 @@
      * Unregisters all requests for notifications for a specific callback.
      */
     void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback);
+
+    /**
+     * Returns whether a given interface is declared on the device, even if it
+     * is not started yet. For instance, this could be a service declared in the VINTF
+     * manifest.
+     */
+    boolean isDeclared(@utf8InCpp String name);
 }
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 28ffa48..79d9b79 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -38,12 +38,32 @@
 
 // ----------------------------------------------------------------------
 
+/**
+ * If this is a local object and the descriptor matches, this will return the
+ * actual local object which is implementing the interface. Otherwise, this will
+ * return a proxy to the interface without checking the interface descriptor.
+ * This means that subsequent calls may fail with BAD_TYPE.
+ */
 template<typename INTERFACE>
 inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
 {
     return INTERFACE::asInterface(obj);
 }
 
+/**
+ * This is the same as interface_cast, except that it always checks to make sure
+ * the descriptor matches, and if it doesn't match, it will return nullptr.
+ */
+template<typename INTERFACE>
+inline sp<INTERFACE> checked_interface_cast(const sp<IBinder>& obj)
+{
+    if (obj->getInterfaceDescriptor() != INTERFACE::descriptor) {
+        return nullptr;
+    }
+
+    return interface_cast<INTERFACE>(obj);
+}
+
 // ----------------------------------------------------------------------
 
 template<typename INTERFACE>
@@ -89,7 +109,27 @@
 
 
 #define __IINTF_CONCAT(x, y) (x ## y)
+
+#ifndef DO_NOT_CHECK_MANUAL_BINDER_INTERFACES
+
 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
+    static_assert(internal::allowedManualInterface(NAME),               \
+                  "b/64223827: Manually written binder interfaces are " \
+                  "considered error prone and frequently have bugs. "   \
+                  "The preferred way to add interfaces is to define "   \
+                  "an .aidl file to auto-generate the interface. If "   \
+                  "an interface must be manually written, add its "     \
+                  "name to the whitelist.");                            \
+    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)    \
+
+#else
+
+#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
+    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)    \
+
+#endif
+
+#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
     const ::android::StaticString16                                     \
         I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
     const ::android::String16 I##INTERFACE::descriptor(                 \
@@ -172,6 +212,122 @@
 
 // ----------------------------------------------------------------------
 
+namespace internal {
+constexpr const char* const kManualInterfaces[] = {
+  "android.app.IActivityManager",
+  "android.app.IUidObserver",
+  "android.drm.IDrm",
+  "android.dvr.IVsyncCallback",
+  "android.dvr.IVsyncService",
+  "android.gfx.tests.ICallback",
+  "android.gfx.tests.IIPCTest",
+  "android.gfx.tests.ISafeInterfaceTest",
+  "android.graphicsenv.IGpuService",
+  "android.gui.DisplayEventConnection",
+  "android.gui.IConsumerListener",
+  "android.gui.IGraphicBufferConsumer",
+  "android.gui.IRegionSamplingListener",
+  "android.gui.ITransactionComposerListener",
+  "android.gui.SensorEventConnection",
+  "android.gui.SensorServer",
+  "android.hardware.ICamera",
+  "android.hardware.ICameraClient",
+  "android.hardware.ICameraRecordingProxy",
+  "android.hardware.ICameraRecordingProxyListener",
+  "android.hardware.ICrypto",
+  "android.hardware.IOMXObserver",
+  "android.hardware.ISoundTrigger",
+  "android.hardware.ISoundTriggerClient",
+  "android.hardware.ISoundTriggerHwService",
+  "android.hardware.IStreamListener",
+  "android.hardware.IStreamSource",
+  "android.input.IInputFlinger",
+  "android.input.ISetInputWindowsListener",
+  "android.media.IAudioFlinger",
+  "android.media.IAudioFlingerClient",
+  "android.media.IAudioPolicyService",
+  "android.media.IAudioPolicyServiceClient",
+  "android.media.IAudioService",
+  "android.media.IAudioTrack",
+  "android.media.IDataSource",
+  "android.media.IDrmClient",
+  "android.media.IEffect",
+  "android.media.IEffectClient",
+  "android.media.IMediaAnalyticsService",
+  "android.media.IMediaCodecList",
+  "android.media.IMediaDrmService",
+  "android.media.IMediaExtractor",
+  "android.media.IMediaExtractorService",
+  "android.media.IMediaHTTPConnection",
+  "android.media.IMediaHTTPService",
+  "android.media.IMediaLogService",
+  "android.media.IMediaMetadataRetriever",
+  "android.media.IMediaPlayer",
+  "android.media.IMediaPlayerClient",
+  "android.media.IMediaPlayerService",
+  "android.media.IMediaRecorder",
+  "android.media.IMediaRecorderClient",
+  "android.media.IMediaResourceMonitor",
+  "android.media.IMediaSource",
+  "android.media.IRemoteDisplay",
+  "android.media.IRemoteDisplayClient",
+  "android.media.IResourceManagerClient",
+  "android.media.IResourceManagerService",
+  "android.os.IComplexTypeInterface",
+  "android.os.IPermissionController",
+  "android.os.IPingResponder",
+  "android.os.IPowerManager",
+  "android.os.IProcessInfoService",
+  "android.os.ISchedulingPolicyService",
+  "android.os.IStringConstants",
+  "android.os.storage.IObbActionListener",
+  "android.os.storage.IStorageEventListener",
+  "android.os.storage.IStorageManager",
+  "android.os.storage.IStorageShutdownObserver",
+  "android.service.vr.IPersistentVrStateCallbacks",
+  "android.service.vr.IVrManager",
+  "android.service.vr.IVrStateCallbacks",
+  "android.ui.ISurfaceComposer",
+  "android.ui.ISurfaceComposerClient",
+  "android.utils.IMemory",
+  "android.utils.IMemoryHeap",
+  "com.android.car.procfsinspector.IProcfsInspector",
+  "com.android.internal.app.IAppOpsCallback",
+  "com.android.internal.app.IAppOpsService",
+  "com.android.internal.app.IBatteryStats",
+  "com.android.internal.os.IResultReceiver",
+  "com.android.internal.os.IShellCallback",
+  "drm.IDrmManagerService",
+  "drm.IDrmServiceListener",
+  "IAAudioClient",
+  "IAAudioService",
+  "VtsFuzzer",
+  nullptr,
+};
+
+constexpr const char* const kDownstreamManualInterfaces[] = {
+  // Add downstream interfaces here.
+  nullptr,
+};
+
+constexpr bool equals(const char* a, const char* b) {
+  if (*a != *b) return false;
+  if (*a == '\0') return true;
+  return equals(a + 1, b + 1);
+}
+
+constexpr bool inList(const char* a, const char* const* whitelist) {
+  if (*whitelist == nullptr) return false;
+  if (equals(a, *whitelist)) return true;
+  return inList(a, whitelist + 1);
+}
+
+constexpr bool allowedManualInterface(const char* name) {
+  return inList(name, kManualInterfaces) ||
+         inList(name, kDownstreamManualInterfaces);
+}
+
+} // namespace internal
 } // namespace android
 
 #endif // ANDROID_IINTERFACE_H
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index a675513..2c43263 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -88,6 +88,14 @@
      * Returns nullptr only for permission problem or fatal error.
      */
     virtual sp<IBinder> waitForService(const String16& name) = 0;
+
+    /**
+     * Check if a service is declared (e.g. VINTF manifest).
+     *
+     * If this returns true, waitForService should always be able to return the
+     * service.
+     */
+    virtual bool isDeclared(const String16& name) = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
@@ -99,6 +107,34 @@
 }
 
 template<typename INTERFACE>
+sp<INTERFACE> waitForDeclaredService(const String16& name) {
+    const sp<IServiceManager> sm = defaultServiceManager();
+    if (!sm->isDeclared(name)) return nullptr;
+    return interface_cast<INTERFACE>(sm->waitForService(name));
+}
+
+template <typename INTERFACE>
+sp<INTERFACE> checkDeclaredService(const String16& name) {
+    const sp<IServiceManager> sm = defaultServiceManager();
+    if (!sm->isDeclared(name)) return nullptr;
+    return interface_cast<INTERFACE>(sm->checkService(name));
+}
+
+template<typename INTERFACE>
+sp<INTERFACE> waitForVintfService(
+        const String16& instance = String16("default")) {
+    return waitForDeclaredService<INTERFACE>(
+        INTERFACE::descriptor + String16("/") + instance);
+}
+
+template<typename INTERFACE>
+sp<INTERFACE> checkVintfService(
+        const String16& instance = String16("default")) {
+    return checkDeclaredService<INTERFACE>(
+        INTERFACE::descriptor + String16("/") + instance);
+}
+
+template<typename INTERFACE>
 status_t getService(const String16& name, sp<INTERFACE>* outService)
 {
     const sp<IServiceManager> sm = defaultServiceManager();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 0f8abab..d4bb85b 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -356,6 +356,11 @@
     status_t            resizeOutVector(std::vector<T>* val) const;
     template<typename T>
     status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
+    template<typename T>
+    status_t            reserveOutVector(std::vector<T>* val, size_t* size) const;
+    template<typename T>
+    status_t            reserveOutVector(std::unique_ptr<std::vector<T>>* val,
+                                         size_t* size) const;
 
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
@@ -475,7 +480,8 @@
     status_t            readEnum(T* pArg) const;
 
     status_t writeByteVectorInternal(const int8_t* data, size_t size);
-    status_t readByteVectorInternal(int8_t* data, size_t size) const;
+    template<typename T>
+    status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
 
     template<typename T, typename U>
     status_t            unsafeReadTypedVector(std::vector<T>* val,
@@ -720,6 +726,42 @@
 }
 
 template<typename T>
+status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
+    int32_t read_size;
+    status_t err = readInt32(&read_size);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    if (read_size < 0) {
+        return UNEXPECTED_NULL;
+    }
+    *size = static_cast<size_t>(read_size);
+    val->reserve(*size);
+    return OK;
+}
+
+template<typename T>
+status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
+                                  size_t* size) const {
+    int32_t read_size;
+    status_t err = readInt32(&read_size);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    if (read_size >= 0) {
+        *size = static_cast<size_t>(read_size);
+        val->reset(new std::vector<T>());
+        (*val)->reserve(*size);
+    } else {
+        val->reset();
+    }
+
+    return OK;
+}
+
+template<typename T>
 status_t Parcel::readStrongBinder(sp<T>* val) const {
     sp<IBinder> tmp;
     status_t ret = readStrongBinder(&tmp);
@@ -988,20 +1030,33 @@
     return readInt64(reinterpret_cast<int64_t *>(pArg));
 }
 
+template<typename T>
+inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
+  // readByteVectorInternal expects a vector that has been reserved (but not
+  // resized) to have the provided size.
+  const T* data = reinterpret_cast<const T*>(readInplace(size));
+  if (!data) return BAD_VALUE;
+  val->clear();
+  val->insert(val->begin(), data, data+size);
+  return NO_ERROR;
+}
+
 template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
 status_t Parcel::readEnumVector(std::vector<T>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
-    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+    return readByteVectorInternal(val, size);
 }
 template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
 status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
-    if (status_t status = resizeOutVector(val); status != OK) return status;
+    size_t size;
+    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
     if (val->get() == nullptr) {
-        // resizeOutVector does not create the out vector if size is < 0.
+        // reserveOutVector does not create the out vector if size is < 0.
         // This occurs when writing a null Enum vector.
         return OK;
     }
-    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+    return readByteVectorInternal(val->get(), size);
 }
 template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
 status_t Parcel::readEnumVector(std::vector<T>* val) const {
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 662e56e..4635ad8 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -42,6 +42,24 @@
     android::status_t writeToParcel(android::Parcel* parcel) const override;
     android::status_t readFromParcel(const android::Parcel* parcel) override;
 
+    inline bool operator!=(const ParcelFileDescriptor& rhs) const {
+        return mFd != rhs.mFd;
+    }
+    inline bool operator<(const ParcelFileDescriptor& rhs) const {
+        return mFd < rhs.mFd;
+    }
+    inline bool operator<=(const ParcelFileDescriptor& rhs) const {
+        return mFd <= rhs.mFd;
+    }
+    inline bool operator==(const ParcelFileDescriptor& rhs) const {
+        return mFd == rhs.mFd;
+    }
+    inline bool operator>(const ParcelFileDescriptor& rhs) const {
+        return mFd > rhs.mFd;
+    }
+    inline bool operator>=(const ParcelFileDescriptor& rhs) const {
+        return mFd >= rhs.mFd;
+    }
 private:
     android::base::unique_fd mFd;
 };
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index f7c38f4..e57ff1c 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -69,6 +69,14 @@
 
             ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
 
+                                // Only usable by the context manager.
+                                // This refcount includes:
+                                // 1. Strong references to the node by this and other processes
+                                // 2. Temporary strong references held by the kernel during a
+                                //    transaction on the node.
+                                // It does NOT include local strong references to the node
+            ssize_t             getStrongRefCountForNodeByHandle(int32_t handle);
+
             enum class CallRestriction {
                 // all calls okay
                 NONE,
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 2894482..b2f51d3 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,7 +81,7 @@
         VINTF = 0b111111,
     };
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
     static constexpr Level kLocalStability = Level::VENDOR;
 #else
     static constexpr Level kLocalStability = Level::SYSTEM;
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 62a0f9f..c0ea6d7 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -22,6 +22,8 @@
             cflags: [
                 "-D__INTRODUCED_IN(n)=",
                 "-D__assert(a,b,c)=",
+                // We want all the APIs to be available on the host.
+                "-D__ANDROID_API__=10000",
             ],
         },
     },
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index dc3c8d2..946ccb7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -21,7 +21,7 @@
 
 /**
  * @file binder_auto_utils.h
- * @brief These objects provide a more C++-like thin interface to the .
+ * @brief These objects provide a more C++-like thin interface to the binder.
  */
 
 #pragma once
@@ -159,13 +159,17 @@
      */
     T* getR() { return &mT; }
 
-    // copy-constructing, or move/copy assignment is disallowed
+    // copy-constructing/assignment is disallowed
     ScopedAResource(const ScopedAResource&) = delete;
     ScopedAResource& operator=(const ScopedAResource&) = delete;
-    ScopedAResource& operator=(ScopedAResource&&) = delete;
 
-    // move-constructing is okay
+    // move-constructing/assignment is okay
     ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
+    ScopedAResource& operator=(ScopedAResource&& other) {
+        set(other.mT);
+        other.mT = DEFAULT;
+        return *this;
+    }
 
    private:
     T mT;
@@ -197,6 +201,7 @@
     explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
     ~ScopedAStatus() {}
     ScopedAStatus(ScopedAStatus&&) = default;
+    ScopedAStatus& operator=(ScopedAStatus&&) = default;
 
     /**
      * See AStatus_isOk.
@@ -219,9 +224,31 @@
     binder_status_t getStatus() const { return AStatus_getStatus(get()); }
 
     /**
-     * Convenience method for okay status.
+     * See AStatus_getMessage
+     */
+    const char* getMessage() const { return AStatus_getMessage(get()); }
+
+    /**
+     * Convenience methods for creating scoped statuses.
      */
     static ScopedAStatus ok() { return ScopedAStatus(AStatus_newOk()); }
+    static ScopedAStatus fromExceptionCode(binder_exception_t exception) {
+        return ScopedAStatus(AStatus_fromExceptionCode(exception));
+    }
+    static ScopedAStatus fromExceptionCodeWithMessage(binder_exception_t exception,
+                                                      const char* message) {
+        return ScopedAStatus(AStatus_fromExceptionCodeWithMessage(exception, message));
+    }
+    static ScopedAStatus fromServiceSpecificError(int32_t serviceSpecific) {
+        return ScopedAStatus(AStatus_fromServiceSpecificError(serviceSpecific));
+    }
+    static ScopedAStatus fromServiceSpecificErrorWithMessage(int32_t serviceSpecific,
+                                                             const char* message) {
+        return ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(serviceSpecific, message));
+    }
+    static ScopedAStatus fromStatus(binder_status_t status) {
+        return ScopedAStatus(AStatus_fromStatus(status));
+    }
 };
 
 /**
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 160739b..4560f22 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -34,7 +34,13 @@
 #include <android/binder_status.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+#ifndef __ANDROID_API__
+#error Android builds must be compiled against a specific API. If this is an \
+ android platform host build, you must use libbinder_ndk_host_user.
+#endif
+
+#if __ANDROID_API__ >= 29
 
 // Also see TF_* in kernel's binder.h
 typedef uint32_t binder_flags_t;
@@ -165,6 +171,8 @@
  *
  * None of these parameters can be null.
  *
+ * Available since API level 29.
+ *
  * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
  * sanity checks on transactions.
  * \param onCreate see AIBinder_Class_onCreate.
@@ -199,6 +207,8 @@
  * If this isn't set, nothing will be dumped when dump is called (for instance with
  * android.os.Binder#dump). Must be called before any instance of the class is created.
  *
+ * Available since API level 29.
+ *
  * \param dump function to call when an instance of this binder class is being dumped.
  */
 void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
@@ -220,6 +230,8 @@
  * these two objects are actually equal using the AIBinder pointer alone (which they should be able
  * to do). Also see the suggested memory ownership model suggested above.
  *
+ * Available since API level 29.
+ *
  * \param clazz the type of the object to be created.
  * \param args the args to pass to AIBinder_onCreate for that class.
  *
@@ -231,6 +243,8 @@
 /**
  * If this is hosted in a process other than the current one.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder being queried.
  *
  * \return true if the AIBinder represents an object in another process.
@@ -244,6 +258,8 @@
  * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
  * based on the results of bookkeeping or other transactions made internally.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder being queried.
  *
  * \return true if the binder is alive.
@@ -255,6 +271,8 @@
  * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
  * sanity check.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder being queried.
  *
  * \return STATUS_OK if the ping succeeds.
@@ -264,7 +282,9 @@
 /**
  * Built-in transaction for all binder objects. This dumps information about a given binder.
  *
- * See also AIBinder_Class_setOnDump, AIBinder_onDump
+ * See also AIBinder_Class_setOnDump, AIBinder_onDump.
+ *
+ * Available since API level 29.
  *
  * \param binder the binder to dump information about
  * \param fd where information should be dumped to
@@ -287,6 +307,8 @@
  *
  * If binder is local, this will return STATUS_INVALID_OPERATION.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object you want to receive death notifications from.
  * \param recipient the callback that will receive notifications when/if the binder dies.
  * \param cookie the value that will be passed to the death recipient on death.
@@ -306,6 +328,8 @@
  * If the binder dies, it will automatically unlink. If the binder is deleted, it will be
  * automatically unlinked.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to remove a previously linked death recipient from.
  * \param recipient the callback to remove.
  * \param cookie the cookie used to link to death.
@@ -322,9 +346,11 @@
  * This can be used with higher-level system services to determine the caller's identity and check
  * permissions.
  *
+ * Available since API level 29.
+ *
  * \return calling uid or the current process's UID if this thread isn't processing a transaction.
  */
-uid_t AIBinder_getCallingUid();
+uid_t AIBinder_getCallingUid() __INTRODUCED_IN(29);
 
 /**
  * This returns the calling PID assuming that this thread is called from a thread that is processing
@@ -335,14 +361,18 @@
  * calling process dies and is replaced with another process with elevated permissions and the same
  * PID.
  *
+ * Available since API level 29.
+ *
  * \return calling pid or the current process's PID if this thread isn't processing a transaction.
  * If the transaction being processed is a oneway transaction, then this method will return 0.
  */
-pid_t AIBinder_getCallingPid();
+pid_t AIBinder_getCallingPid() __INTRODUCED_IN(29);
 
 /**
  * This can only be called if a strong reference to this object already exists in process.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to add a refcount to.
  */
 void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -350,6 +380,8 @@
 /**
  * This will delete the object and call onDestroy once the refcount reaches zero.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to remove a refcount from.
  */
 void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
@@ -357,6 +389,8 @@
 /**
  * For debugging only!
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to retrieve the refcount of.
  *
  * \return the number of strong-refs on this binder in this process. If binder is null, this will be
@@ -373,6 +407,8 @@
  * This returns true if the class association succeeds. If it fails, no change is made to the
  * binder object.
  *
+ * Available since API level 29.
+ *
  * \param binder the object to attach the class to.
  * \param clazz the clazz to attach to binder.
  *
@@ -383,6 +419,8 @@
 /**
  * Returns the class that this binder was constructed with or associated with.
  *
+ * Available since API level 29.
+ *
  * \param binder the object that is being queried.
  *
  * \return the class that this binder is associated with. If this binder wasn't created with
@@ -394,6 +432,8 @@
  * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
  * null), this also returns null. For a remote binder, this will always return null.
  *
+ * Available since API level 29.
+ *
  * \param binder the object that is being queried.
  *
  * \return the userdata returned from AIBinder_onCreate when this object was created. This may be
@@ -422,6 +462,8 @@
  * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
  * deleted with AParcel_delete.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to start a transaction on.
  * \param in out parameter for input data to the transaction.
  *
@@ -442,6 +484,8 @@
  * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
  * and must be released with AParcel_delete when finished reading.
  *
+ * Available since API level 29.
+ *
  * \param binder the binder object to transact on.
  * \param code the implementation-specific code representing which transaction should be taken.
  * \param in the implementation-specific input data to this transaction.
@@ -459,6 +503,8 @@
  * This does not take any ownership of the input binder, but it can be used to retrieve it if
  * something else in some process still holds a reference to it.
  *
+ * Available since API level 29.
+ *
  * \param binder object to create a weak pointer to.
  *
  * \return object representing a weak pointer to binder (or null if binder is null).
@@ -469,6 +515,8 @@
 /**
  * Deletes the weak reference. This will have no impact on the lifetime of the binder.
  *
+ * Available since API level 29.
+ *
  * \param weakBinder object created with AIBinder_Weak_new.
  */
 void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
@@ -477,6 +525,8 @@
  * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
  * null.
  *
+ * Available since API level 29.
+ *
  * \param weakBinder weak pointer to attempt retrieving the original object from.
  *
  * \return an AIBinder object with one refcount given to the caller or null.
@@ -487,6 +537,8 @@
 /**
  * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
  *
+ * Available since API level 29.
+ *
  * \param cookie the cookie passed to AIBinder_linkToDeath.
  */
 typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29);
@@ -494,6 +546,8 @@
 /**
  * Creates a new binder death recipient. This can be attached to multiple different binder objects.
  *
+ * Available since API level 29.
+ *
  * \param onBinderDied the callback to call when this death recipient is invoked.
  *
  * \return the newly constructed object (or null if onBinderDied is null).
@@ -505,19 +559,23 @@
  * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
  * calling this as these will all be automatically unlinked.
  *
+ * Available since API level 29.
+ *
  * \param recipient the binder to delete (previously created with AIBinder_DeathRecipient_new).
  */
 void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
+#endif  //__ANDROID_API__ >= 29
 
-#if __ANDROID_API__ >= __ANDROID_API_R__
+#if __ANDROID_API__ >= 30
 
 /**
  * Gets the extension registered with AIBinder_setExtension.
  *
  * See AIBinder_setExtension.
  *
+ * Available since API level 30.
+ *
  * \param binder the object to get the extension of.
  * \param outExt the returned extension object. Will be null if there is no extension set or
  * non-null with one strong ref count.
@@ -570,6 +628,8 @@
  *         // if bar is null, then there is no extension or a different
  *         // type of extension
  *
+ * Available since API level 30.
+ *
  * \param binder the object to get the extension on. Must be local.
  * \param ext the extension to set (binder will hold a strong reference to this)
  *
@@ -578,7 +638,7 @@
  */
 binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
 
-#endif  //__ANDROID_API__ >= __ANDROID_API_R__
+#endif  //__ANDROID_API__ >= 30
 
 __END_DECLS
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index 124f36c..be3029c 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,7 @@
 #include <jni.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 
 /**
  * Converts an android.os.IBinder object into an AIBinder* object.
@@ -40,6 +40,8 @@
  * AIBinder object, the original object is returned. The returned object has one refcount
  * associated with it, and so this should be accompanied with an AIBinder_decStrong call.
  *
+ * Available since API level 29.
+ *
  * \param env Java environment.
  * \param binder android.os.IBinder java object.
  *
@@ -55,6 +57,8 @@
  * If either env or the binder is null, null is returned. If this binder object was originally an
  * IBinder object, the original java object will be returned.
  *
+ * Available since API level 29.
+ *
  * \param env Java environment.
  * \param binder the object to convert.
  *
@@ -63,7 +67,7 @@
 __attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
         __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
+#endif  //__ANDROID_API__ >= 29
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 8c41707..86b75b8 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -35,7 +35,7 @@
 typedef struct AIBinder AIBinder;
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 
 /**
  * This object represents a package of data that can be sent between processes. When transacting, an
@@ -49,6 +49,8 @@
 /**
  * Cleans up a parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel A parcel returned by AIBinder_prepareTransaction or AIBinder_transact when a
  * transaction is being aborted.
  */
@@ -57,6 +59,8 @@
 /**
  * Sets the position within the parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel The parcel of which to set the position.
  * \param position Position of the parcel to set. This must be a value returned by
  * AParcel_getDataPosition. Positions are constant for a given parcel between processes.
@@ -69,6 +73,8 @@
 /**
  * Gets the current position within the parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel The parcel of which to get the position.
  *
  * \return The size of the parcel. This will always be greater than 0. The values returned by this
@@ -389,6 +395,8 @@
  * Writes an AIBinder to the next location in a non-null parcel. Can be null. This does not take any
  * refcounts of ownership of the binder from the client.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param binder the value to write to the parcel.
  *
@@ -400,6 +408,8 @@
  * Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership
  * is passed to the caller of this function.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param binder the out parameter for what is read from the parcel. This may be null.
  *
@@ -414,12 +424,14 @@
  *
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);
+binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) __INTRODUCED_IN(29);
 
 /**
  * Reads an int from the next location in a non-null parcel.
@@ -428,13 +440,16 @@
  *
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param fd the out parameter for what is read from the parcel (or -1 to represent a null
  * ParcelFileDescriptor)
  *
  * \return STATUS_OK on successful write.
  */
-binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);
+binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd)
+        __INTRODUCED_IN(29);
 
 /**
  * Writes an AStatus object to the next location in a non-null parcel.
@@ -445,6 +460,8 @@
  * this happens or if writing the status object itself fails, the return value from this function
  * should be propagated to the client, and AParcel_readStatusHeader shouldn't be called.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param status the value to write to the parcel.
  *
@@ -457,6 +474,8 @@
  * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
  * of this function.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param status the out parameter for what is read from the parcel.
  *
@@ -470,6 +489,8 @@
  *
  * If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param string the null-terminated string to write to the parcel, at least of size 'length'.
  * \param length the length of the string to be written.
@@ -487,6 +508,8 @@
  * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
  * will be called with length -1.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param stringData some external representation of a string.
  * \param allocator allocator that will be called once the size of the string is known.
@@ -504,6 +527,8 @@
  * returned from this function will be used to fill out the data from the parcel. If length is -1,
  * this will write a 'null' string array to the binder buffer.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
  * \param length the length of the array to be written.
@@ -526,6 +551,8 @@
  * the contents of the string that is read. If the string array being read is 'null', this will
  * instead just pass -1 to AParcel_stringArrayAllocator.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called with arrayData once the size of the output
@@ -543,6 +570,8 @@
 /**
  * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -562,6 +591,8 @@
  * length is greater than zero, elementReader will be called for every index to read the
  * corresponding parcelable.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -578,6 +609,8 @@
 /**
  * Writes int32_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -588,6 +621,8 @@
 /**
  * Writes uint32_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -598,6 +633,8 @@
 /**
  * Writes int64_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -608,6 +645,8 @@
 /**
  * Writes uint64_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -618,6 +657,8 @@
 /**
  * Writes float value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -628,6 +669,8 @@
 /**
  * Writes double value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -638,6 +681,8 @@
 /**
  * Writes bool value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -648,6 +693,8 @@
 /**
  * Writes char16_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -658,6 +705,8 @@
 /**
  * Writes int8_t value to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param value the value to write to the parcel.
  *
@@ -668,6 +717,8 @@
 /**
  * Reads into int32_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -678,6 +729,8 @@
 /**
  * Reads into uint32_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -688,6 +741,8 @@
 /**
  * Reads into int64_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -698,6 +753,8 @@
 /**
  * Reads into uint64_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -708,6 +765,8 @@
 /**
  * Reads into float value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -718,6 +777,8 @@
 /**
  * Reads into double value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -728,6 +789,8 @@
 /**
  * Reads into bool value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -738,6 +801,8 @@
 /**
  * Reads into char16_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -748,6 +813,8 @@
 /**
  * Reads into int8_t value from the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param value the value to read from the parcel.
  *
@@ -758,6 +825,8 @@
 /**
  * Writes an array of int32_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -770,6 +839,8 @@
 /**
  * Writes an array of uint32_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -782,6 +853,8 @@
 /**
  * Writes an array of int64_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -794,6 +867,8 @@
 /**
  * Writes an array of uint64_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -806,6 +881,8 @@
 /**
  * Writes an array of float to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -818,6 +895,8 @@
 /**
  * Writes an array of double to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -833,6 +912,8 @@
  * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying
  * values to write to the parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData some external representation of an array.
  * \param length the length of arrayData (or -1 if this represents a null array).
@@ -846,6 +927,8 @@
 /**
  * Writes an array of char16_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -858,6 +941,8 @@
 /**
  * Writes an array of int8_t to the next location in a non-null parcel.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to write to.
  * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0).
  * \param length the length of arrayData or -1 if this represents a null array.
@@ -874,6 +959,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -890,6 +977,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -906,6 +995,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -922,6 +1013,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -938,6 +1031,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -954,6 +1049,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -969,6 +1066,8 @@
  * First, allocator will be called with the length of the array. Then, for every i in [0, length),
  * setter(arrayData, i, x) will be called where x is the value at the associated index.
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -988,6 +1087,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1004,6 +1105,8 @@
  * length is greater than zero, the buffer returned by the allocator will be filled with the
  * corresponding data
  *
+ * Available since API level 29.
+ *
  * \param parcel the parcel to read from.
  * \param arrayData some external representation of an array.
  * \param allocator the callback that will be called to allocate the array.
@@ -1015,7 +1118,7 @@
 
 // @END-PRIMITIVE-READ-WRITE
 
-#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
+#endif  //__ANDROID_API__ >= 29
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index f3bc31b..7871667 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -441,6 +441,42 @@
 }
 
 /**
+ * Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
+ * to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeStdVectorParcelableElement<ScopedFileDescriptor>(
+        AParcel* parcel, const void* vectorData, size_t index) {
+    const std::vector<ScopedFileDescriptor>* vector =
+            static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData);
+    int writeFd = vector->at(index).get();
+    if (writeFd < 0) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+    return AParcel_writeParcelFileDescriptor(parcel, writeFd);
+}
+
+/**
+ * Reads a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
+ * from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readStdVectorParcelableElement<ScopedFileDescriptor>(
+        const AParcel* parcel, void* vectorData, size_t index) {
+    std::vector<ScopedFileDescriptor>* vector =
+            static_cast<std::vector<ScopedFileDescriptor>*>(vectorData);
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        if (readFd < 0) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+        vector->at(index).set(readFd);
+    }
+    return status;
+}
+
+/**
  * Convenience API for writing a std::vector<P>
  */
 template <typename P>
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 2671b9b..78d70f8 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -30,7 +30,7 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if __ANDROID_API__ >= 29
 
 enum {
     STATUS_OK = 0,
@@ -105,6 +105,8 @@
 /**
  * New status which is considered a success.
  *
+ * Available since API level 29.
+ *
  * \return a newly constructed status object that the caller owns.
  */
 __attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
@@ -112,6 +114,8 @@
 /**
  * New status with exception code.
  *
+ * Available since API level 29.
+ *
  * \param exception the code that this status should represent. If this is EX_NONE, then this
  * constructs an non-error status object.
  *
@@ -123,6 +127,8 @@
 /**
  * New status with exception code and message.
  *
+ * Available since API level 29.
+ *
  * \param exception the code that this status should represent. If this is EX_NONE, then this
  * constructs an non-error status object.
  * \param message the error message to associate with this status object.
@@ -137,6 +143,8 @@
  *
  * This is considered to be EX_TRANSACTION_FAILED with extra information.
  *
+ * Available since API level 29.
+ *
  * \param serviceSpecific an implementation defined error code.
  *
  * \return a newly constructed status object that the caller owns.
@@ -149,6 +157,8 @@
  *
  * This is considered to be EX_TRANSACTION_FAILED with extra information.
  *
+ * Available since API level 29.
+ *
  * \param serviceSpecific an implementation defined error code.
  * \param message the error message to associate with this status object.
  *
@@ -162,6 +172,8 @@
  * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
  * an AStatus instance.
  *
+ * Available since API level 29.
+ *
  * \param a low-level error to associate with this status object.
  *
  * \return a newly constructed status object that the caller owns.
@@ -173,6 +185,8 @@
  * Whether this object represents a successful transaction. If this function returns true, then
  * AStatus_getExceptionCode will return EX_NONE.
  *
+ * Available since API level 29.
+ *
  * \param status the status being queried.
  *
  * \return whether the status represents a successful transaction. For more details, see below.
@@ -182,6 +196,8 @@
 /**
  * The exception that this status object represents.
  *
+ * Available since API level 29.
+ *
  * \param status the status being queried.
  *
  * \return the exception code that this object represents.
@@ -194,6 +210,8 @@
  * 0, the status object may still represent a different exception or status. To find out if this
  * transaction as a whole is okay, use AStatus_isOk instead.
  *
+ * Available since API level 29.
+ *
  * \param status the status being queried.
  *
  * \return the service-specific error code if the exception code is EX_SERVICE_SPECIFIC or 0.
@@ -206,6 +224,8 @@
  * object may represent a different exception or a service specific error. To find out if this
  * transaction as a whole is okay, use AStatus_isOk instead.
  *
+ * Available since API level 29.
+ *
  * \param status the status being queried.
  *
  * \return the status code if the exception code is EX_TRANSACTION_FAILED or 0.
@@ -218,6 +238,8 @@
  *
  * The returned string has the lifetime of the status object passed into this function.
  *
+ * Available since API level 29.
+ *
  * \param status the status being queried.
  *
  * \return the message associated with this error.
@@ -227,11 +249,13 @@
 /**
  * Deletes memory associated with the status instance.
  *
+ * Available since API level 29.
+ *
  * \param status the status to delete, returned from AStatus_newOk or one of the AStatus_from* APIs.
  */
 void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= __ANDROID_API_Q__
+#endif  //__ANDROID_API__ >= 29
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index e1a8cfd..56d95a7 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -30,7 +30,8 @@
     FLAG_PRIVATE_VENDOR = 0x10000000,
 };
 
-#if (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
+        (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
 
 enum {
     FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
@@ -45,7 +46,8 @@
     AIBinder_markVendorStability(binder);
 }
 
-#else  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#else  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+       // !defined(__ANDROID_APEX__))
 
 enum {
     FLAG_PRIVATE_LOCAL = 0,
@@ -54,13 +56,16 @@
 /**
  * This interface has the stability of the system image.
  */
-void AIBinder_markSystemStability(AIBinder* binder);
+__attribute__((weak)) void AIBinder_markSystemStability(AIBinder* binder);
 
 static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) {
+    if (AIBinder_markSystemStability == nullptr) return;
+
     AIBinder_markSystemStability(binder);
 }
 
-#endif  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#endif  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+        // !defined(__ANDROID_APEX__))
 
 /**
  * This interface has system<->vendor stability
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d4d5387..d59d6e4 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,12 +89,12 @@
     AStatus_getStatus;
     AStatus_isOk;
     AStatus_newOk;
-    ABinderProcess_joinThreadPool; # apex vndk
-    ABinderProcess_setThreadPoolMaxThreadCount; # apex vndk
-    ABinderProcess_startThreadPool; # apex vndk
-    AServiceManager_addService; # apex vndk
-    AServiceManager_checkService; # apex vndk
-    AServiceManager_getService; # apex vndk
+    ABinderProcess_joinThreadPool; # apex llndk
+    ABinderProcess_setThreadPoolMaxThreadCount; # apex llndk
+    ABinderProcess_startThreadPool; # apex llndk
+    AServiceManager_addService; # apex llndk
+    AServiceManager_checkService; # apex llndk
+    AServiceManager_getService; # apex llndk
   local:
     *;
 };
@@ -105,8 +105,8 @@
     AIBinder_setExtension;
 
     AIBinder_markSystemStability; # apex
-    AIBinder_markVendorStability; # vndk
-    AIBinder_markVintfStability; # apex vndk
+    AIBinder_markVendorStability; # llndk
+    AIBinder_markVintfStability; # apex llndk
   local:
     *;
 };
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index ae2276e..f18e118 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -50,7 +50,7 @@
     if (length < -1) return STATUS_BAD_VALUE;
 
     if (!isNullArray && length < 0) {
-        LOG(ERROR) << __func__ << ": null array must be used with length == -1.";
+        LOG(ERROR) << __func__ << ": non-null array but length is " << length;
         return STATUS_BAD_VALUE;
     }
     if (isNullArray && length > 0) {
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
deleted file mode 100755
index 698d291..0000000
--- a/libs/binder/ndk/scripts/format.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-
-echo "Formatting code"
-
-bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
-clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index 1c5dba3..ebd08b2 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -77,6 +77,7 @@
     static_libs: [
         "IBinderVendorDoubleLoadTest-cpp",
         "IBinderVendorDoubleLoadTest-ndk_platform",
+        "libbinder_aidl_test_stub-ndk_platform",
     ],
     shared_libs: [
         "libbase",
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
index f72dc36..d3ccdc2 100644
--- a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
+++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
@@ -16,6 +16,7 @@
 
 #include <BnBinderVendorDoubleLoadTest.h>
 #include <aidl/BnBinderVendorDoubleLoadTest.h>
+#include <aidl/android/os/IServiceManager.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
@@ -109,6 +110,24 @@
     }
 }
 
+TEST(DoubleBinder, CallIntoSystemStabilityNdk) {
+    // picking an arbitrary system service
+    SpAIBinder binder = SpAIBinder(AServiceManager_checkService("manager"));
+    ASSERT_NE(nullptr, binder.get());
+
+    // can make stable transaction to system server
+    EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+
+    using aidl::android::os::IServiceManager;
+    std::shared_ptr<IServiceManager> manager = IServiceManager::fromBinder(binder);
+    ASSERT_NE(nullptr, manager.get());
+
+    std::vector<std::string> services;
+    ASSERT_EQ(
+            STATUS_BAD_TYPE,
+            manager->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &services).getStatus());
+}
+
 void initDrivers() {
     // Explicitly instantiated with the same driver that system would use.
     // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
deleted file mode 100755
index 1eba892..0000000
--- a/libs/binder/ndk/update.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-set -ex
-
-# This script makes sure that the source code is in sync with the various scripts
-./scripts/gen_parcel_helper.py
-./scripts/format.sh
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 635ea69..5a7f9a9 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -119,12 +119,7 @@
     srcs: ["binderSafeInterfaceTest.cpp"],
 
     cppflags: [
-        "-Weverything",
-        "-Wno-c++98-compat",
-        "-Wno-c++98-compat-pedantic",
-        "-Wno-global-constructors",
-        "-Wno-padded",
-        "-Wno-weak-vtables",
+        "-Wextra",
     ],
 
     cpp_std: "experimental",
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 0bee56c..1f2779a 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -134,18 +134,15 @@
 TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) {
     sp<IBinder> vintfServer = BadStableBinder::vintf();
 
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("."), vintfServer));
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("/"), vintfServer));
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("/."), vintfServer));
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("a.d.IFoo"), vintfServer));
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("foo"), vintfServer));
-    EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
-        android::defaultServiceManager()->addService(String16("a.d.IFoo/foo"), vintfServer));
+    for (const char* instance8 : {
+        ".", "/", "/.", "a.d.IFoo", "foo", "a.d.IFoo/foo"
+    }) {
+        String16 instance (instance8);
+
+        EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
+            android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8;
+        EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8;
+    }
 }
 
 TEST(BinderStability, CantCallVendorBinderInSystemContext) {
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 40f6b43..250f902 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -46,6 +46,8 @@
 static const char* hal_interfaces_to_dump[] {
         "android.hardware.audio@2.0::IDevicesFactory",
         "android.hardware.audio@4.0::IDevicesFactory",
+        "android.hardware.audio@5.0::IDevicesFactory",
+        "android.hardware.biometrics.face@1.0::IBiometricsFace",
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
         "android.hardware.drm@1.0::IDrmFactory",
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 24b6c2d..bb9e263 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -213,7 +213,8 @@
         case GraphicsEnv::Driver::GL:
         case GraphicsEnv::Driver::GL_UPDATED:
         case GraphicsEnv::Driver::ANGLE: {
-            if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.glDriverToLoad == GraphicsEnv::Driver::NONE ||
+                mGpuStats.glDriverToLoad == GraphicsEnv::Driver::GL) {
                 mGpuStats.glDriverToLoad = driver;
                 break;
             }
@@ -225,7 +226,8 @@
         }
         case Driver::VULKAN:
         case Driver::VULKAN_UPDATED: {
-            if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE) {
+            if (mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::NONE ||
+                mGpuStats.vkDriverToLoad == GraphicsEnv::Driver::VULKAN) {
                 mGpuStats.vkDriverToLoad = driver;
                 break;
             }
@@ -267,14 +269,14 @@
     return interface_cast<IGpuService>(binder);
 }
 
-void GraphicsEnv::setCpuVulkanInUse() {
+void GraphicsEnv::setTargetStats(const Stats stats, const uint64_t value) {
     ATRACE_CALL();
 
-    // Use the same stats lock to protect getGpuService() as well.
     std::lock_guard<std::mutex> lock(mStatsLock);
     const sp<IGpuService> gpuService = getGpuService();
     if (gpuService) {
-        gpuService->setCpuVulkanInUse(mGpuStats.appPackageName, mGpuStats.driverVersionCode);
+        gpuService->setTargetStats(mGpuStats.appPackageName, mGpuStats.driverVersionCode, stats,
+                                   value);
     }
 }
 
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 5f96249..db16f3c 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -92,15 +92,17 @@
         return reply.readParcelableVector(outStats);
     }
 
-    virtual void setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) {
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GraphicsEnv::Stats stats, const uint64_t value) {
         Parcel data, reply;
         data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
 
         data.writeUtf8AsUtf16(appPackageName);
         data.writeUint64(driverVersionCode);
+        data.writeInt32(static_cast<int32_t>(stats));
+        data.writeUint64(value);
 
-        remote()->transact(BnGpuService::SET_CPU_VULKAN_IN_USE, data, &reply, IBinder::FLAG_ONEWAY);
+        remote()->transact(BnGpuService::SET_TARGET_STATS, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -174,7 +176,7 @@
 
             return OK;
         }
-        case SET_CPU_VULKAN_IN_USE: {
+        case SET_TARGET_STATS: {
             CHECK_INTERFACE(IGpuService, data, reply);
 
             std::string appPackageName;
@@ -183,7 +185,14 @@
             uint64_t driverVersionCode;
             if ((status = data.readUint64(&driverVersionCode)) != OK) return status;
 
-            setCpuVulkanInUse(appPackageName, driverVersionCode);
+            int32_t stats;
+            if ((status = data.readInt32(&stats)) != OK) return status;
+
+            uint64_t value;
+            if ((status = data.readUint64(&value)) != OK) return status;
+
+            setTargetStats(appPackageName, driverVersionCode,
+                           static_cast<GraphicsEnv::Stats>(stats), value);
 
             return OK;
         }
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index f5d19db..937bcd9 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -43,6 +43,10 @@
         ANGLE = 5,
     };
 
+    enum Stats {
+        CPU_VULKAN_IN_USE = 0,
+    };
+
 private:
     struct GpuStats {
         std::string driverPackageName;
@@ -96,7 +100,7 @@
     void setGpuStats(const std::string& driverPackageName, const std::string& driverVersionName,
                      uint64_t versionCode, int64_t driverBuildTime,
                      const std::string& appPackageName, const int32_t vulkanVersion);
-    void setCpuVulkanInUse();
+    void setTargetStats(const Stats stats, const uint64_t value = 0);
     void setDriverToLoad(Driver driver);
     void setDriverLoaded(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
     void sendGpuStatsLocked(Api api, bool isDriverLoaded, int64_t driverLoadingTime);
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index 34f1c7e..b8d0bd1 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -40,9 +40,9 @@
                              const int32_t vulkanVersion, GraphicsEnv::Driver driver,
                              bool isDriverLoaded, int64_t driverLoadingTime) = 0;
 
-    // set CPU Vulkan in use signal from GraphicsEnvironment.
-    virtual void setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) = 0;
+    // set target stats.
+    virtual void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GraphicsEnv::Stats stats, const uint64_t value = 0) = 0;
 
     // get GPU global stats from GpuStats module.
     virtual status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const = 0;
@@ -57,7 +57,7 @@
         SET_GPU_STATS = IBinder::FIRST_CALL_TRANSACTION,
         GET_GPU_STATS_GLOBAL_INFO,
         GET_GPU_STATS_APP_INFO,
-        SET_CPU_VULKAN_IN_USE,
+        SET_TARGET_STATS,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 59cb8e0..166775b 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -15,6 +15,18 @@
     name: "libgui_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
+
+    // we must build this module to get the required header as that is generated
+    export_shared_lib_headers: [
+        "android.hidl.token@1.0-utils",
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+    ],
+    shared_libs: [
+        "android.hidl.token@1.0-utils",
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.bufferqueue@2.0",
+    ],
 }
 
 cc_library_shared {
@@ -34,6 +46,7 @@
         "BufferItemConsumer.cpp",
         "ConsumerBase.cpp",
         "CpuConsumer.cpp",
+        "DebugEGLImageTracker.cpp",
         "DisplayEventReceiver.cpp",
         "GLConsumer.cpp",
         "GuiConfig.cpp",
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9c311a3..92ab410 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -936,6 +936,15 @@
                     }
                 }
 
+                // Make sure to merge the damage rect from the frame we're about
+                // to drop into the new frame's damage rect.
+                if (last.mSurfaceDamage.bounds() == Rect::INVALID_RECT ||
+                    item.mSurfaceDamage.bounds() == Rect::INVALID_RECT) {
+                    item.mSurfaceDamage = Region::INVALID_REGION;
+                } else {
+                    item.mSurfaceDamage |= last.mSurfaceDamage;
+                }
+
                 // Overwrite the droppable buffer with the incoming one
                 mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                 frameReplacedListener = mCore->mConsumerListener;
diff --git a/libs/gui/DebugEGLImageTracker.cpp b/libs/gui/DebugEGLImageTracker.cpp
new file mode 100644
index 0000000..ab6f364
--- /dev/null
+++ b/libs/gui/DebugEGLImageTracker.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+#include <gui/DebugEGLImageTracker.h>
+
+#include <cinttypes>
+#include <unordered_map>
+
+using android::base::StringAppendF;
+
+std::mutex DebugEGLImageTracker::mInstanceLock;
+std::atomic<DebugEGLImageTracker *> DebugEGLImageTracker::mInstance;
+
+class DebugEGLImageTrackerNoOp : public DebugEGLImageTracker {
+public:
+    DebugEGLImageTrackerNoOp() = default;
+    ~DebugEGLImageTrackerNoOp() override = default;
+    void create(const char * /*from*/) override {}
+    void destroy(const char * /*from*/) override {}
+
+    void dump(std::string & /*result*/) override {}
+};
+
+class DebugEGLImageTrackerImpl : public DebugEGLImageTracker {
+public:
+    DebugEGLImageTrackerImpl() = default;
+    ~DebugEGLImageTrackerImpl() override = default;
+    void create(const char * /*from*/) override;
+    void destroy(const char * /*from*/) override;
+
+    void dump(std::string & /*result*/) override;
+
+private:
+    std::mutex mLock;
+    std::unordered_map<std::string, int64_t> mCreateTracker;
+    std::unordered_map<std::string, int64_t> mDestroyTracker;
+
+    int64_t mTotalCreated = 0;
+    int64_t mTotalDestroyed = 0;
+};
+
+DebugEGLImageTracker *DebugEGLImageTracker::getInstance() {
+    std::lock_guard lock(mInstanceLock);
+    if (mInstance == nullptr) {
+        char value[PROPERTY_VALUE_MAX];
+        property_get("debug.sf.enable_egl_image_tracker", value, "0");
+        const bool enabled = static_cast<bool>(atoi(value));
+
+        if (enabled) {
+            mInstance = new DebugEGLImageTrackerImpl();
+        } else {
+            mInstance = new DebugEGLImageTrackerNoOp();
+        }
+    }
+
+    return mInstance;
+}
+
+void DebugEGLImageTrackerImpl::create(const char *from) {
+    std::lock_guard lock(mLock);
+    mCreateTracker[from]++;
+    mTotalCreated++;
+}
+
+void DebugEGLImageTrackerImpl::destroy(const char *from) {
+    std::lock_guard lock(mLock);
+    mDestroyTracker[from]++;
+    mTotalDestroyed++;
+}
+
+void DebugEGLImageTrackerImpl::dump(std::string &result) {
+    std::lock_guard lock(mLock);
+    StringAppendF(&result, "Live EGL Image objects: %" PRIi64 "\n",
+                  mTotalCreated - mTotalDestroyed);
+    StringAppendF(&result, "Total EGL Image created: %" PRIi64 "\n", mTotalCreated);
+    for (const auto &[from, count] : mCreateTracker) {
+        StringAppendF(&result, "\t%s: %" PRIi64 "\n", from.c_str(), count);
+    }
+    StringAppendF(&result, "Total EGL Image destroyed: %" PRIi64 "\n", mTotalDestroyed);
+    for (const auto &[from, count] : mDestroyTracker) {
+        StringAppendF(&result, "\t%s: %" PRIi64 "\n", from.c_str(), count);
+    }
+}
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f5cf1c4..b8faa2d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -32,10 +32,11 @@
 
 // ---------------------------------------------------------------------------
 
-DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
+DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
+                                           ISurfaceComposer::ConfigChanged configChanged) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     if (sf != nullptr) {
-        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
+        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
         if (mEventConnection != nullptr) {
             mDataChannel = std::make_unique<gui::BitTube>();
             mEventConnection->stealReceiveChannel(mDataChannel.get());
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 8d66154..8199c98 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -34,6 +34,7 @@
 #include <math/mat4.h>
 
 #include <gui/BufferItem.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <gui/GLConsumer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
@@ -944,6 +945,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("~EglImage: eglDestroyImageKHR failed");
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         eglTerminate(mEglDisplay);
     }
 }
@@ -957,6 +959,7 @@
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         eglTerminate(mEglDisplay);
         mEglImage = EGL_NO_IMAGE_KHR;
         mEglDisplay = EGL_NO_DISPLAY;
@@ -1006,7 +1009,10 @@
         EGLint error = eglGetError();
         ALOGE("error creating EGLImage: %#x", error);
         eglTerminate(dpy);
+    } else {
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
     }
+
     return image;
 }
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 9590df7..12deaf0 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -278,8 +278,8 @@
         return NO_ERROR;
     }
 
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource)
-    {
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
+                                                                     ConfigChanged configChanged) {
         Parcel data, reply;
         sp<IDisplayEventConnection> result;
         int err = data.writeInterfaceToken(
@@ -288,6 +288,7 @@
             return result;
         }
         data.writeInt32(static_cast<int32_t>(vsyncSource));
+        data.writeInt32(static_cast<int32_t>(configChanged));
         err = remote()->transact(
                 BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
                 data, &reply);
@@ -1155,8 +1156,11 @@
         }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IDisplayEventConnection> connection(createDisplayEventConnection(
-                    static_cast<ISurfaceComposer::VsyncSource>(data.readInt32())));
+            auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
+            auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
+
+            sp<IDisplayEventConnection> connection(
+                    createDisplayEventConnection(vsyncSource, configChanged));
             reply->writeStrongBinder(IInterface::asBinder(connection));
             return NO_ERROR;
         }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e6eb327..9fe5de8 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1920,7 +1920,8 @@
     return OK;
 }
 
-status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
+status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer,
+                                                    Dataspace dataspace) {
     if (buffer == nullptr) {
         return BAD_VALUE;
     }
@@ -1929,6 +1930,11 @@
     if (err != OK) {
         return err;
     }
+    ui::Dataspace tmpDataspace = surface->getBuffersDataSpace();
+    err = surface->setBuffersDataSpace(dataspace);
+    if (err != OK) {
+        return err;
+    }
     err = surface->attachBuffer(buffer->getNativeBuffer());
     if (err != OK) {
         return err;
@@ -1937,6 +1943,10 @@
     if (err != OK) {
         return err;
     }
+    err = surface->setBuffersDataSpace(tmpDataspace);
+    if (err != OK) {
+        return err;
+    }
     err = surface->disconnect(NATIVE_WINDOW_API_CPU);
     return err;
 }
diff --git a/libs/gui/include/gui/DebugEGLImageTracker.h b/libs/gui/include/gui/DebugEGLImageTracker.h
new file mode 100644
index 0000000..5d369c9
--- /dev/null
+++ b/libs/gui/include/gui/DebugEGLImageTracker.h
@@ -0,0 +1,44 @@
+/*
+ * 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 <atomic>
+#include <mutex>
+#include <string>
+
+class DebugEGLImageTracker {
+public:
+    static DebugEGLImageTracker *getInstance();
+
+    virtual void create(const char *from) = 0;
+    virtual void destroy(const char *from) = 0;
+
+    virtual void dump(std::string &result) = 0;
+
+protected:
+    DebugEGLImageTracker() = default;
+    virtual ~DebugEGLImageTracker() = default;
+    DebugEGLImageTracker(const DebugEGLImageTracker &) = delete;
+
+    static std::mutex mInstanceLock;
+    static std::atomic<DebugEGLImageTracker *> mInstance;
+};
+
+#define DEBUG_EGL_IMAGE_TRACKER_CREATE() \
+    (DebugEGLImageTracker::getInstance()->create(__PRETTY_FUNCTION__))
+#define DEBUG_EGL_IMAGE_TRACKER_DESTROY() \
+    (DebugEGLImageTracker::getInstance()->destroy(__PRETTY_FUNCTION__))
\ No newline at end of file
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 22de751..a558cf9 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -88,10 +88,13 @@
      * DisplayEventReceiver creates and registers an event connection with
      * SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
      * or requestNextVsync to receive them.
+     * To receive Config Changed events specify this in the constructor.
      * Other events start being delivered immediately.
      */
     explicit DisplayEventReceiver(
-            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
+            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress);
 
     /*
      * ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e2f7736..c84910b 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -90,6 +90,8 @@
         eVsyncSourceSurfaceFlinger = 1
     };
 
+    enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };
+
     /*
      * Create a connection with SurfaceFlinger.
      */
@@ -97,7 +99,8 @@
 
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            VsyncSource vsyncSource = eVsyncSourceApp) = 0;
+            VsyncSource vsyncSource = eVsyncSourceApp,
+            ConfigChanged configChanged = eConfigChangedSuppress) = 0;
 
     /* create a virtual display
      * requires ACCESS_SURFACE_FLINGER permission.
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 0c471bb..5c6a1ee 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -292,7 +292,8 @@
 
     ui::Dataspace getBuffersDataSpace();
 
-    static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
+    static status_t attachAndQueueBufferWithDataspace(Surface* surface, sp<GraphicBuffer> buffer,
+                                                      ui::Dataspace dataspace);
 
 protected:
     enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index ff1ba0a..386f731 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -410,6 +410,19 @@
     bgSurface->expectTap(1, 1);
 }
 
+TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
+    std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+    // In case we pass the very big inset without any checking.
+    fgSurface->mInputInfo.surfaceInset = INT32_MAX;
+    fgSurface->showAt(100, 100);
+
+    fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
+
+    // expect no crash for overflow, and inset size to be clamped to surface size
+    injectTap(202, 202);
+    fgSurface->expectTap(1, 1);
+}
+
 // Ensure we ignore transparent region when getting screen bounds when positioning input frame.
 TEST_F(InputSurfacesTest, input_ignores_transparent_region) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 960cf18..d370858 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -548,8 +548,8 @@
     }
 
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
-    sp<IDisplayEventConnection> createDisplayEventConnection(ISurfaceComposer::VsyncSource)
-            override {
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override {
         return nullptr;
     }
     sp<IBinder> createDisplay(const String8& /*displayName*/,
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 27ab482..55400c7 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -85,6 +85,11 @@
     export_header_lib_headers: [
         "libnativebase_headers",
     ],
+
+    stubs: {
+        symbol_file: "libnativewindow.map.txt",
+        versions: ["29"],
+    },
 }
 
 llndk_library {
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index da959e3..ae5e47b 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -342,6 +342,8 @@
  * not compatible with its usage flags, the results are undefined and
  * may include program termination.
  *
+ * Available since API level 26.
+ *
  * \return 0 on success, or an error number of the allocation fails for
  * any reason. The returned buffer has a reference count of 1.
  */
@@ -352,18 +354,24 @@
  *
  * This prevents the object from being deleted until the last reference
  * is removed.
+ *
+ * Available since API level 26.
  */
 void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 
 /**
  * Remove a reference that was previously acquired with
  * AHardwareBuffer_acquire() or AHardwareBuffer_allocate().
+ *
+ * Available since API level 26.
  */
 void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
 
 /**
  * Return a description of the AHardwareBuffer in the passed
  * AHardwareBuffer_Desc struct.
+ *
+ * Available since API level 26.
  */
 void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
         AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
@@ -413,6 +421,8 @@
  * simultaneously, and the contents of the buffer behave like shared
  * memory.
  *
+ * Available since API level 26.
+ *
  * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
  * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
  * has more than one layer. Error number if the lock fails for any other
@@ -441,6 +451,8 @@
  *
  * See the AHardwareBuffer_lock documentation for all other locking semantics.
  *
+ * Available since API level 29.
+ *
  * \return 0 on success. -EINVAL if \a buffer is NULL, the usage flags
  * are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or the buffer
  * has more than one layer. Error number if the lock fails for any other
@@ -462,6 +474,8 @@
  * completed before the function returned and no further operations are
  * necessary.
  *
+ * Available since API level 26.
+ *
  * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
  * the unlock fails for any reason.
  */
@@ -470,6 +484,8 @@
 /**
  * Send the AHardwareBuffer to an AF_UNIX socket.
  *
+ * Available since API level 26.
+ *
  * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
  * number if the operation fails for any reason.
  */
@@ -478,6 +494,8 @@
 /**
  * Receive an AHardwareBuffer from an AF_UNIX socket.
  *
+ * Available since API level 26.
+ *
  * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
  * number if the operation fails for any reason.
  */
@@ -501,6 +519,8 @@
  * some implementations have implementation-defined limits on texture
  * size and layer count.
  *
+ * Available since API level 29.
+ *
  * \return 1 if the format and usage flag combination is allocatable,
  *     0 otherwise.
  */
@@ -514,6 +534,8 @@
  * of the locked buffer.  If the bytes per pixel or bytes per stride are unknown
  * or variable, or if the underlying mapper implementation does not support returning
  * additional information, then this call will fail with INVALID_OPERATION
+ *
+ * Available since API level 29.
  */
 int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
         int32_t fence, const ARect* rect, void** outVirtualAddress,
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 6730596..3e436e3 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -189,6 +189,8 @@
 /**
  * Set a transform that will be applied to future buffers posted to the window.
  *
+ * Available since API level 26.
+ *
  * \param transform combination of {@link ANativeWindowTransform} flags
  * \return 0 for success, or -EINVAL if \p transform is invalid
  */
@@ -208,6 +210,8 @@
  * measurement data instead of color images. The default dataSpace is 0,
  * ADATASPACE_UNKNOWN, unless it has been overridden by the producer.
  *
+ * Available since API level 28.
+ *
  * \param dataSpace data space of all buffers queued after this call.
  * \return 0 for success, -EINVAL if window is invalid or the dataspace is not
  * supported.
@@ -216,6 +220,9 @@
 
 /**
  * Get the dataspace of the buffers in window.
+ *
+ * Available since API level 28.
+ *
  * \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
  * dataspace is unknown, or -EINVAL if window is invalid.
  */
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index bad8b11..db1c9b7 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -2,9 +2,9 @@
   global:
     AHardwareBuffer_acquire;
     AHardwareBuffer_allocate;
-    AHardwareBuffer_createFromHandle; # vndk
+    AHardwareBuffer_createFromHandle; # llndk # apex
     AHardwareBuffer_describe;
-    AHardwareBuffer_getNativeHandle; # vndk
+    AHardwareBuffer_getNativeHandle; # llndk # apex
     AHardwareBuffer_isSupported; # introduced=29
     AHardwareBuffer_lock;
     AHardwareBuffer_lockAndGetInfo; # introduced=29
@@ -13,32 +13,32 @@
     AHardwareBuffer_release;
     AHardwareBuffer_sendHandleToUnixSocket;
     AHardwareBuffer_unlock;
-    ANativeWindowBuffer_getHardwareBuffer; # vndk
-    ANativeWindow_OemStorageGet; # vndk
-    ANativeWindow_OemStorageSet; # vndk
+    ANativeWindowBuffer_getHardwareBuffer; # llndk
+    ANativeWindow_OemStorageGet; # llndk
+    ANativeWindow_OemStorageSet; # llndk
     ANativeWindow_acquire;
-    ANativeWindow_cancelBuffer; # vndk
-    ANativeWindow_dequeueBuffer; # vndk
+    ANativeWindow_cancelBuffer; # llndk
+    ANativeWindow_dequeueBuffer; # llndk
     ANativeWindow_getBuffersDataSpace; # introduced=28
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getWidth;
     ANativeWindow_lock;
-    ANativeWindow_query; # vndk
-    ANativeWindow_queryf; # vndk
-    ANativeWindow_queueBuffer; # vndk
+    ANativeWindow_query; # llndk
+    ANativeWindow_queryf; # llndk
+    ANativeWindow_queueBuffer; # llndk
     ANativeWindow_release;
-    ANativeWindow_setAutoRefresh; # vndk
-    ANativeWindow_setBufferCount; # vndk
+    ANativeWindow_setAutoRefresh; # llndk
+    ANativeWindow_setBufferCount; # llndk
     ANativeWindow_setBuffersDataSpace; # introduced=28
-    ANativeWindow_setBuffersDimensions; # vndk
-    ANativeWindow_setBuffersFormat; # vndk
+    ANativeWindow_setBuffersDimensions; # llndk
+    ANativeWindow_setBuffersFormat; # llndk
     ANativeWindow_setBuffersGeometry;
-    ANativeWindow_setBuffersTimestamp; # vndk
+    ANativeWindow_setBuffersTimestamp; # llndk
     ANativeWindow_setBuffersTransform;
-    ANativeWindow_setSharedBufferMode; # vndk
-    ANativeWindow_setSwapInterval; # vndk
-    ANativeWindow_setUsage; # vndk
+    ANativeWindow_setSharedBufferMode; # llndk
+    ANativeWindow_setSwapInterval; # llndk
+    ANativeWindow_setUsage; # llndk
     ANativeWindow_unlockAndPost;
   local:
     *;
diff --git a/libs/nativewindow/tests/AHardwareBufferTest.cpp b/libs/nativewindow/tests/AHardwareBufferTest.cpp
index cc2731d..71b1f9f 100644
--- a/libs/nativewindow/tests/AHardwareBufferTest.cpp
+++ b/libs/nativewindow/tests/AHardwareBufferTest.cpp
@@ -20,6 +20,7 @@
 #include <android/hardware_buffer.h>
 #include <private/android/AHardwareBufferHelpers.h>
 #include <android/hardware/graphics/common/1.0/types.h>
+#include <vndk/hardware_buffer.h>
 
 #include <gtest/gtest.h>
 
@@ -100,9 +101,33 @@
             (uint64_t)BufferUsage::CPU_WRITE_RARELY,
             AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY));
 
-EXPECT_TRUE(TestUsageConversion(
+    EXPECT_TRUE(TestUsageConversion(
         (uint64_t)BufferUsage::GPU_RENDER_TARGET | (uint64_t)BufferUsage::GPU_TEXTURE |
-            1ull << 29 | 1ull << 57,
+        1ull << 29 | 1ull << 57,
         AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
         AHARDWAREBUFFER_USAGE_VENDOR_1 | AHARDWAREBUFFER_USAGE_VENDOR_13));
 }
+
+TEST(AHardwareBufferTest, GetCreateHandleTest) {
+    AHardwareBuffer_Desc desc{
+            .width = 64,
+            .height = 1,
+            .layers = 1,
+            .format = AHARDWAREBUFFER_FORMAT_BLOB,
+            .usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+            .stride = 64,
+    };
+
+    AHardwareBuffer* buffer = nullptr;
+    EXPECT_EQ(0, AHardwareBuffer_allocate(&desc, &buffer));
+    const native_handle_t* handle = AHardwareBuffer_getNativeHandle(buffer);
+    EXPECT_NE(nullptr, handle);
+
+    AHardwareBuffer* otherBuffer = nullptr;
+    EXPECT_EQ(0, AHardwareBuffer_createFromHandle(
+        &desc, handle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &otherBuffer));
+    EXPECT_NE(nullptr, otherBuffer);
+
+    AHardwareBuffer_release(buffer);
+    AHardwareBuffer_release(otherBuffer);
+}
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 36211ca..cc252d6 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -26,6 +26,7 @@
         "libgui",
         "liblog",
         "libnativewindow",
+        "libprocessgroup",
         "libsync",
         "libui",
         "libutils",
@@ -51,6 +52,7 @@
         "gl/GLExtensions.cpp",
         "gl/GLFramebuffer.cpp",
         "gl/GLImage.cpp",
+        "gl/ImageManager.cpp",
         "gl/Program.cpp",
         "gl/ProgramCache.cpp",
     ],
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 46a8e9e..d2a7525 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -19,9 +19,8 @@
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include "GLESRenderEngine.h"
-
-#include <math.h>
+#include <sched.h>
+#include <cmath>
 #include <fstream>
 #include <sstream>
 #include <unordered_set>
@@ -31,6 +30,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
 #include <renderengine/private/Description.h>
@@ -42,6 +42,7 @@
 #include <ui/Region.h>
 #include <utils/KeyedVector.h>
 #include <utils/Trace.h>
+#include "GLESRenderEngine.h"
 #include "GLExtensions.h"
 #include "GLFramebuffer.h"
 #include "GLImage.h"
@@ -422,10 +423,13 @@
         mTraceGpuCompletion = true;
         mFlushTracer = std::make_unique<FlushTracer>(this);
     }
+    mImageManager = std::make_unique<ImageManager>(this);
     mDrawingBuffer = createFramebuffer();
 }
 
 GLESRenderEngine::~GLESRenderEngine() {
+    // Destroy the image manager first.
+    mImageManager = nullptr;
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     unbindFrameBuffer(mDrawingBuffer.get());
     mDrawingBuffer = nullptr;
@@ -433,6 +437,7 @@
         EGLImageKHR expired = mFramebufferImageCache.front().second;
         mFramebufferImageCache.pop_front();
         eglDestroyImageKHR(mEGLDisplay, expired);
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
     }
     mImageCache.clear();
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -614,64 +619,51 @@
     }
 }
 
-status_t GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    return cacheExternalTextureBufferLocked(buffer);
-}
-
 status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
                                                      const sp<GraphicBuffer>& buffer,
                                                      const sp<Fence>& bufferFence) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    return bindExternalTextureBufferLocked(texName, buffer, bufferFence);
-}
-
-status_t GLESRenderEngine::cacheExternalTextureBufferLocked(const sp<GraphicBuffer>& buffer) {
     if (buffer == nullptr) {
         return BAD_VALUE;
     }
 
     ATRACE_CALL();
 
-    if (mImageCache.count(buffer->getId()) > 0) {
-        return NO_ERROR;
+    bool found = false;
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        auto cachedImage = mImageCache.find(buffer->getId());
+        found = (cachedImage != mImageCache.end());
     }
 
-    std::unique_ptr<Image> newImage = createImage();
-
-    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
-                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-    if (!created) {
-        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
-              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
-              buffer->getPixelFormat());
-        return NO_INIT;
-    }
-    mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
-
-    return NO_ERROR;
-}
-
-status_t GLESRenderEngine::bindExternalTextureBufferLocked(uint32_t texName,
-                                                           const sp<GraphicBuffer>& buffer,
-                                                           const sp<Fence>& bufferFence) {
-    ATRACE_CALL();
-    status_t cacheResult = cacheExternalTextureBufferLocked(buffer);
-
-    if (cacheResult != NO_ERROR) {
-        return cacheResult;
+    // If we couldn't find the image in the cache at this time, then either
+    // SurfaceFlinger messed up registering the buffer ahead of time or we got
+    // backed up creating other EGLImages.
+    if (!found) {
+        status_t cacheResult = mImageManager->cache(buffer);
+        if (cacheResult != NO_ERROR) {
+            return cacheResult;
+        }
     }
 
-    auto cachedImage = mImageCache.find(buffer->getId());
+    // Whether or not we needed to cache, re-check mImageCache to make sure that
+    // there's an EGLImage. The current threading model guarantees that we don't
+    // destroy a cached image until it's really not needed anymore (i.e. this
+    // function should not be called), so the only possibility is that something
+    // terrible went wrong and we should just bind something and move on.
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        auto cachedImage = mImageCache.find(buffer->getId());
 
-    if (cachedImage == mImageCache.end()) {
-        // We failed creating the image if we got here, so bail out.
-        bindExternalTextureImage(texName, *createImage());
-        return NO_INIT;
+        if (cachedImage == mImageCache.end()) {
+            // We failed creating the image if we got here, so bail out.
+            ALOGE("Failed to create an EGLImage when rendering");
+            bindExternalTextureImage(texName, *createImage());
+            return NO_INIT;
+        }
+
+        bindExternalTextureImage(texName, *cachedImage->second);
     }
 
-    bindExternalTextureImage(texName, *cachedImage->second);
-
     // Wait for the new buffer to be ready.
     if (bufferFence != nullptr && bufferFence->isValid()) {
         if (GLExtensions::getInstance().hasWaitSync()) {
@@ -696,13 +688,81 @@
     return NO_ERROR;
 }
 
+void GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
+    mImageManager->cacheAsync(buffer, nullptr);
+}
+
+std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::cacheExternalTextureBufferForTesting(
+        const sp<GraphicBuffer>& buffer) {
+    auto barrier = std::make_shared<ImageManager::Barrier>();
+    mImageManager->cacheAsync(buffer, barrier);
+    return barrier;
+}
+
+status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer) {
+    if (buffer == nullptr) {
+        return BAD_VALUE;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        if (mImageCache.count(buffer->getId()) > 0) {
+            // If there's already an image then fail fast here.
+            return NO_ERROR;
+        }
+    }
+    ATRACE_CALL();
+
+    // Create the image without holding a lock so that we don't block anything.
+    std::unique_ptr<Image> newImage = createImage();
+
+    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
+                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+    if (!created) {
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+              buffer->getPixelFormat());
+        return NO_INIT;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        if (mImageCache.count(buffer->getId()) > 0) {
+            // In theory it's possible for another thread to recache the image,
+            // so bail out if another thread won.
+            return NO_ERROR;
+        }
+        mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
+    }
+
+    return NO_ERROR;
+}
+
 void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    const auto& cachedImage = mImageCache.find(bufferId);
-    if (cachedImage != mImageCache.end()) {
-        ALOGV("Destroying image for buffer: %" PRIu64, bufferId);
-        mImageCache.erase(bufferId);
-        return;
+    mImageManager->releaseAsync(bufferId, nullptr);
+}
+
+std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::unbindExternalTextureBufferForTesting(
+        uint64_t bufferId) {
+    auto barrier = std::make_shared<ImageManager::Barrier>();
+    mImageManager->releaseAsync(bufferId, barrier);
+    return barrier;
+}
+
+void GLESRenderEngine::unbindExternalTextureBufferInternal(uint64_t bufferId) {
+    std::unique_ptr<Image> image;
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        const auto& cachedImage = mImageCache.find(bufferId);
+
+        if (cachedImage != mImageCache.end()) {
+            ALOGV("Destroying image for buffer: %" PRIu64, bufferId);
+            // Move the buffer out of cache first, so that we can destroy
+            // without holding the cache's lock.
+            image = std::move(cachedImage->second);
+            mImageCache.erase(bufferId);
+            return;
+        }
     }
     ALOGV("Failed to find image for buffer: %" PRIu64, bufferId);
 }
@@ -842,6 +902,7 @@
                                                              bool useFramebufferCache) {
     sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
     if (useFramebufferCache) {
+        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
         for (const auto& image : mFramebufferImageCache) {
             if (image.first == graphicBuffer->getId()) {
                 return image.second;
@@ -857,14 +918,20 @@
                                           nativeBuffer, attributes);
     if (useFramebufferCache) {
         if (image != EGL_NO_IMAGE_KHR) {
+            std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
             if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
                 EGLImageKHR expired = mFramebufferImageCache.front().second;
                 mFramebufferImageCache.pop_front();
                 eglDestroyImageKHR(mEGLDisplay, expired);
+                DEBUG_EGL_IMAGE_TRACKER_DESTROY();
             }
             mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
         }
     }
+
+    if (image != EGL_NO_IMAGE_KHR) {
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
+    }
     return image;
 }
 
@@ -889,127 +956,123 @@
         return BAD_VALUE;
     }
 
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
+    BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache);
 
-        BindNativeBufferAsFramebuffer fbo(*this, buffer, useFramebufferCache);
-
-        if (fbo.getStatus() != NO_ERROR) {
-            ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
-                  buffer->handle);
-            checkErrors();
-            return fbo.getStatus();
-        }
-
-        // clear the entire buffer, sometimes when we reuse buffers we'd persist
-        // ghost images otherwise.
-        // we also require a full transparent framebuffer for overlays. This is
-        // probably not quite efficient on all GPUs, since we could filter out
-        // opaque layers.
-        clearWithColor(0.0, 0.0, 0.0, 0.0);
-
-        setViewportAndProjection(display.physicalDisplay, display.clip);
-
-        setOutputDataSpace(display.outputDataspace);
-        setDisplayMaxLuminance(display.maxLuminance);
-
-        mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
-        mState.projectionMatrix = projectionMatrix;
-        if (!display.clearRegion.isEmpty()) {
-            glDisable(GL_BLEND);
-            fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
-        }
-
-        Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
-        for (auto layer : layers) {
-            mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
-
-            const FloatRect bounds = layer.geometry.boundaries;
-            Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-            position[0] = vec2(bounds.left, bounds.top);
-            position[1] = vec2(bounds.left, bounds.bottom);
-            position[2] = vec2(bounds.right, bounds.bottom);
-            position[3] = vec2(bounds.right, bounds.top);
-
-            setupLayerCropping(layer, mesh);
-            setColorTransform(display.colorTransform * layer.colorTransform);
-
-            bool usePremultipliedAlpha = true;
-            bool disableTexture = true;
-            bool isOpaque = false;
-
-            if (layer.source.buffer.buffer != nullptr) {
-                disableTexture = false;
-                isOpaque = layer.source.buffer.isOpaque;
-
-                sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
-                bindExternalTextureBufferLocked(layer.source.buffer.textureName, gBuf,
-                                                layer.source.buffer.fence);
-
-                usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
-                Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
-                mat4 texMatrix = layer.source.buffer.textureTransform;
-
-                texture.setMatrix(texMatrix.asArray());
-                texture.setFiltering(layer.source.buffer.useTextureFiltering);
-
-                texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
-                setSourceY410BT2020(layer.source.buffer.isY410BT2020);
-
-                renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
-                texCoords[0] = vec2(0.0, 0.0);
-                texCoords[1] = vec2(0.0, 1.0);
-                texCoords[2] = vec2(1.0, 1.0);
-                texCoords[3] = vec2(1.0, 0.0);
-                setupLayerTexturing(texture);
-            }
-
-            const half3 solidColor = layer.source.solidColor;
-            const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
-            // Buffer sources will have a black solid color ignored in the shader,
-            // so in that scenario the solid color passed here is arbitrary.
-            setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
-                               layer.geometry.roundedCornersRadius);
-            if (layer.disableBlending) {
-                glDisable(GL_BLEND);
-            }
-            setSourceDataSpace(layer.sourceDataspace);
-
-            // We only want to do a special handling for rounded corners when having rounded corners
-            // is the only reason it needs to turn on blending, otherwise, we handle it like the
-            // usual way since it needs to turn on blending anyway.
-            if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
-                handleRoundedCorners(display, layer, mesh);
-            } else {
-                drawMesh(mesh);
-            }
-
-            // Cleanup if there's a buffer source
-            if (layer.source.buffer.buffer != nullptr) {
-                disableBlending();
-                setSourceY410BT2020(false);
-                disableTexturing();
-            }
-        }
-
-        if (drawFence != nullptr) {
-            *drawFence = flush();
-        }
-        // If flush failed or we don't support native fences, we need to force the
-        // gl command stream to be executed.
-        if (drawFence == nullptr || drawFence->get() < 0) {
-            bool success = finish();
-            if (!success) {
-                ALOGE("Failed to flush RenderEngine commands");
-                checkErrors();
-                // Chances are, something illegal happened (either the caller passed
-                // us bad parameters, or we messed up our shader generation).
-                return INVALID_OPERATION;
-            }
-        }
-
+    if (fbo.getStatus() != NO_ERROR) {
+        ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
+              buffer->handle);
         checkErrors();
+        return fbo.getStatus();
     }
+
+    // clear the entire buffer, sometimes when we reuse buffers we'd persist
+    // ghost images otherwise.
+    // we also require a full transparent framebuffer for overlays. This is
+    // probably not quite efficient on all GPUs, since we could filter out
+    // opaque layers.
+    clearWithColor(0.0, 0.0, 0.0, 0.0);
+
+    setViewportAndProjection(display.physicalDisplay, display.clip);
+
+    setOutputDataSpace(display.outputDataspace);
+    setDisplayMaxLuminance(display.maxLuminance);
+
+    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+    mState.projectionMatrix = projectionMatrix;
+    if (!display.clearRegion.isEmpty()) {
+        glDisable(GL_BLEND);
+        fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
+    }
+
+    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
+    for (auto layer : layers) {
+        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
+
+        const FloatRect bounds = layer.geometry.boundaries;
+        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+        position[0] = vec2(bounds.left, bounds.top);
+        position[1] = vec2(bounds.left, bounds.bottom);
+        position[2] = vec2(bounds.right, bounds.bottom);
+        position[3] = vec2(bounds.right, bounds.top);
+
+        setupLayerCropping(layer, mesh);
+        setColorTransform(display.colorTransform * layer.colorTransform);
+
+        bool usePremultipliedAlpha = true;
+        bool disableTexture = true;
+        bool isOpaque = false;
+
+        if (layer.source.buffer.buffer != nullptr) {
+            disableTexture = false;
+            isOpaque = layer.source.buffer.isOpaque;
+
+            sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
+            bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
+                                      layer.source.buffer.fence);
+
+            usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
+            Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
+            mat4 texMatrix = layer.source.buffer.textureTransform;
+
+            texture.setMatrix(texMatrix.asArray());
+            texture.setFiltering(layer.source.buffer.useTextureFiltering);
+
+            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
+            setSourceY410BT2020(layer.source.buffer.isY410BT2020);
+
+            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+            texCoords[0] = vec2(0.0, 0.0);
+            texCoords[1] = vec2(0.0, 1.0);
+            texCoords[2] = vec2(1.0, 1.0);
+            texCoords[3] = vec2(1.0, 0.0);
+            setupLayerTexturing(texture);
+        }
+
+        const half3 solidColor = layer.source.solidColor;
+        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+        // Buffer sources will have a black solid color ignored in the shader,
+        // so in that scenario the solid color passed here is arbitrary.
+        setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
+                           layer.geometry.roundedCornersRadius);
+        if (layer.disableBlending) {
+            glDisable(GL_BLEND);
+        }
+        setSourceDataSpace(layer.sourceDataspace);
+
+        // We only want to do a special handling for rounded corners when having rounded corners
+        // is the only reason it needs to turn on blending, otherwise, we handle it like the
+        // usual way since it needs to turn on blending anyway.
+        if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
+            handleRoundedCorners(display, layer, mesh);
+        } else {
+            drawMesh(mesh);
+        }
+
+        // Cleanup if there's a buffer source
+        if (layer.source.buffer.buffer != nullptr) {
+            disableBlending();
+            setSourceY410BT2020(false);
+            disableTexturing();
+        }
+    }
+
+    if (drawFence != nullptr) {
+        *drawFence = flush();
+    }
+    // If flush failed or we don't support native fences, we need to force the
+    // gl command stream to be executed.
+    if (drawFence == nullptr || drawFence->get() < 0) {
+        bool success = finish();
+        if (!success) {
+            ALOGE("Failed to flush RenderEngine commands");
+            checkErrors();
+            // Chances are, something illegal happened (either the caller passed
+            // us bad parameters, or we messed up our shader generation).
+            return INVALID_OPERATION;
+        }
+    }
+
+    checkErrors();
     return NO_ERROR;
 }
 
@@ -1306,6 +1369,23 @@
     StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
                   dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
                   dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        StringAppendF(&result, "RenderEngine image cache size: %zu\n", mImageCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        for (const auto& [id, unused] : mImageCache) {
+            StringAppendF(&result, "0x%" PRIx64 "\n", id);
+        }
+    }
+    {
+        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
+        StringAppendF(&result, "RenderEngine framebuffer image cache size: %zu\n",
+                      mFramebufferImageCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        for (const auto& [id, unused] : mFramebufferImageCache) {
+            StringAppendF(&result, "0x%" PRIx64 "\n", id);
+        }
+    }
 }
 
 GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
@@ -1432,7 +1512,7 @@
 }
 
 bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
+    std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
     return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
                        [=](std::pair<uint64_t, EGLImageKHR> image) {
                            return image.first == bufferId;
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index de793c2..dd60e50 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -17,9 +17,7 @@
 #ifndef SF_GLESRENDERENGINE_H_
 #define SF_GLESRENDERENGINE_H_
 
-#include <android-base/thread_annotations.h>
 #include <stdint.h>
-#include <sys/types.h>
 #include <condition_variable>
 #include <deque>
 #include <mutex>
@@ -30,8 +28,11 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
+#include <android-base/thread_annotations.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/private/Description.h>
+#include <sys/types.h>
+#include "ImageManager.h"
 
 #define EGL_NO_CONFIG ((EGLConfig)0)
 
@@ -74,7 +75,7 @@
     void bindExternalTextureImage(uint32_t texName, const Image& image) override;
     status_t bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer,
                                        const sp<Fence>& fence) EXCLUDES(mRenderingMutex);
-    status_t cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex);
+    void cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex);
     void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     status_t bindFrameBuffer(Framebuffer* framebuffer) override;
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
@@ -85,25 +86,32 @@
     bool useProtectedContext(bool useProtectedContext) override;
     status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
                         ANativeWindowBuffer* buffer, const bool useFramebufferCache,
-                        base::unique_fd&& bufferFence, base::unique_fd* drawFence)
-            EXCLUDES(mRenderingMutex) override;
+                        base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
 
     // internal to RenderEngine
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
     EGLConfig getEGLConfig() const { return mEGLConfig; }
     // Creates an output image for rendering to
     EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                                               bool useFramebufferCache);
+                                               bool useFramebufferCache)
+            EXCLUDES(mFramebufferImageCacheMutex);
 
     // Test-only methods
     // Returns true iff mImageCache contains an image keyed by bufferId
     bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     // Returns true iff mFramebufferImageCache contains an image keyed by bufferId
-    bool isFramebufferImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
+    bool isFramebufferImageCachedForTesting(uint64_t bufferId)
+            EXCLUDES(mFramebufferImageCacheMutex);
+    // These are wrappers around public methods above, but exposing Barrier
+    // objects so that tests can block.
+    std::shared_ptr<ImageManager::Barrier> cacheExternalTextureBufferForTesting(
+            const sp<GraphicBuffer>& buffer);
+    std::shared_ptr<ImageManager::Barrier> unbindExternalTextureBufferForTesting(uint64_t bufferId);
 
 protected:
     Framebuffer* getFramebufferForDrawing() override;
-    void dump(std::string& result) override;
+    void dump(std::string& result) override EXCLUDES(mRenderingMutex)
+            EXCLUDES(mFramebufferImageCacheMutex);
     void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                   ui::Transform::orientation_flags rotation) override;
     void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
@@ -145,6 +153,9 @@
     void setScissor(const Rect& region);
     void disableScissor();
     bool waitSync(EGLSyncKHR sync, EGLint flags);
+    status_t cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer)
+            EXCLUDES(mRenderingMutex);
+    void unbindExternalTextureBufferInternal(uint64_t bufferId) EXCLUDES(mRenderingMutex);
 
     // A data space is considered HDR data space if it has BT2020 color space
     // with PQ or HLG transfer function.
@@ -200,7 +211,11 @@
     uint32_t mFramebufferImageCacheSize = 0;
 
     // Cache of output images, keyed by corresponding GraphicBuffer ID.
-    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache;
+    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache
+            GUARDED_BY(mFramebufferImageCacheMutex);
+    // The only reason why we have this mutex is so that we don't segfault when
+    // dumping info.
+    std::mutex mFramebufferImageCacheMutex;
 
     // Current dataspace of layer being rendered
     ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
@@ -220,15 +235,6 @@
     // multiple threads is guaranteed thread-safe.
     std::mutex mRenderingMutex;
 
-    // See bindExternalTextureBuffer above, but requiring that mRenderingMutex
-    // is held.
-    status_t bindExternalTextureBufferLocked(uint32_t texName, const sp<GraphicBuffer>& buffer,
-                                             const sp<Fence>& fence) REQUIRES(mRenderingMutex);
-    // See cacheExternalTextureBuffer above, but requiring that mRenderingMutex
-    // is held.
-    status_t cacheExternalTextureBufferLocked(const sp<GraphicBuffer>& buffer)
-            REQUIRES(mRenderingMutex);
-
     std::unique_ptr<Framebuffer> mDrawingBuffer;
 
     class FlushTracer {
@@ -253,7 +259,9 @@
         bool mRunning = true;
     };
     friend class FlushTracer;
+    friend class ImageManager;
     std::unique_ptr<FlushTracer> mFlushTracer;
+    std::unique_ptr<ImageManager> mImageManager = std::make_unique<ImageManager>(this);
 };
 
 } // namespace gl
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index dacf8d3..5fbb5ba 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -22,6 +22,7 @@
 #include <GLES/glext.h>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+#include <gui/DebugEGLImageTracker.h>
 #include <nativebase/nativebase.h>
 #include <utils/Trace.h>
 #include "GLESRenderEngine.h"
@@ -47,6 +48,7 @@
     if (mEGLImage != EGL_NO_IMAGE_KHR) {
         if (!usingFramebufferCache) {
             eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+            DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         }
         mEGLImage = EGL_NO_IMAGE_KHR;
         mBufferWidth = 0;
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
index 77e648e..8497721 100644
--- a/libs/renderengine/gl/GLImage.cpp
+++ b/libs/renderengine/gl/GLImage.cpp
@@ -20,6 +20,7 @@
 
 #include <vector>
 
+#include <gui/DebugEGLImageTracker.h>
 #include <log/log.h>
 #include <utils/Trace.h>
 #include "GLESRenderEngine.h"
@@ -58,6 +59,7 @@
         if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
             ALOGE("failed to destroy image: %#x", eglGetError());
         }
+        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
         mEGLImage = EGL_NO_IMAGE_KHR;
     }
 
@@ -69,6 +71,7 @@
             ALOGE("failed to create EGLImage: %#x", eglGetError());
             return false;
         }
+        DEBUG_EGL_IMAGE_TRACKER_CREATE();
         mProtected = isProtected;
     }
 
diff --git a/libs/renderengine/gl/ImageManager.cpp b/libs/renderengine/gl/ImageManager.cpp
new file mode 100644
index 0000000..5af0e4f
--- /dev/null
+++ b/libs/renderengine/gl/ImageManager.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <pthread.h>
+
+#include <processgroup/sched_policy.h>
+#include <utils/Trace.h>
+#include "GLESRenderEngine.h"
+#include "ImageManager.h"
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+ImageManager::ImageManager(GLESRenderEngine* engine) : mEngine(engine) {
+    pthread_setname_np(mThread.native_handle(), "ImageManager");
+    // Use SCHED_FIFO to minimize jitter
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for ImageManager");
+    }
+}
+
+ImageManager::~ImageManager() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mRunning = false;
+    }
+    mCondition.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void ImageManager::cacheAsync(const sp<GraphicBuffer>& buffer,
+                              const std::shared_ptr<Barrier>& barrier) {
+    if (buffer == nullptr) {
+        {
+            std::lock_guard<std::mutex> lock(barrier->mutex);
+            barrier->isOpen = true;
+            barrier->result = BAD_VALUE;
+        }
+        barrier->condition.notify_one();
+        return;
+    }
+    ATRACE_CALL();
+    QueueEntry entry = {QueueEntry::Operation::Insert, buffer, buffer->getId(), barrier};
+    queueOperation(std::move(entry));
+}
+
+status_t ImageManager::cache(const sp<GraphicBuffer>& buffer) {
+    ATRACE_CALL();
+    auto barrier = std::make_shared<Barrier>();
+    cacheAsync(buffer, barrier);
+    std::lock_guard<std::mutex> lock(barrier->mutex);
+    barrier->condition.wait(barrier->mutex,
+                            [&]() REQUIRES(barrier->mutex) { return barrier->isOpen; });
+    return barrier->result;
+}
+
+void ImageManager::releaseAsync(uint64_t bufferId, const std::shared_ptr<Barrier>& barrier) {
+    ATRACE_CALL();
+    QueueEntry entry = {QueueEntry::Operation::Delete, nullptr, bufferId, barrier};
+    queueOperation(std::move(entry));
+}
+
+void ImageManager::queueOperation(const QueueEntry&& entry) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mQueue.emplace(entry);
+        ATRACE_INT("ImageManagerQueueDepth", mQueue.size());
+    }
+    mCondition.notify_one();
+}
+
+void ImageManager::threadMain() {
+    set_sched_policy(0, SP_FOREGROUND);
+    bool run;
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        run = mRunning;
+    }
+    while (run) {
+        QueueEntry entry;
+        {
+            std::lock_guard<std::mutex> lock(mMutex);
+            mCondition.wait(mMutex,
+                            [&]() REQUIRES(mMutex) { return !mQueue.empty() || !mRunning; });
+            run = mRunning;
+
+            if (!mRunning) {
+                // if mRunning is false, then ImageManager is being destroyed, so
+                // bail out now.
+                break;
+            }
+
+            entry = mQueue.front();
+            mQueue.pop();
+            ATRACE_INT("ImageManagerQueueDepth", mQueue.size());
+        }
+
+        status_t result = NO_ERROR;
+        switch (entry.op) {
+            case QueueEntry::Operation::Delete:
+                mEngine->unbindExternalTextureBufferInternal(entry.bufferId);
+                break;
+            case QueueEntry::Operation::Insert:
+                result = mEngine->cacheExternalTextureBufferInternal(entry.buffer);
+                break;
+        }
+        if (entry.barrier != nullptr) {
+            {
+                std::lock_guard<std::mutex> entryLock(entry.barrier->mutex);
+                entry.barrier->result = result;
+                entry.barrier->isOpen = true;
+            }
+            entry.barrier->condition.notify_one();
+        }
+    }
+}
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/gl/ImageManager.h b/libs/renderengine/gl/ImageManager.h
new file mode 100644
index 0000000..b5ba554
--- /dev/null
+++ b/libs/renderengine/gl/ImageManager.h
@@ -0,0 +1,70 @@
+/*
+ * 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 <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLESRenderEngine;
+
+class ImageManager {
+public:
+    struct Barrier {
+        std::mutex mutex;
+        std::condition_variable_any condition;
+        bool isOpen GUARDED_BY(mutex) = false;
+        status_t result GUARDED_BY(mutex) = NO_ERROR;
+    };
+    ImageManager(GLESRenderEngine* engine);
+    ~ImageManager();
+    void cacheAsync(const sp<GraphicBuffer>& buffer, const std::shared_ptr<Barrier>& barrier)
+            EXCLUDES(mMutex);
+    status_t cache(const sp<GraphicBuffer>& buffer);
+    void releaseAsync(uint64_t bufferId, const std::shared_ptr<Barrier>& barrier) EXCLUDES(mMutex);
+
+private:
+    struct QueueEntry {
+        enum class Operation { Delete, Insert };
+
+        Operation op = Operation::Delete;
+        sp<GraphicBuffer> buffer = nullptr;
+        uint64_t bufferId = 0;
+        std::shared_ptr<Barrier> barrier = nullptr;
+    };
+
+    void queueOperation(const QueueEntry&& entry);
+    void threadMain();
+    GLESRenderEngine* const mEngine;
+    std::thread mThread = std::thread([this]() { threadMain(); });
+    std::condition_variable_any mCondition;
+    std::mutex mMutex;
+    std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
+
+    bool mRunning GUARDED_BY(mMutex) = true;
+};
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index e707004..c6a7bd8 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -116,10 +116,20 @@
                                                const sp<Fence>& fence) = 0;
     // Caches Image resources for this buffer, but does not bind the buffer to
     // a particular texture.
-    virtual status_t cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) = 0;
+    // Note that work is deferred to an additional thread, i.e. this call
+    // is made asynchronously, but the caller can expect that cache/unbind calls
+    // are performed in a manner that's conflict serializable, i.e. unbinding
+    // a buffer should never occur before binding the buffer if the caller
+    // called {bind, cache}ExternalTextureBuffer before calling unbind.
+    virtual void cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) = 0;
     // Removes internal resources referenced by the bufferId. This method should be
     // invoked when the caller will no longer hold a reference to a GraphicBuffer
     // and needs to clean up its resources.
+    // Note that work is deferred to an additional thread, i.e. this call
+    // is made asynchronously, but the caller can expect that cache/unbind calls
+    // are performed in a manner that's conflict serializable, i.e. unbinding
+    // a buffer should never occur before binding the buffer if the caller
+    // called {bind, cache}ExternalTextureBuffer before calling unbind.
     virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0;
     // When binding a native buffer, it must be done before setViewportAndProjection
     // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
@@ -176,6 +186,17 @@
     // should be called for every display that needs to be rendered via the GPU.
     // @param display The display-wide settings that should be applied prior to
     // drawing any layers.
+    //
+    // Assumptions when calling this method:
+    // 1. There is exactly one caller - i.e. multi-threading is not supported.
+    // 2. Additional threads may be calling the {bind,cache}ExternalTexture
+    // methods above. But the main thread is responsible for holding resources
+    // such that Image destruction does not occur while this method is called.
+    //
+    // TODO(b/136806342): This should behavior should ideally be fixed since
+    // the above two assumptions are brittle, as conditional thread safetyness
+    // may be insufficient when maximizing rendering performance in the future.
+    //
     // @param layers The layers to draw onto the display, in Z-order.
     // @param buffer The buffer which will be drawn to. This buffer will be
     // ready once drawFence fires.
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index e33bcfd..b4d3ef2 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -51,7 +51,7 @@
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
     MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
-    MOCK_METHOD1(cacheExternalTextureBuffer, status_t(const sp<GraphicBuffer>&));
+    MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp<GraphicBuffer>&));
     MOCK_METHOD3(bindExternalTextureBuffer,
                  status_t(uint32_t, const sp<GraphicBuffer>&, const sp<Fence>&));
     MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t));
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 9b483ef..e98babc 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -31,6 +31,7 @@
         "libgui",
         "liblog",
         "libnativewindow",
+        "libprocessgroup",
         "libsync",
         "libui",
         "libutils",
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 7acaecf..f47c7fd 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
+#include <chrono>
+#include <condition_variable>
 
+#include <gtest/gtest.h>
 #include <renderengine/RenderEngine.h>
 #include <sync/sync.h>
 #include <ui/PixelFormat.h>
@@ -1001,8 +1003,15 @@
     invokeDraw(settings, layers, mBuffer);
     uint64_t bufferId = layer.source.buffer.buffer->getId();
     EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
-    sRE->unbindExternalTextureBuffer(bufferId);
+    std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
+            sRE->unbindExternalTextureBufferForTesting(bufferId);
+    std::lock_guard<std::mutex> lock(barrier->mutex);
+    ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
+                                            [&]() REQUIRES(barrier->mutex) {
+                                                return barrier->isOpen;
+                                            }));
     EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
+    EXPECT_EQ(NO_ERROR, barrier->result);
 }
 
 TEST_F(RenderEngineTest, drawLayers_bindExternalBufferWithNullBuffer) {
@@ -1019,21 +1028,52 @@
     sRE->bindExternalTextureBuffer(texName, buf, nullptr);
     uint64_t bufferId = buf->getId();
     EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
-    sRE->unbindExternalTextureBuffer(bufferId);
+    std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
+            sRE->unbindExternalTextureBufferForTesting(bufferId);
+    std::lock_guard<std::mutex> lock(barrier->mutex);
+    ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
+                                            [&]() REQUIRES(barrier->mutex) {
+                                                return barrier->isOpen;
+                                            }));
+    EXPECT_EQ(NO_ERROR, barrier->result);
     EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
 }
 
 TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferWithNullBuffer) {
-    status_t result = sRE->cacheExternalTextureBuffer(nullptr);
-    ASSERT_EQ(BAD_VALUE, result);
+    std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
+            sRE->cacheExternalTextureBufferForTesting(nullptr);
+    std::lock_guard<std::mutex> lock(barrier->mutex);
+    ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
+                                            [&]() REQUIRES(barrier->mutex) {
+                                                return barrier->isOpen;
+                                            }));
+    EXPECT_TRUE(barrier->isOpen);
+    EXPECT_EQ(BAD_VALUE, barrier->result);
 }
 
 TEST_F(RenderEngineTest, drawLayers_cacheExternalBufferCachesImages) {
     sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
     uint64_t bufferId = buf->getId();
-    sRE->cacheExternalTextureBuffer(buf);
+    std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
+            sRE->cacheExternalTextureBufferForTesting(buf);
+    {
+        std::lock_guard<std::mutex> lock(barrier->mutex);
+        ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
+                                                [&]() REQUIRES(barrier->mutex) {
+                                                    return barrier->isOpen;
+                                                }));
+        EXPECT_EQ(NO_ERROR, barrier->result);
+    }
     EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
-    sRE->unbindExternalTextureBuffer(bufferId);
+    barrier = sRE->unbindExternalTextureBufferForTesting(bufferId);
+    {
+        std::lock_guard<std::mutex> lock(barrier->mutex);
+        ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
+                                                [&]() REQUIRES(barrier->mutex) {
+                                                    return barrier->isOpen;
+                                                }));
+        EXPECT_EQ(NO_ERROR, barrier->result);
+    }
     EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
 }
 
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index 940ff5a..e8154a6 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -21,22 +21,7 @@
         "-Werror",
     ],
     cppflags: [
-        "-Weverything",
-
-        // The static constructors and destructors in this library have not been noted to
-        // introduce significant overheads
-        "-Wno-exit-time-destructors",
-        "-Wno-global-constructors",
-
-        // We only care about compiling as C++14
-        "-Wno-c++98-compat-pedantic",
-
-        // android/sensors.h uses nested anonymous unions and anonymous structs
-        "-Wno-nested-anon-types",
-        "-Wno-gnu-anonymous-struct",
-
-        // Don't warn about struct padding
-        "-Wno-padded",
+        "-Wextra",
     ],
 
     srcs: [
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 2518e93..42b578c 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,32 +26,18 @@
         "-Werror",
     ],
     cppflags: [
-        "-Weverything",
-
-        // The static constructors and destructors in this library have not been noted to
-        // introduce significant overheads
-        "-Wno-exit-time-destructors",
-        "-Wno-global-constructors",
-
-        // We only care about compiling as C++14
-        "-Wno-c++98-compat-pedantic",
-
-        // We are aware of the risks inherent in comparing floats for equality
-        "-Wno-float-equal",
-
-        // We use four-character constants for the GraphicBuffer header, and don't care
-        // that they're non-portable as long as they're consistent within one execution
-        "-Wno-four-char-constants",
-
-        // Don't warn about struct padding
-        "-Wno-padded",
-
-        "-Wno-switch-enum",
-        "-Wno-format-pedantic",
+        "-Wextra",
     ],
 
     sanitize: {
         integer_overflow: true,
+        misc_undefined: ["bounds"],
+        diag: {
+            misc_undefined: ["bounds"],
+            no_recover: [
+                "bounds",
+            ],
+        },
     },
 
     srcs: [
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 1c597f2..5f1c71e 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -20,6 +20,7 @@
 
 #include <ui/GraphicBufferAllocator.h>
 
+#include <limits.h>
 #include <stdio.h>
 
 #include <grallocusage/GrallocUsageConversion.h>
@@ -114,6 +115,14 @@
     if (!width || !height)
         width = height = 1;
 
+    const uint32_t bpp = bytesPerPixel(format);
+    if (std::numeric_limits<size_t>::max() / width / height < static_cast<size_t>(bpp)) {
+        ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
+              "usage %" PRIx64 ": Requesting too large a buffer size",
+              width, height, layerCount, format, usage);
+        return BAD_VALUE;
+    }
+
     // Ensure that layerCount is valid.
     if (layerCount < 1)
         layerCount = 1;
@@ -126,7 +135,6 @@
     if (error == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        uint32_t bpp = bytesPerPixel(format);
         alloc_rec_t rec;
         rec.width = width;
         rec.height = height;
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index a7c248c..127f7ee 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -35,6 +35,22 @@
 
 class GraphicBufferTest : public testing::Test {};
 
+TEST_F(GraphicBufferTest, AllocateNoError) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    sp<GraphicBuffer> gb(new GraphicBuffer(kTestWidth, kTestHeight, format, kTestLayerCount,
+                                           kTestUsage, std::string("test")));
+    ASSERT_EQ(NO_ERROR, gb->initCheck());
+}
+
+TEST_F(GraphicBufferTest, AllocateBadDimensions) {
+    PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+    uint32_t width, height;
+    width = height = std::numeric_limits<uint32_t>::max();
+    sp<GraphicBuffer> gb(new GraphicBuffer(width, height, format, kTestLayerCount, kTestUsage,
+                                           std::string("test")));
+    ASSERT_EQ(BAD_VALUE, gb->initCheck());
+}
+
 TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) {
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 6d202ae..2fcee7b 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,11 +29,9 @@
 sharedLibraries = [
     "libbase",
     "libcutils",
-    "libhardware",
     "liblog",
     "libui",
     "libutils",
-    "libnativewindow",
     "libpdx_default_transport",
 ]
 
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 1176abf..1ce9c99 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -39,7 +39,6 @@
         "libcutils",
         "liblog",
         "libutils",
-        "libcrypto",
         "libselinux",
     ],
 }
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index ac01dc8..9b1b522 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -379,14 +379,12 @@
                 // any symbol dependencies will be resolved by system libraries. They
                 // can't safely use libc++_shared, for example. Which is one reason
                 // (among several) we only allow them in non-user builds.
-                void* handle = nullptr;
                 auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
                 if (app_namespace && !android::base::StartsWith(layer, kSystemLayerLibraryDir)) {
-                    bool native_bridge = false;
                     char* error_message = nullptr;
-                    handle = OpenNativeLibraryInNamespace(
-                        app_namespace, layer.c_str(), &native_bridge, &error_message);
-                    if (!handle) {
+                    dlhandle_ = OpenNativeLibraryInNamespace(
+                        app_namespace, layer.c_str(), &native_bridge_, &error_message);
+                    if (!dlhandle_) {
                         ALOGE("Failed to load layer %s with error: %s", layer.c_str(),
                               error_message);
                         android::NativeLoaderFreeErrorMessage(error_message);
@@ -394,11 +392,11 @@
                     }
 
                 } else {
-                    handle = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL);
+                    dlhandle_ = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL);
                 }
 
-                if (handle) {
-                    ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)handle,
+                if (dlhandle_) {
+                    ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)dlhandle_,
                           layers[i].c_str());
                 } else {
                     // If the layer is found but can't be loaded, try setenforce 0
@@ -411,8 +409,7 @@
                 std::string init_func = "AndroidGLESLayer_Initialize";
                 ALOGV("Looking for entrypoint %s", init_func.c_str());
 
-                layer_init_func LayerInit =
-                        reinterpret_cast<layer_init_func>(dlsym(handle, init_func.c_str()));
+                layer_init_func LayerInit = GetTrampoline<layer_init_func>(init_func.c_str());
                 if (LayerInit) {
                     ALOGV("Found %s for layer %s", init_func.c_str(), layer.c_str());
                     layer_init_.push_back(LayerInit);
@@ -425,8 +422,7 @@
                 std::string setup_func = "AndroidGLESLayer_GetProcAddress";
                 ALOGV("Looking for entrypoint %s", setup_func.c_str());
 
-                layer_setup_func LayerSetup =
-                        reinterpret_cast<layer_setup_func>(dlsym(handle, setup_func.c_str()));
+                layer_setup_func LayerSetup = GetTrampoline<layer_setup_func>(setup_func.c_str());
                 if (LayerSetup) {
                     ALOGV("Found %s for layer %s", setup_func.c_str(), layer.c_str());
                     layer_setup_.push_back(LayerSetup);
diff --git a/opengl/libs/EGL/egl_layers.h b/opengl/libs/EGL/egl_layers.h
index e401b44..1e2783f 100644
--- a/opengl/libs/EGL/egl_layers.h
+++ b/opengl/libs/EGL/egl_layers.h
@@ -21,10 +21,15 @@
 #include <unordered_map>
 #include <vector>
 
-#include <EGL/egldefs.h>
+#include <android/dlext.h>
+#include <dlfcn.h>
 
+#include <EGL/egldefs.h>
 #include "egl_platform_entries.h"
 
+#include <nativebridge/native_bridge.h>
+#include <nativeloader/native_loader.h>
+
 typedef __eglMustCastToProperFunctionPointerType EGLFuncPointer;
 
 namespace android {
@@ -54,10 +59,21 @@
     std::vector<layer_setup_func> layer_setup_;
 
 private:
-    LayerLoader() : layers_loaded_(false), initialized_(false), current_layer_(0){};
+    LayerLoader() : layers_loaded_(false), initialized_(false), current_layer_(0), dlhandle_(nullptr), native_bridge_(false){};
     bool layers_loaded_;
     bool initialized_;
     unsigned current_layer_;
+    void* dlhandle_;
+    bool native_bridge_;
+
+    template<typename Func = void*>
+    Func GetTrampoline(const char* name) const {
+        if (native_bridge_) {
+            return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline(
+                dlhandle_, name, nullptr, 0));
+        }
+        return reinterpret_cast<Func>(dlsym(dlhandle_, name));
+    }
 };
 
 }; // namespace android
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index e996be6..a3bb6de 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -61,7 +61,7 @@
 
 using nsecs_t = int64_t;
 
-struct extention_map_t {
+struct extension_map_t {
     const char* name;
     __eglMustCastToProperFunctionPointerType address;
 };
@@ -154,7 +154,7 @@
  * (keep in sync with gExtensionString above)
  *
  */
-static const extention_map_t sExtensionMap[] = {
+static const extension_map_t sExtensionMap[] = {
     // EGL_KHR_lock_surface
     { "eglLockSurfaceKHR",
             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
@@ -257,13 +257,14 @@
          !strcmp((procname), "eglAwakenProcessIMG"))
 
 // accesses protected by sExtensionMapMutex
-static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtensionMap;
+static std::unordered_map<std::string, int> sGLExtensionSlotMap;
 
-static int sGLExtentionSlot = 0;
+static int sGLExtensionSlot = 0;
 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
 
 static void(*findProcAddress(const char* name,
-        const extention_map_t* map, size_t n))() {
+        const extension_map_t* map, size_t n))() {
     for (uint32_t i=0 ; i<n ; i++) {
         if (!strcmp(name, map[i].name)) {
             return map[i].address;
@@ -1223,7 +1224,7 @@
     addr = findBuiltinWrapper(procname);
     if (addr) return addr;
 
-    // this protects accesses to sGLExtentionMap and sGLExtentionSlot
+    // this protects accesses to sGLExtensionMap, sGLExtensionSlot, and sGLExtensionSlotMap
     pthread_mutex_lock(&sExtensionMapMutex);
 
     /*
@@ -1244,51 +1245,69 @@
      */
 
     const std::string name(procname);
-
-    auto& extentionMap = sGLExtentionMap;
-    auto pos = extentionMap.find(name);
-    addr = (pos != extentionMap.end()) ? pos->second : nullptr;
-    const int slot = sGLExtentionSlot;
-
-    ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
-             "no more slots for eglGetProcAddress(\"%s\")",
-             procname);
-
+    auto& extensionMap = sGLExtensionMap;
+    auto& extensionSlotMap = sGLExtensionSlotMap;
     egl_connection_t* const cnx = &gEGLImpl;
     LayerLoader& layer_loader(LayerLoader::getInstance());
 
-    if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
+    // See if we've already looked up this extension
+    auto pos = extensionMap.find(name);
+    addr = (pos != extensionMap.end()) ? pos->second : nullptr;
 
-        if (cnx->dso && cnx->egl.eglGetProcAddress) {
+    if (!addr) {
+        // This is the first time we've looked this function up
+        // Ensure we have room to track it
+        const int slot = sGLExtensionSlot;
+        if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) {
 
-            // Extensions are independent of the bound context
-            addr = cnx->egl.eglGetProcAddress(procname);
-            if (addr) {
+            if (cnx->dso && cnx->egl.eglGetProcAddress) {
 
-                // purposefully track the bottom of the stack in extensionMap
-                extentionMap[name] = addr;
+                // Extensions are independent of the bound context
+                addr = cnx->egl.eglGetProcAddress(procname);
+                if (addr) {
 
-                // Apply layers
-                addr = layer_loader.ApplyLayers(procname, addr);
+                    // purposefully track the bottom of the stack in extensionMap
+                    extensionMap[name] = addr;
 
-                // Track the top most entry point
-                cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
-                cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
-                addr = gExtensionForwarders[slot];
-                sGLExtentionSlot++;
+                    // Apply layers
+                    addr = layer_loader.ApplyLayers(procname, addr);
+
+                    // Track the top most entry point return the extension forwarder
+                    cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
+                    cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
+                    addr = gExtensionForwarders[slot];
+
+                    // Remember the slot for this extension
+                    extensionSlotMap[name] = slot;
+
+                    // Increment the global extension index
+                    sGLExtensionSlot++;
+                }
             }
+        } else {
+            // The extension forwarder has a fixed number of slots
+            ALOGE("no more slots for eglGetProcAddress(\"%s\")", procname);
         }
 
-    } else if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) {
+    } else {
+        // We tracked an address, so we've seen this func before
+        // Look up the slot for this extension
+        auto slot_pos = extensionSlotMap.find(name);
+        int ext_slot = (slot_pos != extensionSlotMap.end()) ? slot_pos->second : -1;
+        if (ext_slot < 0) {
+            // Something has gone wrong, this should not happen
+            ALOGE("No extension slot found for %s", procname);
+            return nullptr;
+        }
 
-        // We've seen this func before, but we tracked the bottom, so re-apply layers
-        // More layers might have been enabled
+        // We tracked the bottom of the stack, so re-apply layers since
+        // more layers might have been enabled
         addr = layer_loader.ApplyLayers(procname, addr);
 
-        // Track the top most entry point
-        cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
-        cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
-        addr = gExtensionForwarders[slot];
+        // Track the top most entry point and return the extension forwarder
+        cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[ext_slot] =
+        cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[ext_slot] = addr;
+        addr = gExtensionForwarders[ext_slot];
     }
 
     pthread_mutex_unlock(&sExtensionMapMutex);
diff --git a/opengl/libs/libEGL.map.txt b/opengl/libs/libEGL.map.txt
index b2d7957..0c14e01 100644
--- a/opengl/libs/libEGL.map.txt
+++ b/opengl/libs/libEGL.map.txt
@@ -28,7 +28,7 @@
     eglDestroySurface;
     eglDestroySync; # introduced=29
     eglDestroySyncKHR; # introduced-arm=18 introduced-arm64=21 introduced-mips=18 introduced-mips64=21 introduced-x86=18 introduced-x86_64=21
-    eglDupNativeFenceFDANDROID; # vndk
+    eglDupNativeFenceFDANDROID; # llndk
     eglGetConfigAttrib;
     eglGetConfigs;
     eglGetCurrentContext;
@@ -54,7 +54,7 @@
     eglQueryStreamTimeKHR; # introduced=23
     eglQueryStreamu64KHR; # introduced=23
     eglQueryString;
-    eglQueryStringImplementationANDROID; # vndk
+    eglQueryStringImplementationANDROID; # llndk
     eglQuerySurface;
     eglReleaseTexImage;
     eglReleaseThread;
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 8accf9d..c8253e0 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -53,33 +53,23 @@
                              int64_t driverBuildTime, const std::string& appPackageName,
                              const int32_t vulkanVersion, GraphicsEnv::Driver driver,
                              bool isDriverLoaded, int64_t driverLoadingTime) {
-    ATRACE_CALL();
-
     mGpuStats->insert(driverPackageName, driverVersionName, driverVersionCode, driverBuildTime,
                       appPackageName, vulkanVersion, driver, isDriverLoaded, driverLoadingTime);
 }
 
 status_t GpuService::getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullGlobalStats(outStats);
-
     return OK;
 }
 
 status_t GpuService::getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const {
-    ATRACE_CALL();
-
     mGpuStats->pullAppStats(outStats);
-
     return OK;
 }
 
-void GpuService::setCpuVulkanInUse(const std::string& appPackageName,
-                                   const uint64_t driverVersionCode) {
-    ATRACE_CALL();
-
-    mGpuStats->setCpuVulkanInUse(appPackageName, driverVersionCode);
+void GpuService::setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                                const GraphicsEnv::Stats stats, const uint64_t value) {
+    mGpuStats->insertTargetStats(appPackageName, driverVersionCode, stats, value);
 }
 
 status_t GpuService::shellCommand(int /*in*/, int out, int err, std::vector<String16>& args) {
diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h
index 8226901..7d44a35 100644
--- a/services/gpuservice/GpuService.h
+++ b/services/gpuservice/GpuService.h
@@ -50,8 +50,8 @@
                      int64_t driverLoadingTime) override;
     status_t getGpuStatsGlobalInfo(std::vector<GpuStatsGlobalInfo>* outStats) const override;
     status_t getGpuStatsAppInfo(std::vector<GpuStatsAppInfo>* outStats) const override;
-    void setCpuVulkanInUse(const std::string& appPackageName,
-                           const uint64_t driverVersionCode) override;
+    void setTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                        const GraphicsEnv::Stats stats, const uint64_t value) override;
 
     /*
      * IBinder interface
diff --git a/services/gpuservice/gpustats/GpuStats.cpp b/services/gpuservice/gpustats/GpuStats.cpp
index 37c6abc..5d27e72 100644
--- a/services/gpuservice/gpustats/GpuStats.cpp
+++ b/services/gpuservice/gpustats/GpuStats.cpp
@@ -126,14 +126,25 @@
     addLoadingTime(driver, driverLoadingTime, &mAppStats[appStatsKey]);
 }
 
-void GpuStats::setCpuVulkanInUse(const std::string& appPackageName,
-                                 const uint64_t driverVersionCode) {
+void GpuStats::insertTargetStats(const std::string& appPackageName,
+                                 const uint64_t driverVersionCode, const GraphicsEnv::Stats stats,
+                                 const uint64_t /*value*/) {
+    ATRACE_CALL();
+
     const std::string appStatsKey = appPackageName + std::to_string(driverVersionCode);
+
+    std::lock_guard<std::mutex> lock(mLock);
     if (!mAppStats.count(appStatsKey)) {
         return;
     }
 
-    mAppStats[appStatsKey].cpuVulkanInUse = true;
+    switch (stats) {
+        case GraphicsEnv::Stats::CPU_VULKAN_IN_USE:
+            mAppStats[appStatsKey].cpuVulkanInUse = true;
+            break;
+        default:
+            break;
+    }
 }
 
 void GpuStats::interceptSystemDriverStatsLocked() {
diff --git a/services/gpuservice/gpustats/GpuStats.h b/services/gpuservice/gpustats/GpuStats.h
index b293f59..378f7f4 100644
--- a/services/gpuservice/gpustats/GpuStats.h
+++ b/services/gpuservice/gpustats/GpuStats.h
@@ -37,8 +37,9 @@
                 uint64_t driverVersionCode, int64_t driverBuildTime,
                 const std::string& appPackageName, const int32_t vulkanVersion,
                 GraphicsEnv::Driver driver, bool isDriverLoaded, int64_t driverLoadingTime);
-    // Set CPU Vulkan in use signal into app stats.
-    void setCpuVulkanInUse(const std::string& appPackageName, const uint64_t driverVersionCode);
+    // Insert target stats into app stats or potentially global stats as well.
+    void insertTargetStats(const std::string& appPackageName, const uint64_t driverVersionCode,
+                           const GraphicsEnv::Stats stats, const uint64_t value);
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
     // Pull gpu global stats
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index ef1a224..6a7f279 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -82,7 +82,7 @@
 // Check if the "deep touch" feature is on.
 static bool deepPressEnabled() {
     std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
-            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true");
+            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
     std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
     if (flag_value == "1" || flag_value == "true") {
         ALOGI("Deep press feature enabled.");
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c11b88e..14ed73d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -299,14 +299,10 @@
 }
 
 void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
-    SortedVector< sp<SensorEventConnection> > activeConnections;
-    populateActiveConnections(&activeConnections);
-    {
-        Mutex::Autolock _l(mLock);
-        for (size_t i = 0 ; i < activeConnections.size(); i++) {
-            if (activeConnections[i] != nullptr && activeConnections[i]->getUid() == uid) {
-                activeConnections[i]->setSensorAccess(hasAccess);
-            }
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+        if (conn->getUid() == uid) {
+            conn->setSensorAccess(hasAccess);
         }
     }
 }
@@ -360,7 +356,7 @@
         if (args.size() > 2) {
            return INVALID_OPERATION;
         }
-        Mutex::Autolock _l(mLock);
+        ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
         SensorDevice& dev(SensorDevice::getInstance());
         if (args.size() == 2 && args[0] == String16("restrict")) {
             // If already in restricted mode. Ignore.
@@ -374,7 +370,7 @@
 
             mCurrentOperatingMode = RESTRICTED;
             // temporarily stop all sensor direct report and disable sensors
-            disableAllSensorsLocked();
+            disableAllSensorsLocked(&connLock);
             mWhiteListedPackage.setTo(String8(args[1]));
             return status_t(NO_ERROR);
         } else if (args.size() == 1 && args[0] == String16("enable")) {
@@ -382,7 +378,7 @@
             if (mCurrentOperatingMode == RESTRICTED) {
                 mCurrentOperatingMode = NORMAL;
                 // enable sensors and recover all sensor direct report
-                enableAllSensorsLocked();
+                enableAllSensorsLocked(&connLock);
             }
             if (mCurrentOperatingMode == DATA_INJECTION) {
                resetToNormalModeLocked();
@@ -473,22 +469,18 @@
             result.appendFormat("Sensor Privacy: %s\n",
                     mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled");
 
-            result.appendFormat("%zd active connections\n", mActiveConnections.size());
-            for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
-                sp<SensorEventConnection> connection(mActiveConnections[i].promote());
-                if (connection != nullptr) {
-                    result.appendFormat("Connection Number: %zu \n", i);
-                    connection->dump(result);
-                }
+            const auto& activeConnections = connLock.getActiveConnections();
+            result.appendFormat("%zd active connections\n", activeConnections.size());
+            for (size_t i=0 ; i < activeConnections.size() ; i++) {
+                result.appendFormat("Connection Number: %zu \n", i);
+                activeConnections[i]->dump(result);
             }
 
-            result.appendFormat("%zd direct connections\n", mDirectConnections.size());
-            for (size_t i = 0 ; i < mDirectConnections.size() ; i++) {
-                sp<SensorDirectConnection> connection(mDirectConnections[i].promote());
-                if (connection != nullptr) {
-                    result.appendFormat("Direct connection %zu:\n", i);
-                    connection->dump(result);
-                }
+            const auto& directConnections = connLock.getDirectConnections();
+            result.appendFormat("%zd direct connections\n", directConnections.size());
+            for (size_t i = 0 ; i < directConnections.size() ; i++) {
+                result.appendFormat("Direct connection %zu:\n", i);
+                directConnections[i]->dump(result);
             }
 
             result.appendFormat("Previous Registrations:\n");
@@ -515,17 +507,14 @@
 }
 
 void SensorService::disableAllSensors() {
-    Mutex::Autolock _l(mLock);
-    disableAllSensorsLocked();
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    disableAllSensorsLocked(&connLock);
 }
 
-void SensorService::disableAllSensorsLocked() {
+void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
     SensorDevice& dev(SensorDevice::getInstance());
-    for (auto &i : mDirectConnections) {
-        sp<SensorDirectConnection> connection(i.promote());
-        if (connection != nullptr) {
-            connection->stopAll(true /* backupRecord */);
-        }
+    for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+        connection->stopAll(true /* backupRecord */);
     }
     dev.disableAllSensors();
     // Clear all pending flush connections for all active sensors. If one of the active
@@ -537,11 +526,11 @@
 }
 
 void SensorService::enableAllSensors() {
-    Mutex::Autolock _l(mLock);
-    enableAllSensorsLocked();
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    enableAllSensorsLocked(&connLock);
 }
 
-void SensorService::enableAllSensorsLocked() {
+void SensorService::enableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
     // sensors should only be enabled if the operating state is not restricted and sensor
     // privacy is not enabled.
     if (mCurrentOperatingMode == RESTRICTED || mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -552,14 +541,12 @@
     }
     SensorDevice& dev(SensorDevice::getInstance());
     dev.enableAllSensors();
-    for (auto &i : mDirectConnections) {
-        sp<SensorDirectConnection> connection(i.promote());
-        if (connection != nullptr) {
-            connection->recoverAll();
-        }
+    for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+        connection->recoverAll();
     }
 }
 
+
 // NOTE: This is a remote API - make sure all args are validated
 status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
     if (!checkCallingPermission(sManageSensorsPermission, nullptr, nullptr)) {
@@ -734,17 +721,8 @@
         for (int i = 0; i < count; i++) {
              mSensorEventBuffer[i].flags = 0;
         }
+        ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
 
-        // Make a copy of the connection vector as some connections may be removed during the course
-        // of this loop (especially when one-shot sensor events are present in the sensor_event
-        // buffer). Promote all connections to StrongPointers before the lock is acquired. If the
-        // destructor of the sp gets called when the lock is acquired, it may result in a deadlock
-        // as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the
-        // strongPointers to a vector before the lock is acquired.
-        SortedVector< sp<SensorEventConnection> > activeConnections;
-        populateActiveConnections(&activeConnections);
-
-        Mutex::Autolock _l(mLock);
         // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
         // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
         // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
@@ -818,6 +796,10 @@
             }
         }
 
+        // Cache the list of active connections, since we use it in multiple places below but won't
+        // modify it here
+        const std::vector<sp<SensorEventConnection>> activeConnections = connLock.getActiveConnections();
+
         for (int i = 0; i < count; ++i) {
             // Map flush_complete_events in the buffer to SensorEventConnections which called flush
             // on the hardware sensor. mapFlushEventsToConnections[i] will be the
@@ -869,11 +851,8 @@
                         ALOGE("Dynamic sensor release error.");
                     }
 
-                    size_t numConnections = activeConnections.size();
-                    for (size_t i=0 ; i < numConnections; ++i) {
-                        if (activeConnections[i] != nullptr) {
-                            activeConnections[i]->removeSensor(handle);
-                        }
+                    for (const sp<SensorEventConnection>& connection : activeConnections) {
+                        connection->removeSensor(handle);
                     }
                 }
             }
@@ -882,18 +861,14 @@
         // Send our events to clients. Check the state of wake lock for each client and release the
         // lock if none of the clients need it.
         bool needsWakeLock = false;
-        size_t numConnections = activeConnections.size();
-        for (size_t i=0 ; i < numConnections; ++i) {
-            if (activeConnections[i] != nullptr) {
-                activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
-                        mMapFlushEventsToConnections);
-                needsWakeLock |= activeConnections[i]->needsWakeLock();
-                // If the connection has one-shot sensors, it may be cleaned up after first trigger.
-                // Early check for one-shot sensors.
-                if (activeConnections[i]->hasOneShotSensors()) {
-                    cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
-                            count);
-                }
+        for (const sp<SensorEventConnection>& connection : activeConnections) {
+            connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
+                    mMapFlushEventsToConnections);
+            needsWakeLock |= connection->needsWakeLock();
+            // If the connection has one-shot sensors, it may be cleaned up after first trigger.
+            // Early check for one-shot sensors.
+            if (connection->hasOneShotSensors()) {
+                cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);
             }
         }
 
@@ -912,17 +887,11 @@
 }
 
 void SensorService::resetAllWakeLockRefCounts() {
-    SortedVector< sp<SensorEventConnection> > activeConnections;
-    populateActiveConnections(&activeConnections);
-    {
-        Mutex::Autolock _l(mLock);
-        for (size_t i=0 ; i < activeConnections.size(); ++i) {
-            if (activeConnections[i] != nullptr) {
-                activeConnections[i]->resetWakeLockRefCount();
-            }
-        }
-        setWakeLockAcquiredLocked(false);
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    for (const sp<SensorEventConnection>& connection : connLock.getActiveConnections()) {
+        connection->resetWakeLockRefCount();
     }
+    setWakeLockAcquiredLocked(false);
 }
 
 void SensorService::setWakeLockAcquiredLocked(bool acquire) {
@@ -1144,9 +1113,7 @@
     sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
             requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
     if (requestedMode == DATA_INJECTION) {
-        if (mActiveConnections.indexOf(result) < 0) {
-            mActiveConnections.add(result);
-        }
+        mConnectionHolder.addEventConnectionIfNotPresent(result);
         // Add the associated file descriptor to the Looper for polling whenever there is data to
         // be injected.
         result->updateLooperRegistration(mLooper);
@@ -1162,7 +1129,7 @@
 sp<ISensorEventConnection> SensorService::createSensorDirectConnection(
         const String16& opPackageName, uint32_t size, int32_t type, int32_t format,
         const native_handle *resource) {
-    Mutex::Autolock _l(mLock);
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
 
     // No new direct connections are allowed when sensor privacy is enabled
     if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -1190,9 +1157,8 @@
     }
 
     // check for duplication
-    for (auto &i : mDirectConnections) {
-        sp<SensorDirectConnection> connection(i.promote());
-        if (connection != nullptr && connection->isEquivalent(&mem)) {
+    for (const sp<SensorDirectConnection>& connection : connLock.getDirectConnections()) {
+        if (connection->isEquivalent(&mem)) {
             ALOGE("Duplicate create channel request for the same share memory");
             return nullptr;
         }
@@ -1229,7 +1195,7 @@
         return nullptr;
     }
 
-    SensorDirectConnection* conn = nullptr;
+    sp<SensorDirectConnection> conn;
     SensorDevice& dev(SensorDevice::getInstance());
     int channelHandle = dev.registerDirectChannel(&mem);
 
@@ -1246,7 +1212,7 @@
     } else {
         // add to list of direct connections
         // sensor service should never hold pointer or sp of SensorDirectConnection object.
-        mDirectConnections.add(wp<SensorDirectConnection>(conn));
+        mConnectionHolder.addDirectConnection(conn);
     }
     return conn;
 }
@@ -1358,7 +1324,7 @@
 }
 
 void SensorService::cleanupConnection(SensorEventConnection* c) {
-    Mutex::Autolock _l(mLock);
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
     const wp<SensorEventConnection> connection(c);
     size_t size = mActiveSensors.size();
     ALOGD_IF(DEBUG_CONNECTIONS, "%zu active sensors", size);
@@ -1391,10 +1357,10 @@
         }
     }
     c->updateLooperRegistration(mLooper);
-    mActiveConnections.remove(connection);
+    mConnectionHolder.removeEventConnection(connection);
     BatteryService::cleanup(c->getUid());
     if (c->needsWakeLock()) {
-        checkWakeLockStateLocked();
+        checkWakeLockStateLocked(&connLock);
     }
 
     {
@@ -1414,7 +1380,7 @@
 
     SensorDevice& dev(SensorDevice::getInstance());
     dev.unregisterDirectChannel(c->getHalChannelHandle());
-    mDirectConnections.remove(c);
+    mConnectionHolder.removeDirectConnection(c);
 }
 
 sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
@@ -1433,7 +1399,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
     if (mCurrentOperatingMode != NORMAL
            && !isWhiteListedPackage(connection->getPackageName())) {
         return INVALID_OPERATION;
@@ -1484,7 +1450,7 @@
                             }
                             connection->sendEvents(&event, 1, nullptr);
                             if (!connection->needsWakeLock() && mWakeLockAcquired) {
-                                checkWakeLockStateLocked();
+                                checkWakeLockStateLocked(&connLock);
                             }
                         }
                     }
@@ -1497,9 +1463,7 @@
         BatteryService::enableSensor(connection->getUid(), handle);
         // the sensor was added (which means it wasn't already there)
         // so, see if this connection becomes active
-        if (mActiveConnections.indexOf(connection) < 0) {
-            mActiveConnections.add(connection);
-        }
+        mConnectionHolder.addEventConnectionIfNotPresent(connection);
     } else {
         ALOGW("sensor %08x already enabled in connection %p (ignoring)",
             handle, connection.get());
@@ -1603,7 +1567,7 @@
         }
         if (connection->hasAnySensor() == false) {
             connection->updateLooperRegistration(mLooper);
-            mActiveConnections.remove(connection);
+            mConnectionHolder.removeEventConnection(connection);
         }
         // see if this sensor becomes inactive
         if (rec->removeConnection(connection)) {
@@ -1762,22 +1726,19 @@
 }
 
 void SensorService::checkWakeLockState() {
-    Mutex::Autolock _l(mLock);
-    checkWakeLockStateLocked();
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    checkWakeLockStateLocked(&connLock);
 }
 
-void SensorService::checkWakeLockStateLocked() {
+void SensorService::checkWakeLockStateLocked(ConnectionSafeAutolock* connLock) {
     if (!mWakeLockAcquired) {
         return;
     }
     bool releaseLock = true;
-    for (size_t i=0 ; i<mActiveConnections.size() ; i++) {
-        sp<SensorEventConnection> connection(mActiveConnections[i].promote());
-        if (connection != nullptr) {
-            if (connection->needsWakeLock()) {
-                releaseLock = false;
-                break;
-            }
+    for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
+        if (connection->needsWakeLock()) {
+            releaseLock = false;
+            break;
         }
     }
     if (releaseLock) {
@@ -1793,17 +1754,6 @@
     }
 }
 
-void SensorService::populateActiveConnections(
-        SortedVector< sp<SensorEventConnection> >* activeConnections) {
-    Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
-        sp<SensorEventConnection> connection(mActiveConnections[i].promote());
-        if (connection != nullptr) {
-            activeConnections->add(connection);
-        }
-    }
-}
-
 bool SensorService::isWhiteListedPackage(const String8& packageName) {
     return (packageName.contains(mWhiteListedPackage.string()));
 }
@@ -1938,4 +1888,62 @@
     }
     return binder::Status::ok();
 }
-}; // namespace android
+
+SensorService::ConnectionSafeAutolock::ConnectionSafeAutolock(
+        SensorService::SensorConnectionHolder& holder, Mutex& mutex)
+        : mConnectionHolder(holder), mAutolock(mutex) {}
+
+template<typename ConnectionType>
+const std::vector<sp<ConnectionType>>& SensorService::ConnectionSafeAutolock::getConnectionsHelper(
+        const SortedVector<wp<ConnectionType>>& connectionList,
+        std::vector<std::vector<sp<ConnectionType>>>* referenceHolder) {
+    referenceHolder->emplace_back();
+    std::vector<sp<ConnectionType>>& connections = referenceHolder->back();
+    for (const wp<ConnectionType>& weakConnection : connectionList){
+        sp<ConnectionType> connection = weakConnection.promote();
+        if (connection != nullptr) {
+            connections.push_back(std::move(connection));
+        }
+    }
+    return connections;
+}
+
+const std::vector<sp<SensorService::SensorEventConnection>>&
+        SensorService::ConnectionSafeAutolock::getActiveConnections() {
+    return getConnectionsHelper(mConnectionHolder.mActiveConnections,
+                                &mReferencedActiveConnections);
+}
+
+const std::vector<sp<SensorService::SensorDirectConnection>>&
+        SensorService::ConnectionSafeAutolock::getDirectConnections() {
+    return getConnectionsHelper(mConnectionHolder.mDirectConnections,
+                                &mReferencedDirectConnections);
+}
+
+void SensorService::SensorConnectionHolder::addEventConnectionIfNotPresent(
+        const sp<SensorService::SensorEventConnection>& connection) {
+    if (mActiveConnections.indexOf(connection) < 0) {
+        mActiveConnections.add(connection);
+    }
+}
+
+void SensorService::SensorConnectionHolder::removeEventConnection(
+        const wp<SensorService::SensorEventConnection>& connection) {
+    mActiveConnections.remove(connection);
+}
+
+void SensorService::SensorConnectionHolder::addDirectConnection(
+        const sp<SensorService::SensorDirectConnection>& connection) {
+    mDirectConnections.add(connection);
+}
+
+void SensorService::SensorConnectionHolder::removeDirectConnection(
+        const wp<SensorService::SensorDirectConnection>& connection) {
+    mDirectConnections.remove(connection);
+}
+
+SensorService::ConnectionSafeAutolock SensorService::SensorConnectionHolder::lock(Mutex& mutex) {
+    return ConnectionSafeAutolock(*this, mutex);
+}
+
+} // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index e6ec96d..060b5eb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -20,6 +20,7 @@
 #include "SensorList.h"
 #include "RecentEventLogger.h"
 
+#include <android-base/macros.h>
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IUidObserver.h>
@@ -42,6 +43,7 @@
 #include <sys/types.h>
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 
 #if __clang__
 // Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -95,10 +97,67 @@
     friend class BinderService<SensorService>;
 
     // nested class/struct for internal use
-    class SensorRecord;
+    class ConnectionSafeAutolock;
+    class SensorConnectionHolder;
     class SensorEventAckReceiver;
+    class SensorRecord;
     class SensorRegistrationInfo;
 
+    // Promoting a SensorEventConnection or SensorDirectConnection from wp to sp must be done with
+    // mLock held, but destroying that sp must be done unlocked to avoid a race condition that
+    // causes a deadlock (remote dies while we hold a local sp, then our decStrong() call invokes
+    // the dtor -> cleanupConnection() tries to re-lock the mutex). This class ensures safe usage
+    // by wrapping a Mutex::Autolock on SensorService's mLock, plus vectors that hold promoted sp<>
+    // references until the lock is released, when they are safely destroyed.
+    // All read accesses to the connection lists in mConnectionHolder must be done via this class.
+    class ConnectionSafeAutolock final {
+    public:
+        // Returns a list of non-null promoted connection references
+        const std::vector<sp<SensorEventConnection>>& getActiveConnections();
+        const std::vector<sp<SensorDirectConnection>>& getDirectConnections();
+
+    private:
+        // Constructed via SensorConnectionHolder::lock()
+        friend class SensorConnectionHolder;
+        explicit ConnectionSafeAutolock(SensorConnectionHolder& holder, Mutex& mutex);
+        DISALLOW_IMPLICIT_CONSTRUCTORS(ConnectionSafeAutolock);
+
+        // NOTE: Order of these members is important, as the destructor for non-static members
+        // get invoked in the reverse order of their declaration. Here we are relying on the
+        // Autolock to be destroyed *before* the vectors, so the sp<> objects are destroyed without
+        // the lock held, which avoids the deadlock.
+        SensorConnectionHolder& mConnectionHolder;
+        std::vector<std::vector<sp<SensorEventConnection>>> mReferencedActiveConnections;
+        std::vector<std::vector<sp<SensorDirectConnection>>> mReferencedDirectConnections;
+        Mutex::Autolock mAutolock;
+
+        template<typename ConnectionType>
+        const std::vector<sp<ConnectionType>>& getConnectionsHelper(
+                const SortedVector<wp<ConnectionType>>& connectionList,
+                std::vector<std::vector<sp<ConnectionType>>>* referenceHolder);
+    };
+
+    // Encapsulates the collection of active SensorEventConection and SensorDirectConnection
+    // references. Write access is done through this class with mLock held, but all read access
+    // must be routed through ConnectionSafeAutolock.
+    class SensorConnectionHolder {
+    public:
+        void addEventConnectionIfNotPresent(const sp<SensorEventConnection>& connection);
+        void removeEventConnection(const wp<SensorEventConnection>& connection);
+
+        void addDirectConnection(const sp<SensorDirectConnection>& connection);
+        void removeDirectConnection(const wp<SensorDirectConnection>& connection);
+
+        // Pass in the mutex that protects this connection holder; acquires the lock and returns an
+        // object that can be used to safely read the lists of connections
+        ConnectionSafeAutolock lock(Mutex& mutex);
+
+    private:
+        friend class ConnectionSafeAutolock;
+        SortedVector< wp<SensorEventConnection> > mActiveConnections;
+        SortedVector< wp<SensorDirectConnection> > mDirectConnections;
+    };
+
     // If accessing a sensor we need to make sure the UID has access to it. If
     // the app UID is idle then it cannot access sensors and gets no trigger
     // events, no on-change events, flush event behavior does not change, and
@@ -250,7 +309,7 @@
     // method checks whether all the events from these wake up sensors have been delivered to the
     // corresponding applications, if yes the wakelock is released.
     void checkWakeLockState();
-    void checkWakeLockStateLocked();
+    void checkWakeLockStateLocked(ConnectionSafeAutolock* connLock);
     bool isWakeLockAcquired();
     bool isWakeUpSensorEvent(const sensors_event_t& event) const;
 
@@ -268,10 +327,6 @@
     // Send events from the event cache for this particular connection.
     void sendEventsFromCache(const sp<SensorEventConnection>& connection);
 
-    // Promote all weak referecences in mActiveConnections vector to strong references and add them
-    // to the output vector.
-    void populateActiveConnections( SortedVector< sp<SensorEventConnection> >* activeConnections);
-
     // If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
     // allowed to register for or call flush on sensors. Typically only cts test packages are
     // allowed.
@@ -306,10 +361,10 @@
 
     // temporarily stops all active direct connections and disables all sensors
     void disableAllSensors();
-    void disableAllSensorsLocked();
+    void disableAllSensorsLocked(ConnectionSafeAutolock* connLock);
     // restarts the previously stopped direct connections and enables all sensors
     void enableAllSensors();
-    void enableAllSensorsLocked();
+    void enableAllSensorsLocked(ConnectionSafeAutolock* connLock);
 
     static uint8_t sHmacGlobalKey[128];
     static bool sHmacGlobalKeyIsValid;
@@ -327,12 +382,13 @@
     mutable Mutex mLock;
     DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
     std::unordered_set<int> mActiveVirtualSensors;
-    SortedVector< wp<SensorEventConnection> > mActiveConnections;
+    SensorConnectionHolder mConnectionHolder;
     bool mWakeLockAcquired;
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
+    // WARNING: these SensorEventConnection instances must not be promoted to sp, except via
+    // modification to add support for them in ConnectionSafeAutolock
     wp<const SensorEventConnection> * mMapFlushEventsToConnections;
     std::unordered_map<int, SensorServiceUtil::RecentEventLogger*> mRecentEvent;
-    SortedVector< wp<SensorDirectConnection> > mDirectConnections;
     Mode mCurrentOperatingMode;
 
     // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5f07bec..cda982a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -149,9 +149,10 @@
         "Scheduler/LayerHistory.cpp",
         "Scheduler/LayerInfo.cpp",
         "Scheduler/MessageQueue.cpp",
+        "Scheduler/PhaseOffsets.cpp",
         "Scheduler/Scheduler.cpp",
         "Scheduler/SchedulerUtils.cpp",
-        "Scheduler/PhaseOffsets.cpp",
+        "Scheduler/VSyncModulator.cpp",
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
         "SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index b679380..46a62ed 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -48,7 +48,7 @@
 class BufferLayer : public Layer {
 public:
     explicit BufferLayer(const LayerCreationArgs& args);
-    ~BufferLayer() override;
+    virtual ~BufferLayer() override;
 
     // -----------------------------------------------------------------------
     // Overriden from Layer
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 6709fb4..414814a 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -369,6 +369,15 @@
     return mCurrentSurfaceDamage;
 }
 
+void BufferLayerConsumer::mergeSurfaceDamage(const Region& damage) {
+    if (damage.bounds() == Rect::INVALID_RECT ||
+        mCurrentSurfaceDamage.bounds() == Rect::INVALID_RECT) {
+        mCurrentSurfaceDamage = Region::INVALID_REGION;
+    } else {
+        mCurrentSurfaceDamage |= damage;
+    }
+}
+
 int BufferLayerConsumer::getCurrentApi() const {
     Mutex::Autolock lock(mMutex);
     return mCurrentApi;
@@ -485,7 +494,6 @@
         if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr ||
             oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) {
             mImages[item.mSlot] = std::make_shared<Image>(item.mGraphicBuffer, mRE);
-            mRE.cacheExternalTextureBuffer(item.mGraphicBuffer);
         }
     }
 }
@@ -522,6 +530,12 @@
     ConsumerBase::dumpLocked(result, prefix);
 }
 
+BufferLayerConsumer::Image::Image(const sp<GraphicBuffer>& graphicBuffer,
+                                  renderengine::RenderEngine& engine)
+      : mGraphicBuffer(graphicBuffer), mRE(engine) {
+    mRE.cacheExternalTextureBuffer(mGraphicBuffer);
+}
+
 BufferLayerConsumer::Image::~Image() {
     if (mGraphicBuffer != nullptr) {
         ALOGV("Destroying buffer: %" PRId64, mGraphicBuffer->getId());
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index e3f6100..617b1c2 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -140,6 +140,9 @@
     // must be called from SF main thread
     const Region& getSurfaceDamage() const;
 
+    // Merge the given damage region into the current damage region value.
+    void mergeSurfaceDamage(const Region& damage);
+
     // getCurrentApi retrieves the API which queues the current buffer.
     int getCurrentApi() const;
 
@@ -220,8 +223,7 @@
     // Utility class for managing GraphicBuffer references into renderengine
     class Image {
     public:
-        Image(sp<GraphicBuffer> graphicBuffer, renderengine::RenderEngine& engine)
-              : mGraphicBuffer(graphicBuffer), mRE(engine) {}
+        Image(const sp<GraphicBuffer>& graphicBuffer, renderengine::RenderEngine& engine);
         virtual ~Image();
         const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index ab7b8ba..cbb9d65 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -317,6 +317,7 @@
         // and return early
         if (queuedBuffer) {
             Mutex::Autolock lock(mQueueItemLock);
+            mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
             mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber);
             mQueueItems.removeAt(0);
             mQueuedFrames--;
@@ -352,6 +353,7 @@
         // Remove any stale buffers that have been dropped during
         // updateTexImage
         while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+            mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
             mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber);
             mQueueItems.removeAt(0);
             mQueuedFrames--;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 203bd72..63a07c3 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -50,8 +50,12 @@
     mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
     mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
 }
+
 BufferStateLayer::~BufferStateLayer() {
     if (mActiveBuffer != nullptr) {
+        // Ensure that mActiveBuffer is uncached from RenderEngine here, as
+        // RenderEngine may have been using the buffer as an external texture
+        // after the client uncached the buffer.
         auto& engine(mFlinger->getRenderEngine());
         engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
     }
@@ -571,11 +575,6 @@
         return BAD_VALUE;
     }
 
-    if (mActiveBuffer != nullptr) {
-        // todo: get this to work with BufferStateLayerCache
-        auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
-    }
     mActiveBuffer = s.buffer;
     mActiveBufferFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 4e2bc45..97e24cb 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -34,6 +34,7 @@
 class BufferStateLayer : public BufferLayer {
 public:
     explicit BufferStateLayer(const LayerCreationArgs&);
+
     ~BufferStateLayer() override;
 
     // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index 77f2f57..16fe27c 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -55,16 +55,16 @@
     return true;
 }
 
-void ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
+bool ClientCache::add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer) {
     auto& [processToken, id] = cacheId;
     if (processToken == nullptr) {
         ALOGE("failed to cache buffer: invalid process token");
-        return;
+        return false;
     }
 
     if (!buffer) {
         ALOGE("failed to cache buffer: invalid buffer");
-        return;
+        return false;
     }
 
     std::lock_guard lock(mMutex);
@@ -77,13 +77,13 @@
         token = processToken.promote();
         if (!token) {
             ALOGE("failed to cache buffer: invalid token");
-            return;
+            return false;
         }
 
         status_t err = token->linkToDeath(mDeathRecipient);
         if (err != NO_ERROR) {
             ALOGE("failed to cache buffer: could not link to death");
-            return;
+            return false;
         }
         auto [itr, success] =
                 mBuffers.emplace(processToken, std::unordered_map<uint64_t, ClientCacheBuffer>());
@@ -95,10 +95,11 @@
 
     if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) {
         ALOGE("failed to cache buffer: cache is full");
-        return;
+        return false;
     }
 
     processBuffers[id].buffer = buffer;
+    return true;
 }
 
 void ClientCache::erase(const client_cache_t& cacheId) {
@@ -139,16 +140,17 @@
     return buf->buffer;
 }
 
-void ClientCache::registerErasedRecipient(const client_cache_t& cacheId,
+bool ClientCache::registerErasedRecipient(const client_cache_t& cacheId,
                                           const wp<ErasedRecipient>& recipient) {
     std::lock_guard lock(mMutex);
 
     ClientCacheBuffer* buf = nullptr;
     if (!getBuffer(cacheId, &buf)) {
         ALOGE("failed to register erased recipient, could not retrieve buffer");
-        return;
+        return false;
     }
     buf->recipients.insert(recipient);
+    return true;
 }
 
 void ClientCache::unregisterErasedRecipient(const client_cache_t& cacheId,
diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h
index 9f057c4..aa6c80d 100644
--- a/services/surfaceflinger/ClientCache.h
+++ b/services/surfaceflinger/ClientCache.h
@@ -36,7 +36,7 @@
 public:
     ClientCache();
 
-    void add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
+    bool add(const client_cache_t& cacheId, const sp<GraphicBuffer>& buffer);
     void erase(const client_cache_t& cacheId);
 
     sp<GraphicBuffer> get(const client_cache_t& cacheId);
@@ -48,7 +48,7 @@
         virtual void bufferErased(const client_cache_t& clientCacheId) = 0;
     };
 
-    void registerErasedRecipient(const client_cache_t& cacheId,
+    bool registerErasedRecipient(const client_cache_t& cacheId,
                                  const wp<ErasedRecipient>& recipient);
     void unregisterErasedRecipient(const client_cache_t& cacheId,
                                    const wp<ErasedRecipient>& recipient);
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 6f076ad..1c31ab9 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -118,6 +118,13 @@
         //
         // You can either "make dist tests" before flashing, or set this
         // option to false temporarily.
-        address: true,
+
+
+        // FIXME: ASAN build is broken for a while, but was not discovered
+        // since new PM silently suppressed ASAN. Temporarily turn off ASAN
+        // to unblock the compiler upgrade process.
+        // address: true,
+        // http://b/139747256
+        address: false,
     },
 }
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index cc5a5b5..7f47a2e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -24,6 +24,7 @@
 
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <gui/BufferQueue.h>
+#include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlTransportUtils.h>
 
 namespace android {
@@ -229,6 +230,7 @@
 
 void Composer::registerCallback(const sp<IComposerCallback>& callback)
 {
+    android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
     auto ret = mClient->registerCallback(callback);
     if (!ret.isOk()) {
         ALOGE("failed to register IComposerCallback");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f4284fe..dda15e9 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2040,20 +2040,20 @@
     InputWindowInfo info = mDrawingState.inputInfo;
 
     if (info.displayId == ADISPLAY_ID_NONE) {
-        info.displayId = mDrawingState.layerStack;
+        info.displayId = getLayerStack();
     }
 
     ui::Transform t = getTransform();
     const float xScale = t.sx();
     const float yScale = t.sy();
-    float xSurfaceInset = info.surfaceInset;
-    float ySurfaceInset = info.surfaceInset;
+    int32_t xSurfaceInset = info.surfaceInset;
+    int32_t ySurfaceInset = info.surfaceInset;
     if (xScale != 1.0f || yScale != 1.0f) {
-        info.windowXScale *= 1.0f / xScale;
-        info.windowYScale *= 1.0f / yScale;
+        info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f;
+        info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f;
         info.touchableRegion.scaleSelf(xScale, yScale);
-        xSurfaceInset *= xScale;
-        ySurfaceInset *= yScale;
+        xSurfaceInset = std::round(xSurfaceInset * xScale);
+        ySurfaceInset = std::round(ySurfaceInset * yScale);
     }
 
     // Transform layer size to screen space and inset it by surface insets.
@@ -2065,6 +2065,11 @@
         layerBounds = getCroppedBufferSize(getDrawingState());
     }
     layerBounds = t.transform(layerBounds);
+
+    // clamp inset to layer bounds
+    xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
+    ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
+
     layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
 
     // Input coordinate should match the layer bounds.
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 132b4cf..3b4d873 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_LAYER_H
 #define ANDROID_LAYER_H
 
-#include <sys/types.h>
-
 #include <compositionengine/LayerFE.h>
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -28,6 +26,7 @@
 #include <math/vec4.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
+#include <sys/types.h>
 #include <ui/FloatRect.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
@@ -44,16 +43,16 @@
 #include <vector>
 
 #include "Client.h"
+#include "ClientCache.h"
+#include "DisplayHardware/ComposerHal.h"
+#include "DisplayHardware/HWComposer.h"
 #include "FrameTracker.h"
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
+#include "RenderArea.h"
 #include "SurfaceFlinger.h"
 #include "TransactionCompletedThread.h"
 
-#include "DisplayHardware/ComposerHal.h"
-#include "DisplayHardware/HWComposer.h"
-#include "RenderArea.h"
-
 using namespace android::surfaceflinger;
 
 namespace android {
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 66906e9..07fdead 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -44,11 +44,14 @@
 enum class samplingStep {
     noWorkNeeded,
     idleTimerWaiting,
+    waitForQuietFrame,
     waitForZeroPhase,
     waitForSamplePhase,
     sample
 };
 
+constexpr auto timeForRegionSampling = 5000000ns;
+constexpr auto maxRegionSamplingSkips = 10;
 constexpr auto defaultRegionSamplingOffset = -3ms;
 constexpr auto defaultRegionSamplingPeriod = 100ms;
 constexpr auto defaultRegionSamplingTimerTimeout = 100ms;
@@ -215,9 +218,9 @@
 void RegionSamplingThread::checkForStaleLuma() {
     std::lock_guard lock(mThreadControlMutex);
 
-    if (mDiscardedFrames) {
+    if (mDiscardedFrames > 0) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForZeroPhase));
-        mDiscardedFrames = false;
+        mDiscardedFrames = 0;
         mPhaseCallback->startVsyncListener();
     }
 }
@@ -235,13 +238,25 @@
     auto now = std::chrono::nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     if (lastSampleTime + mTunables.mSamplingPeriod > now) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::idleTimerWaiting));
-        mDiscardedFrames = true;
+        if (mDiscardedFrames == 0) mDiscardedFrames++;
         return;
     }
+    if (mDiscardedFrames < maxRegionSamplingSkips) {
+        // If there is relatively little time left for surfaceflinger
+        // until the next vsync deadline, defer this sampling work
+        // to a later frame, when hopefully there will be more time.
+        DisplayStatInfo stats;
+        mScheduler.getDisplayStatInfo(&stats);
+        if (std::chrono::nanoseconds(stats.vsyncTime) - now < timeForRegionSampling) {
+            ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForQuietFrame));
+            mDiscardedFrames++;
+            return;
+        }
+    }
 
     ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::sample));
 
-    mDiscardedFrames = false;
+    mDiscardedFrames = 0;
     lastSampleTime = now;
 
     mIdleTimer.reset();
@@ -258,7 +273,7 @@
 
 namespace {
 // Using Rec. 709 primaries
-float getLuma(float r, float g, float b) {
+inline float getLuma(float r, float g, float b) {
     constexpr auto rec709_red_primary = 0.2126f;
     constexpr auto rec709_green_primary = 0.7152f;
     constexpr auto rec709_blue_primary = 0.0722f;
@@ -293,10 +308,10 @@
         const uint32_t* rowBase = data + row * stride;
         for (int32_t column = area.left; column < area.right; ++column) {
             uint32_t pixel = rowBase[column];
-            const float r = (pixel & 0xFF) / 255.0f;
-            const float g = ((pixel >> 8) & 0xFF) / 255.0f;
-            const float b = ((pixel >> 16) & 0xFF) / 255.0f;
-            const uint8_t luma = std::round(getLuma(r, g, b) * 255.0f);
+            const float r = pixel & 0xFF;
+            const float g = (pixel >> 8) & 0xFF;
+            const float b = (pixel >> 16) & 0xFF;
+            const uint8_t luma = std::round(getLuma(r, g, b));
             ++brightnessBuckets[luma];
             if (brightnessBuckets[luma] > majoritySampleNum) return luma / 255.0f;
         }
@@ -342,9 +357,19 @@
     }
 
     const auto device = mFlinger.getDefaultDisplayDevice();
-    const auto display = device->getCompositionDisplay();
-    const auto state = display->getState();
-    const auto orientation = static_cast<ui::Transform::orientation_flags>(state.orientation);
+    const auto orientation = [](uint32_t orientation) {
+        switch (orientation) {
+            default:
+            case DisplayState::eOrientationDefault:
+                return ui::Transform::ROT_0;
+            case DisplayState::eOrientation90:
+                return ui::Transform::ROT_90;
+            case DisplayState::eOrientation180:
+                return ui::Transform::ROT_180;
+            case DisplayState::eOrientation270:
+                return ui::Transform::ROT_270;
+        }
+    }(device->getOrientation());
 
     std::vector<RegionSamplingThread::Descriptor> descriptors;
     Region sampleRegion;
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 3c6fcf3..96ffe20 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -117,7 +117,7 @@
     std::condition_variable_any mCondition;
     bool mRunning GUARDED_BY(mThreadControlMutex) = true;
     bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false;
-    bool mDiscardedFrames GUARDED_BY(mThreadControlMutex) = false;
+    uint32_t mDiscardedFrames GUARDED_BY(mThreadControlMutex) = 0;
     std::chrono::nanoseconds lastSampleTime GUARDED_BY(mThreadControlMutex);
 
     std::mutex mSamplingMutex;
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 95ff9d0..0c94052 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -92,9 +92,12 @@
         mPeriod = period;
         if (!mModelLocked && referenceTimeChanged) {
             for (auto& eventListener : mEventListeners) {
-                eventListener.mHasFired = false;
-                eventListener.mLastEventTime =
-                        mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
+                eventListener.mLastEventTime = mReferenceTime + mPhase + eventListener.mPhase;
+                // If mLastEventTime is after mReferenceTime (can happen when positive phase offsets
+                // are used) we treat it as like it happened in previous period.
+                if (eventListener.mLastEventTime > mReferenceTime) {
+                    eventListener.mLastEventTime -= mPeriod;
+                }
             }
         }
         if (mTraceDetailedInfo) {
@@ -123,13 +126,6 @@
 
     void unlockModel() {
         Mutex::Autolock lock(mMutex);
-        if (mModelLocked) {
-            for (auto& eventListener : mEventListeners) {
-                if (eventListener.mLastEventTime > mReferenceTime) {
-                    eventListener.mHasFired = true;
-                }
-            }
-        }
         mModelLocked = false;
         ATRACE_INT("DispSync:ModelLocked", mModelLocked);
     }
@@ -259,10 +255,6 @@
             listener.mLastCallbackTime = lastCallbackTime;
         }
 
-        if (!mModelLocked && listener.mLastEventTime > mReferenceTime) {
-            listener.mHasFired = true;
-        }
-
         mEventListeners.push_back(listener);
 
         mCond.signal();
@@ -300,12 +292,8 @@
                 // new offset to allow for a seamless offset change without double-firing or
                 // skipping.
                 nsecs_t diff = oldPhase - phase;
-                if (diff > mPeriod / 2) {
-                    diff -= mPeriod;
-                } else if (diff < -mPeriod / 2) {
-                    diff += mPeriod;
-                }
                 eventListener.mLastEventTime -= diff;
+                eventListener.mLastCallbackTime -= diff;
                 mCond.signal();
                 return NO_ERROR;
             }
@@ -320,7 +308,6 @@
         nsecs_t mLastEventTime;
         nsecs_t mLastCallbackTime;
         DispSync::Callback* mCallback;
-        bool mHasFired = false;
     };
 
     struct CallbackInvocation {
@@ -368,12 +355,7 @@
                           eventListener.mName);
                     continue;
                 }
-                if (eventListener.mHasFired && !mModelLocked) {
-                    eventListener.mLastEventTime = t;
-                    ALOGV("[%s] [%s] Skipping event due to already firing", mName,
-                          eventListener.mName);
-                    continue;
-                }
+
                 CallbackInvocation ci;
                 ci.mCallback = eventListener.mCallback;
                 ci.mEventTime = t;
@@ -382,7 +364,6 @@
                 callbackInvocations.push_back(ci);
                 eventListener.mLastEventTime = t;
                 eventListener.mLastCallbackTime = now;
-                eventListener.mHasFired = true;
             }
         }
 
@@ -687,7 +668,13 @@
         nsecs_t durationSum = 0;
         nsecs_t minDuration = INT64_MAX;
         nsecs_t maxDuration = 0;
-        for (size_t i = 1; i < mNumResyncSamples; i++) {
+        // We skip the first 2 samples because the first vsync duration on some
+        // devices may be much more inaccurate than on other devices, e.g. due
+        // to delays in ramping up from a power collapse. By doing so this
+        // actually increases the accuracy of the DispSync model even though
+        // we're effectively relying on fewer sample points.
+        static constexpr size_t numSamplesSkipped = 2;
+        for (size_t i = numSamplesSkipped; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
             size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
             nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
@@ -698,15 +685,14 @@
 
         // Exclude the min and max from the average
         durationSum -= minDuration + maxDuration;
-        mPeriod = durationSum / (mNumResyncSamples - 3);
+        mPeriod = durationSum / (mNumResyncSamples - numSamplesSkipped - 2);
 
         ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
 
         double sampleAvgX = 0;
         double sampleAvgY = 0;
         double scale = 2.0 * M_PI / double(mPeriod);
-        // Intentionally skip the first sample
-        for (size_t i = 1; i < mNumResyncSamples; i++) {
+        for (size_t i = numSamplesSkipped; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
             nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
             double samplePhase = double(sample % mPeriod) * scale;
@@ -714,8 +700,8 @@
             sampleAvgY += sin(samplePhase);
         }
 
-        sampleAvgX /= double(mNumResyncSamples - 1);
-        sampleAvgY /= double(mNumResyncSamples - 1);
+        sampleAvgX /= double(mNumResyncSamples - numSamplesSkipped);
+        sampleAvgY /= double(mNumResyncSamples - numSamplesSkipped);
 
         mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
 
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 00948ae..5faf46e 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -27,18 +27,23 @@
 
 namespace android {
 
-DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset,
+                               nsecs_t offsetThresholdForNextVsync, bool traceVsync,
                                const char* name)
       : mName(name),
         mTraceVsync(traceVsync),
         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
         mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
+        mVsyncOffsetLabel(base::StringPrintf("VsyncOffset-%s", name)),
+        mVsyncNegativeOffsetLabel(base::StringPrintf("VsyncNegativeOffset-%s", name)),
         mDispSync(dispSync),
-        mPhaseOffset(phaseOffset) {}
+        mPhaseOffset(phaseOffset),
+        mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
 
 void DispSyncSource::setVSyncEnabled(bool enable) {
     std::lock_guard lock(mVsyncMutex);
     if (enable) {
+        tracePhaseOffset();
         status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                    static_cast<DispSync::Callback*>(this),
                                                    mLastCallbackTime);
@@ -64,16 +69,21 @@
 
 void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
     std::lock_guard lock(mVsyncMutex);
-
-    // Normalize phaseOffset to [0, period)
-    auto period = mDispSync->getPeriod();
-    phaseOffset %= period;
-    if (phaseOffset < 0) {
-        // If we're here, then phaseOffset is in (-period, 0). After this
-        // operation, it will be in (0, period)
-        phaseOffset += period;
+    const nsecs_t period = mDispSync->getPeriod();
+    // Check if offset should be handled as negative
+    if (phaseOffset >= mOffsetThresholdForNextVsync) {
+        phaseOffset -= period;
     }
+
+    // Normalize phaseOffset to [-period, period)
+    const int numPeriods = phaseOffset / period;
+    phaseOffset -= numPeriods * period;
+    if (mPhaseOffset == phaseOffset) {
+        return;
+    }
+
     mPhaseOffset = phaseOffset;
+    tracePhaseOffset();
 
     // If we're not enabled, we don't need to mess with the listeners
     if (!mEnabled) {
@@ -92,11 +102,11 @@
     {
         std::lock_guard lock(mCallbackMutex);
         callback = mCallback;
+    }
 
-        if (mTraceVsync) {
-            mValue = (mValue + 1) % 2;
-            ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
-        }
+    if (mTraceVsync) {
+        mValue = (mValue + 1) % 2;
+        ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
     }
 
     if (callback != nullptr) {
@@ -104,4 +114,14 @@
     }
 }
 
-} // namespace android
\ No newline at end of file
+void DispSyncSource::tracePhaseOffset() {
+    if (mPhaseOffset > 0) {
+        ATRACE_INT(mVsyncOffsetLabel.c_str(), mPhaseOffset);
+        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), 0);
+    } else {
+        ATRACE_INT(mVsyncOffsetLabel.c_str(), 0);
+        ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), -mPhaseOffset);
+    }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 4759699..50560a5 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -25,7 +25,8 @@
 
 class DispSyncSource final : public VSyncSource, private DispSync::Callback {
 public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, nsecs_t offsetThresholdForNextVsync,
+                   bool traceVsync, const char* name);
 
     ~DispSyncSource() override = default;
 
@@ -38,12 +39,16 @@
     // The following method is the implementation of the DispSync::Callback.
     virtual void onDispSyncEvent(nsecs_t when);
 
+    void tracePhaseOffset() REQUIRES(mVsyncMutex);
+
     const char* const mName;
     int mValue = 0;
 
     const bool mTraceVsync;
     const std::string mVsyncOnLabel;
     const std::string mVsyncEventLabel;
+    const std::string mVsyncOffsetLabel;
+    const std::string mVsyncNegativeOffsetLabel;
     nsecs_t mLastCallbackTime GUARDED_BY(mVsyncMutex) = 0;
 
     DispSync* mDispSync;
@@ -53,7 +58,8 @@
 
     std::mutex mVsyncMutex;
     nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+    const nsecs_t mOffsetThresholdForNextVsync;
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
 };
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 05bad4d..9d1f777 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -76,6 +76,10 @@
             return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
                                 ", count=%u}",
                                 event.header.displayId, event.vsync.count);
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
+                                ", configId=%u}",
+                                event.header.displayId, event.config.configId);
         default:
             return "Event{}";
     }
@@ -107,8 +111,10 @@
 } // namespace
 
 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
-                                             ResyncCallback resyncCallback)
+                                             ResyncCallback resyncCallback,
+                                             ISurfaceComposer::ConfigChanged configChanged)
       : resyncCallback(std::move(resyncCallback)),
+        configChanged(configChanged),
         mEventThread(eventThread),
         mChannel(gui::BitTube::DefaultSize) {}
 
@@ -203,8 +209,10 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
-    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
+sp<EventThreadConnection> EventThread::createEventConnection(
+        ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
+    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
+                                     configChanged);
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -398,9 +406,11 @@
                                      const sp<EventThreadConnection>& connection) const {
     switch (event.header.type) {
         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
-        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
             return true;
 
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return connection->configChanged == ISurfaceComposer::eConfigChangedDispatch;
+
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
             switch (connection->vsyncRequest) {
                 case VSyncRequest::None:
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 61530c6..dd23b88 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -69,7 +69,8 @@
 
 class EventThreadConnection : public BnDisplayEventConnection {
 public:
-    EventThreadConnection(EventThread*, ResyncCallback);
+    EventThreadConnection(EventThread*, ResyncCallback,
+                          ISurfaceComposer::ConfigChanged configChanged);
     virtual ~EventThreadConnection();
 
     virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -82,6 +83,7 @@
     const ResyncCallback resyncCallback;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
+    const ISurfaceComposer::ConfigChanged configChanged;
 
 private:
     virtual void onFirstRef();
@@ -93,7 +95,8 @@
 public:
     virtual ~EventThread();
 
-    virtual sp<EventThreadConnection> createEventConnection(ResyncCallback) const = 0;
+    virtual sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const = 0;
 
     // called before the screen is turned off from main thread
     virtual void onScreenReleased() = 0;
@@ -128,7 +131,8 @@
     EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
     ~EventThread();
 
-    sp<EventThreadConnection> createEventConnection(ResyncCallback) const override;
+    sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const override;
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 1db43a3..f80c233 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -46,11 +46,13 @@
 LayerHistory::~LayerHistory() = default;
 
 std::unique_ptr<LayerHistory::LayerHandle> LayerHistory::createLayer(const std::string name,
+                                                                     float minRefreshRate,
                                                                      float maxRefreshRate) {
     const int64_t id = sNextId++;
 
     std::lock_guard lock(mLock);
-    mInactiveLayerInfos.emplace(id, std::make_shared<LayerInfo>(name, maxRefreshRate));
+    mInactiveLayerInfos.emplace(id,
+                                std::make_shared<LayerInfo>(name, minRefreshRate, maxRefreshRate));
     return std::make_unique<LayerHistory::LayerHandle>(*this, id);
 }
 
@@ -173,5 +175,18 @@
     }
 }
 
+void LayerHistory::clearHistory() {
+    std::lock_guard lock(mLock);
+
+    auto it = mActiveLayerInfos.begin();
+    while (it != mActiveLayerInfos.end()) {
+        auto id = it->first;
+        auto layerInfo = it->second;
+        layerInfo->clearHistory();
+        mInactiveLayerInfos.insert({id, layerInfo});
+        it = mActiveLayerInfos.erase(it);
+    }
+}
+
 } // namespace scheduler
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index adc5ce5..5598cc1 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -53,7 +53,8 @@
     ~LayerHistory();
 
     // When the layer is first created, register it.
-    std::unique_ptr<LayerHandle> createLayer(const std::string name, float maxRefreshRate);
+    std::unique_ptr<LayerHandle> createLayer(const std::string name, float minRefreshRate,
+                                             float maxRefreshRate);
 
     // Method for inserting layers and their requested present time into the unordered map.
     void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr);
@@ -64,6 +65,9 @@
     // layers. See go/content-fps-detection-in-scheduler for more information.
     std::pair<float, bool> getDesiredRefreshRateAndHDR();
 
+    // Clears all layer history.
+    void clearHistory();
+
     // Removes the handle and the object from the map.
     void destroyLayer(const int64_t id);
 
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 95d7d31..723d71f 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -24,9 +24,10 @@
 namespace android {
 namespace scheduler {
 
-LayerInfo::LayerInfo(const std::string name, float maxRefreshRate)
+LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate)
       : mName(name),
         mMinRefreshDuration(1e9f / maxRefreshRate),
+        mLowActivityRefreshDuration(1e9f / minRefreshRate),
         mRefreshRateHistory(mMinRefreshDuration) {}
 
 LayerInfo::~LayerInfo() = default;
@@ -38,12 +39,19 @@
     mLastUpdatedTime = std::max(lastPresentTime, systemTime());
     mPresentTimeHistory.insertPresentTime(mLastUpdatedTime);
 
+    if (mLastPresentTime == 0) {
+        // First frame
+        mLastPresentTime = lastPresentTime;
+        return;
+    }
+
     const nsecs_t timeDiff = lastPresentTime - mLastPresentTime;
     mLastPresentTime = lastPresentTime;
     // Ignore time diff that are too high - those are stale values
-    if (timeDiff > TIME_EPSILON_NS.count()) return;
-    const nsecs_t refreshDuration = (timeDiff > 0) ? timeDiff : mMinRefreshDuration;
-    mRefreshRateHistory.insertRefreshRate(refreshDuration);
+    if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return;
+    const nsecs_t refreshDuration = std::max(timeDiff, mMinRefreshDuration);
+    const int fps = 1e9f / refreshDuration;
+    mRefreshRateHistory.insertRefreshRate(fps);
 }
 
 } // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 02b6aef..17afdda 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -46,7 +46,7 @@
     public:
         explicit RefreshRateHistory(nsecs_t minRefreshDuration)
               : mMinRefreshDuration(minRefreshDuration) {}
-        void insertRefreshRate(nsecs_t refreshRate) {
+        void insertRefreshRate(int refreshRate) {
             mElements.push_back(refreshRate);
             if (mElements.size() > HISTORY_SIZE) {
                 mElements.pop_front();
@@ -54,13 +54,13 @@
         }
 
         float getRefreshRateAvg() const {
-            nsecs_t refreshDuration = mMinRefreshDuration;
-            if (mElements.size() == HISTORY_SIZE) {
-                refreshDuration = scheduler::calculate_mean(mElements);
+            if (mElements.empty()) {
+                return 1e9f / mMinRefreshDuration;
             }
 
-            return 1e9f / refreshDuration;
+            return scheduler::calculate_mean(mElements);
         }
+
         void clearHistory() { mElements.clear(); }
 
     private:
@@ -86,13 +86,43 @@
         // Checks whether the present time that was inserted HISTORY_SIZE ago is within a
         // certain threshold: TIME_EPSILON_NS.
         bool isRelevant() const {
-            const int64_t obsoleteEpsilon = systemTime() - scheduler::TIME_EPSILON_NS.count();
-            // The layer had to publish at least HISTORY_SIZE of updates, and the first
-            // update should not be older than TIME_EPSILON_NS nanoseconds.
-            if (mElements.size() == HISTORY_SIZE &&
-                mElements.at(HISTORY_SIZE - 1) > obsoleteEpsilon) {
+            if (mElements.size() < 2) {
+                return false;
+            }
+
+            // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates
+            if (mElements.size() != HISTORY_SIZE &&
+                mElements.at(mElements.size() - 1) - mElements.at(0) < HISTORY_TIME.count()) {
+                return false;
+            }
+
+            // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds.
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count();
+            if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) {
+                return false;
+            }
+
+            return true;
+        }
+
+        bool isLowActivityLayer() const {
+            // We want to make sure that we received more than two frames from the layer
+            // in order to check low activity.
+            if (mElements.size() < scheduler::LOW_ACTIVITY_BUFFERS + 1) {
+                return false;
+            }
+
+            const int64_t obsoleteEpsilon =
+                    systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count();
+            // Check the frame before last to determine whether there is low activity.
+            // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending
+            // infrequent updates.
+            if (mElements.at(mElements.size() - (scheduler::LOW_ACTIVITY_BUFFERS + 1)) <
+                obsoleteEpsilon) {
                 return true;
             }
+
             return false;
         }
 
@@ -100,11 +130,12 @@
 
     private:
         std::deque<nsecs_t> mElements;
-        static constexpr size_t HISTORY_SIZE = 10;
+        static constexpr size_t HISTORY_SIZE = 90;
+        static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s;
     };
 
 public:
-    LayerInfo(const std::string name, float maxRefreshRate);
+    LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate);
     ~LayerInfo();
 
     LayerInfo(const LayerInfo&) = delete;
@@ -134,6 +165,10 @@
     // Calculate the average refresh rate.
     float getDesiredRefreshRate() const {
         std::lock_guard lock(mLock);
+
+        if (mPresentTimeHistory.isLowActivityLayer()) {
+            return 1e9f / mLowActivityRefreshDuration;
+        }
         return mRefreshRateHistory.getRefreshRateAvg();
     }
 
@@ -165,6 +200,7 @@
 private:
     const std::string mName;
     const nsecs_t mMinRefreshDuration;
+    const nsecs_t mLowActivityRefreshDuration;
     mutable std::mutex mLock;
     nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0;
     nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index baf900d..fcb307f 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,7 +96,8 @@
     }
 
     mEventThread = eventThread;
-    mEvents = eventThread->createEventConnection(std::move(resyncCallback));
+    mEvents = eventThread->createEventConnection(std::move(resyncCallback),
+                                                 ISurfaceComposer::eConfigChangedSuppress);
     mEvents->stealReceiveChannel(&mEventTube);
     mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                    this);
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 276bce1..8a2604f 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -25,6 +25,7 @@
 
 namespace scheduler {
 
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
 PhaseOffsets::~PhaseOffsets() = default;
 
 namespace impl {
@@ -72,25 +73,32 @@
     property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
     const int phaseOffsetThresholdForNextVsyncNs = atoi(value);
 
-    mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
-                                                              : sfVsyncPhaseOffsetNs,
-                                        earlyAppOffsetNs != -1 ? earlyAppOffsetNs
-                                                               : vsyncPhaseOffsetNs};
-    mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs
-                                                                  : sfVsyncPhaseOffsetNs,
-                                          earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs
-                                                                   : vsyncPhaseOffsetNs};
-    mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
+    Offsets defaultOffsets;
+    Offsets highFpsOffsets;
+    defaultOffsets.early = {RefreshRateType::DEFAULT,
+                            earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+                            earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+    defaultOffsets.earlyGl = {RefreshRateType::DEFAULT,
+                              earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+                              earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+    defaultOffsets.late = {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
 
-    mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
-                                                                  : highFpsLateSfOffsetNs,
-                                     highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
-                                                                   : highFpsLateAppOffsetNs};
-    mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
-                                                                      : highFpsLateSfOffsetNs,
-                                       highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
-                                                                       : highFpsLateAppOffsetNs};
-    mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
+    highFpsOffsets.early = {RefreshRateType::PERFORMANCE,
+                            highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
+                                                         : highFpsLateSfOffsetNs,
+                            highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+                                                          : highFpsLateAppOffsetNs};
+    highFpsOffsets.earlyGl = {RefreshRateType::PERFORMANCE,
+                              highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+                                                             : highFpsLateSfOffsetNs,
+                              highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+                                                              : highFpsLateAppOffsetNs};
+    highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
+                           highFpsLateAppOffsetNs};
+
+    mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
+    mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
+    mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
 
     mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
             ? phaseOffsetThresholdForNextVsyncNs
@@ -99,12 +107,7 @@
 
 PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
         android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
-    switch (refreshRateType) {
-        case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
-            return mHighRefreshRateOffsets;
-        default:
-            return mDefaultRefreshRateOffsets;
-    }
+    return mOffsets.at(refreshRateType);
 }
 
 void PhaseOffsets::dump(std::string& result) const {
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index dc71e6e..2b5c2f1 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <cinttypes>
+#include <unordered_map>
 
 #include "RefreshRateConfigs.h"
 #include "VSyncModulator.h"
@@ -79,14 +80,10 @@
     void dump(std::string& result) const override;
 
 private:
-    Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
-    Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
-
     std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
             RefreshRateConfigs::RefreshRateType::DEFAULT;
 
-    Offsets mDefaultRefreshRateOffsets;
-    Offsets mHighRefreshRateOffsets;
+    std::unordered_map<RefreshRateConfigs::RefreshRateType, Offsets> mOffsets;
     nsecs_t mOffsetThresholdForNextVsync;
 };
 } // namespace impl
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1d899df..8da5612 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -76,6 +76,7 @@
     mSupportKernelTimer = support_kernel_idle_timer(false);
 
     mSetTouchTimerMs = set_touch_timer_ms(0);
+    mSetDisplayPowerTimerMs = set_display_power_timer_ms(0);
 
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.set_idle_timer_ms", value, "0");
@@ -110,26 +111,40 @@
                                                        [this] { expiredTouchTimerCallback(); });
         mTouchTimer->start();
     }
+
+    if (mSetDisplayPowerTimerMs > 0) {
+        mDisplayPowerTimer =
+                std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(
+                                                               mSetDisplayPowerTimerMs),
+                                                       [this] { resetDisplayPowerTimerCallback(); },
+                                                       [this] {
+                                                           expiredDisplayPowerTimerCallback();
+                                                       });
+        mDisplayPowerTimer->start();
+    }
 }
 
 Scheduler::~Scheduler() {
     // Ensure the IdleTimer thread is joined before we start destroying state.
+    mDisplayPowerTimer.reset();
     mTouchTimer.reset();
     mIdleTimer.reset();
 }
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+        const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
+        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,
-                            std::move(interceptCallback));
+                            offsetThresholdForNextVsync, std::move(interceptCallback));
 
     auto eventThreadConnection =
-            createConnectionInternal(eventThread.get(), std::move(resyncCallback));
+            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+                                     ISurfaceComposer::eConfigChangedSuppress);
     mConnections.emplace(id,
                          std::make_unique<Connection>(new ConnectionHandle(id),
                                                       eventThreadConnection,
@@ -138,24 +153,28 @@
 }
 
 std::unique_ptr<EventThread> Scheduler::makeEventThread(
-        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+        nsecs_t offsetThresholdForNextVsync,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     std::unique_ptr<VSyncSource> eventThreadSource =
-            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, offsetThresholdForNextVsync,
+                                             true, connectionName);
     return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
                                                std::move(interceptCallback), connectionName);
 }
 
-sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
-                                                              ResyncCallback&& resyncCallback) {
-    return eventThread->createEventConnection(std::move(resyncCallback));
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+        EventThread* eventThread, ResyncCallback&& resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
+    return eventThread->createEventConnection(std::move(resyncCallback), configChanged);
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
     RETURN_VALUE_IF_INVALID(nullptr);
     return createConnectionInternal(mConnections[handle->id]->thread.get(),
-                                    std::move(resyncCallback));
+                                    std::move(resyncCallback), configChanged);
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -255,7 +274,7 @@
 }
 
 void Scheduler::VsyncState::resync(const GetVsyncPeriod& getVsyncPeriod) {
-    static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+    static constexpr nsecs_t kIgnoreDelay = ms2ns(750);
 
     const nsecs_t now = systemTime();
     const nsecs_t last = lastResyncTime.exchange(now);
@@ -324,8 +343,11 @@
             : RefreshRateType::PERFORMANCE;
 
     const auto refreshRate = mRefreshRateConfigs.getRefreshRate(refreshRateType);
-    const uint32_t fps = (refreshRate) ? refreshRate->fps : 0;
-    return mLayerHistory.createLayer(name, fps);
+    const uint32_t performanceFps = (refreshRate) ? refreshRate->fps : 0;
+
+    const auto defaultRefreshRate = mRefreshRateConfigs.getRefreshRate(RefreshRateType::DEFAULT);
+    const uint32_t defaultFps = (defaultRefreshRate) ? defaultRefreshRate->fps : 0;
+    return mLayerHistory.createLayer(name, defaultFps, performanceFps);
 }
 
 void Scheduler::addLayerPresentTimeAndHDR(
@@ -371,11 +393,17 @@
 }
 
 void Scheduler::setChangeRefreshRateCallback(
-        const ChangeRefreshRateCallback& changeRefreshRateCallback) {
+        const ChangeRefreshRateCallback&& changeRefreshRateCallback) {
     std::lock_guard<std::mutex> lock(mCallbackLock);
     mChangeRefreshRateCallback = changeRefreshRateCallback;
 }
 
+void Scheduler::setGetCurrentRefreshRateTypeCallback(
+        const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateTypeCallback) {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    mGetCurrentRefreshRateTypeCallback = getCurrentRefreshRateTypeCallback;
+}
+
 void Scheduler::setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod) {
     std::lock_guard<std::mutex> lock(mCallbackLock);
     mGetVsyncPeriod = getVsyncPeriod;
@@ -404,43 +432,81 @@
     if (mSupportKernelTimer) {
         resetIdleTimer();
     }
+
+    // Touch event will boost the refresh rate to performance.
+    // Clear Layer History to get fresh FPS detection
+    mLayerHistory.clearHistory();
+}
+
+void Scheduler::setDisplayPowerState(bool normal) {
+    {
+        std::lock_guard<std::mutex> lock(mFeatureStateLock);
+        mIsDisplayPowerStateNormal = normal;
+    }
+
+    if (mDisplayPowerTimer) {
+        mDisplayPowerTimer->reset();
+    }
+
+    // Display Power event will boost the refresh rate to performance.
+    // Clear Layer History to get fresh FPS detection
+    mLayerHistory.clearHistory();
 }
 
 void Scheduler::resetTimerCallback() {
-    timerChangeRefreshRate(IdleTimerState::RESET);
+    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::RESET, false);
     ATRACE_INT("ExpiredIdleTimer", 0);
 }
 
 void Scheduler::resetKernelTimerCallback() {
     ATRACE_INT("ExpiredKernelIdleTimer", 0);
     std::lock_guard<std::mutex> lock(mCallbackLock);
-    if (mGetVsyncPeriod) {
-        resyncToHardwareVsync(true, mGetVsyncPeriod());
+    if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+        // If we're not in performance mode then the kernel timer shouldn't do
+        // anything, as the refresh rate during DPU power collapse will be the
+        // same.
+        if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
+            resyncToHardwareVsync(true, mGetVsyncPeriod());
+        }
     }
 }
 
 void Scheduler::expiredTimerCallback() {
-    timerChangeRefreshRate(IdleTimerState::EXPIRED);
+    handleTimerStateChanged(&mCurrentIdleTimerState, IdleTimerState::EXPIRED, false);
     ATRACE_INT("ExpiredIdleTimer", 1);
 }
 
 void Scheduler::resetTouchTimerCallback() {
-    // We do not notify the applications about config changes when idle timer is reset.
-    touchChangeRefreshRate(TouchState::ACTIVE);
+    handleTimerStateChanged(&mCurrentTouchState, TouchState::ACTIVE, true);
     ATRACE_INT("TouchState", 1);
 }
 
 void Scheduler::expiredTouchTimerCallback() {
-    // We do not notify the applications about config changes when idle timer expires.
-    touchChangeRefreshRate(TouchState::INACTIVE);
+    handleTimerStateChanged(&mCurrentTouchState, TouchState::INACTIVE, true);
     ATRACE_INT("TouchState", 0);
 }
 
+void Scheduler::resetDisplayPowerTimerCallback() {
+    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::RESET, true);
+    ATRACE_INT("ExpiredDisplayPowerTimer", 0);
+}
+
+void Scheduler::expiredDisplayPowerTimerCallback() {
+    handleTimerStateChanged(&mDisplayPowerTimerState, DisplayPowerTimerState::EXPIRED, true);
+    ATRACE_INT("ExpiredDisplayPowerTimer", 1);
+}
+
 void Scheduler::expiredKernelTimerCallback() {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
     ATRACE_INT("ExpiredKernelIdleTimer", 1);
-    // Disable HW Vsync if the timer expired, as we don't need it
-    // enabled if we're not pushing frames.
-    disableHardwareVsync(false);
+    if (mGetCurrentRefreshRateTypeCallback) {
+        if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
+            // Disable HW Vsync if the timer expired, as we don't need it
+            // enabled if we're not pushing frames, and if we're in PERFORMANCE
+            // mode then we'll need to re-update the DispSync model anyways.
+            disableHardwareVsync(false);
+        }
+    }
 }
 
 std::string Scheduler::doDump() {
@@ -450,39 +516,23 @@
     return stream.str();
 }
 
-void Scheduler::timerChangeRefreshRate(IdleTimerState idleTimerState) {
-    RefreshRateType newRefreshRateType;
-    {
-        std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        if (mCurrentIdleTimerState == idleTimerState) {
-            return;
-        }
-        mCurrentIdleTimerState = idleTimerState;
-        newRefreshRateType = calculateRefreshRateType();
-        if (mRefreshRateType == newRefreshRateType) {
-            return;
-        }
-        mRefreshRateType = newRefreshRateType;
-    }
-    changeRefreshRate(newRefreshRateType, ConfigEvent::None);
-}
-
-void Scheduler::touchChangeRefreshRate(TouchState touchState) {
+template <class T>
+void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) {
     ConfigEvent event = ConfigEvent::None;
     RefreshRateType newRefreshRateType;
     {
         std::lock_guard<std::mutex> lock(mFeatureStateLock);
-        if (mCurrentTouchState == touchState) {
+        if (*currentState == newState) {
             return;
         }
-        mCurrentTouchState = touchState;
+        *currentState = newState;
         newRefreshRateType = calculateRefreshRateType();
         if (mRefreshRateType == newRefreshRateType) {
             return;
         }
         mRefreshRateType = newRefreshRateType;
-        // Send an event in case that content detection is on as touch has a higher priority
-        if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) {
+        if (eventOnContentDetection &&
+            mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_ON) {
             event = ConfigEvent::Changed;
         }
     }
@@ -495,6 +545,12 @@
         return RefreshRateType::DEFAULT;
     }
 
+    // If Display Power is not in normal operation we want to be in performance mode.
+    // When coming back to normal mode, a grace period is given with DisplayPowerTimer
+    if (!mIsDisplayPowerStateNormal || mDisplayPowerTimerState == DisplayPowerTimerState::RESET) {
+        return RefreshRateType::PERFORMANCE;
+    }
+
     // As long as touch is active we want to be in performance mode
     if (mCurrentTouchState == TouchState::ACTIVE) {
         return RefreshRateType::PERFORMANCE;
@@ -510,22 +566,24 @@
         return RefreshRateType::PERFORMANCE;
     }
 
-    // Content detection is on, find the appropriate refresh rate
-    // Start with the smallest refresh rate which is within a margin of the content
-    RefreshRateType currRefreshRateType = RefreshRateType::PERFORMANCE;
-    constexpr float MARGIN = 0.05f;
-    auto iter = mRefreshRateConfigs.getRefreshRates().cbegin();
-    while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
-        if (iter->second->fps >= mContentRefreshRate * (1 - MARGIN)) {
-            currRefreshRateType = iter->first;
-            break;
-        }
-        ++iter;
+    // Content detection is on, find the appropriate refresh rate with minimal error
+    auto begin = mRefreshRateConfigs.getRefreshRates().cbegin();
+
+    // Skip POWER_SAVING config as it is not a real config
+    if (begin->first == RefreshRateType::POWER_SAVING) {
+        ++begin;
     }
+    auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRates().cend(),
+                            [rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
+                                return std::abs(l.second->fps - static_cast<float>(rate)) <
+                                        std::abs(r.second->fps - static_cast<float>(rate));
+                            });
+    RefreshRateType currRefreshRateType = iter->first;
 
     // Some content aligns better on higher refresh rate. For example for 45fps we should choose
     // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
     // align well with both
+    constexpr float MARGIN = 0.05f;
     float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
             float(mContentRefreshRate);
     if (std::abs(std::round(ratio) - ratio) > MARGIN) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index a32bd41..5d8bb4c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -49,6 +49,7 @@
     }
 
     using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+    using GetCurrentRefreshRateTypeCallback = std::function<RefreshRateType()>;
     using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
     using GetVsyncPeriod = std::function<nsecs_t()>;
 
@@ -96,12 +97,13 @@
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
-    sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
-                                          ResyncCallback,
+    sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
+                                          nsecs_t offsetThresholdForNextVsync, ResyncCallback,
                                           impl::EventThread::InterceptVSyncsCallback);
 
-    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
-                                                             ResyncCallback);
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            const sp<ConnectionHandle>& handle, ResyncCallback,
+            ISurfaceComposer::ConfigChanged configChanged);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -164,7 +166,9 @@
     // Updates FPS based on the most content presented.
     void updateFpsBasedOnContent();
     // Callback that gets invoked when Scheduler wants to change the refresh rate.
-    void setChangeRefreshRateCallback(const ChangeRefreshRateCallback& changeRefreshRateCallback);
+    void setChangeRefreshRateCallback(const ChangeRefreshRateCallback&& changeRefreshRateCallback);
+    void setGetCurrentRefreshRateTypeCallback(
+            const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateType);
     void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
 
     // Returns whether idle timer is enabled or not
@@ -176,6 +180,9 @@
     // Function that resets the touch timer.
     void notifyTouchEvent();
 
+    // Function that sets whether display power mode is normal or not.
+    void setDisplayPowerState(bool normal);
+
     // Returns relevant information about Scheduler for dumpsys purposes.
     std::string doDump();
 
@@ -184,7 +191,8 @@
 
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
-            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+            nsecs_t offsetThresholdForNextVsync,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
@@ -195,9 +203,11 @@
     enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF };
     enum class IdleTimerState { EXPIRED, RESET };
     enum class TouchState { INACTIVE, ACTIVE };
+    enum class DisplayPowerTimerState { EXPIRED, RESET };
 
     // Creates a connection on the given EventThread and forwards the given callbacks.
-    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&);
+    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+                                                       ISurfaceComposer::ConfigChanged);
 
     nsecs_t calculateAverage() const;
     void updateFrameSkipping(const int64_t skipCount);
@@ -218,12 +228,15 @@
     void resetTouchTimerCallback();
     // Function that is called when the touch timer expires.
     void expiredTouchTimerCallback();
+    // Function that is called when the display power timer resets.
+    void resetDisplayPowerTimerCallback();
+    // Function that is called when the display power timer expires.
+    void expiredDisplayPowerTimerCallback();
     // Sets vsync period.
     void setVsyncPeriod(const nsecs_t period);
-    // Idle timer feature's function to change the refresh rate.
-    void timerChangeRefreshRate(IdleTimerState idleTimerState);
-    // Touch timer feature's function to change the refresh rate.
-    void touchChangeRefreshRate(TouchState touchState);
+    // handles various timer features to change the refresh rate.
+    template <class T>
+    void handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection);
     // Calculate the new refresh rate type
     RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
     // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters.
@@ -279,7 +292,12 @@
     int64_t mSetTouchTimerMs = 0;
     std::unique_ptr<scheduler::IdleTimer> mTouchTimer;
 
+    // Timer used to monitor display power mode.
+    int64_t mSetDisplayPowerTimerMs = 0;
+    std::unique_ptr<scheduler::IdleTimer> mDisplayPowerTimer;
+
     std::mutex mCallbackLock;
+    GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
     ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
     GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
 
@@ -290,14 +308,17 @@
             ContentFeatureState::CONTENT_DETECTION_OFF;
     IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
     TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE;
+    DisplayPowerTimerState mDisplayPowerTimerState GUARDED_BY(mFeatureStateLock) =
+            DisplayPowerTimerState::EXPIRED;
     uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
     RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
     bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false;
+    bool mIsDisplayPowerStateNormal GUARDED_BY(mFeatureStateLock) = true;
 
     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
 
     // Global config to force HDR content to work on DEFAULT refreshRate
-    static constexpr bool mForceHDRContentToDefaultRefreshRate = true;
+    static constexpr bool mForceHDRContentToDefaultRefreshRate = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index 3bf3922..ac10f83 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -36,13 +36,18 @@
 static constexpr int SCREEN_OFF_CONFIG_ID = -1;
 static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
 
-// This number is used when we try to determine how long does a given layer stay relevant.
-// Currently it is set to 100ms, because that would indicate 10Hz rendering.
-static constexpr std::chrono::nanoseconds TIME_EPSILON_NS = 100ms;
-
 // This number is used when we try to determine how long do we keep layer information around
-// before we remove it. Currently it is set to 100ms.
-static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 100ms;
+// before we remove it. It is also used to determine how long the layer stays relevant.
+// This time period captures infrequent updates when playing YouTube video with static image,
+// or waiting idle in messaging app, when cursor is blinking.
+static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms;
+
+// Layer is considered low activity if the LOW_ACTIVITY_BUFFERS buffers come more than
+// LOW_ACTIVITY_EPSILON_NS  apart.
+// This is helping SF to vote for lower refresh rates when there is not activity
+// in screen.
+static constexpr int LOW_ACTIVITY_BUFFERS = 2;
+static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms;
 
 // Calculates the statistical mean (average) in the data structure (array, vector). The
 // function does not modify the contents of the array.
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
new file mode 100644
index 0000000..7a3bf8e
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "VSyncModulator.h"
+
+#include <cutils/properties.h>
+#include <utils/Trace.h>
+
+#include <cinttypes>
+#include <mutex>
+
+namespace android {
+
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+VSyncModulator::VSyncModulator() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.vsync_trace_detailed_info", value, "0");
+    mTraceDetailedInfo = atoi(value);
+    // Populate the offset map with some default offsets.
+    const Offsets defaultOffsets = {RefreshRateType::DEFAULT, 0, 0};
+    setPhaseOffsets(defaultOffsets, defaultOffsets, defaultOffsets, 0);
+}
+
+void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+                                     nsecs_t thresholdForNextVsync) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mOffsetMap.insert_or_assign(OffsetType::Early, early);
+    mOffsetMap.insert_or_assign(OffsetType::EarlyGl, earlyGl);
+    mOffsetMap.insert_or_assign(OffsetType::Late, late);
+    mThresholdForNextVsync = thresholdForNextVsync;
+    updateOffsetsLocked();
+}
+
+void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
+    if (transactionStart == Scheduler::TransactionStart::EARLY) {
+        mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+    }
+
+    // An early transaction stays an early transaction.
+    if (transactionStart == mTransactionStart ||
+        mTransactionStart == Scheduler::TransactionStart::EARLY) {
+        return;
+    }
+    mTransactionStart = transactionStart;
+    updateOffsets();
+}
+
+void VSyncModulator::onTransactionHandled() {
+    if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
+    mTransactionStart = Scheduler::TransactionStart::NORMAL;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeInitiated() {
+    if (mRefreshRateChangePending) {
+        return;
+    }
+    mRefreshRateChangePending = true;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeCompleted() {
+    if (!mRefreshRateChangePending) {
+        return;
+    }
+    mRefreshRateChangePending = false;
+    updateOffsets();
+}
+
+void VSyncModulator::onRefreshed(bool usedRenderEngine) {
+    bool updateOffsetsNeeded = false;
+    if (mRemainingEarlyFrameCount > 0) {
+        mRemainingEarlyFrameCount--;
+        updateOffsetsNeeded = true;
+    }
+    if (usedRenderEngine) {
+        mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
+        updateOffsetsNeeded = true;
+    } else if (mRemainingRenderEngineUsageCount > 0) {
+        mRemainingRenderEngineUsageCount--;
+        updateOffsetsNeeded = true;
+    }
+    if (updateOffsetsNeeded) {
+        updateOffsets();
+    }
+}
+
+VSyncModulator::Offsets VSyncModulator::getOffsets() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mOffsets;
+}
+
+VSyncModulator::Offsets VSyncModulator::getNextOffsets() {
+    return mOffsetMap.at(getNextOffsetType());
+}
+
+VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() {
+    // Early offsets are used if we're in the middle of a refresh rate
+    // change, or if we recently begin a transaction.
+    if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
+        mRefreshRateChangePending) {
+        return OffsetType::Early;
+    } else if (mRemainingRenderEngineUsageCount > 0) {
+        return OffsetType::EarlyGl;
+    } else {
+        return OffsetType::Late;
+    }
+}
+
+void VSyncModulator::updateOffsets() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    updateOffsetsLocked();
+}
+
+void VSyncModulator::updateOffsetsLocked() {
+    const Offsets desired = getNextOffsets();
+
+    if (mSfConnectionHandle != nullptr) {
+        mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
+    }
+
+    if (mAppConnectionHandle != nullptr) {
+        mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
+    }
+
+    flushOffsets();
+}
+
+void VSyncModulator::flushOffsets() {
+    OffsetType type = getNextOffsetType();
+    mOffsets = mOffsetMap.at(type);
+    if (!mTraceDetailedInfo) {
+        return;
+    }
+    ATRACE_INT("Vsync-EarlyOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early);
+    ATRACE_INT("Vsync-EarlyGLOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl);
+    ATRACE_INT("Vsync-LateOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late);
+    ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early);
+    ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl);
+    ATRACE_INT("Vsync-HighFpsLateOffsetsOn",
+               mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 21dad12..ddbd221 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,8 +16,6 @@
 
 #pragma once
 
-#include <utils/Errors.h>
-
 #include <cinttypes>
 #include <mutex>
 
@@ -35,12 +33,28 @@
     // sending new transactions.
     const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
 
+    // Number of frames we'll keep the early gl phase offsets once they are activated.
+    // This acts as a low-pass filter to avoid scenarios where we rapidly
+    // switch in and out of gl composition.
+    const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
+
 public:
+    VSyncModulator();
+
+    // Wrapper for a collection of surfaceflinger/app offsets for a particular
+    // configuration .
     struct Offsets {
+        scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
         nsecs_t sf;
         nsecs_t app;
     };
 
+    enum class OffsetType {
+        Early,
+        EarlyGl,
+        Late,
+    };
+
     // Sets the phase offsets
     //
     // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
@@ -51,31 +65,10 @@
     // appEarly: Like sfEarly, but for the app-vsync
     // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
     // appLate: The regular app vsync phase offset.
-    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
-        mEarlyOffsets = early;
-        mEarlyGlOffsets = earlyGl;
-        mLateOffsets = late;
+    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+                         nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);
 
-        if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
-            mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
-        }
-
-        if (mAppConnectionHandle && late.app != mOffsets.load().app) {
-            mScheduler->setPhaseOffset(mAppConnectionHandle, late.app);
-        }
-
-        mOffsets = late;
-    }
-
-    Offsets getEarlyOffsets() const { return mEarlyOffsets; }
-
-    Offsets getEarlyGlOffsets() const { return mEarlyGlOffsets; }
-
-    void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
-        mSfEventThread = sfEventThread;
-        mAppEventThread = appEventThread;
-    }
-
+    // Sets the scheduler and vsync connection handlers.
     void setSchedulerAndHandles(Scheduler* scheduler,
                                 Scheduler::ConnectionHandle* appConnectionHandle,
                                 Scheduler::ConnectionHandle* sfConnectionHandle) {
@@ -84,120 +77,57 @@
         mSfConnectionHandle = sfConnectionHandle;
     }
 
-    void setTransactionStart(Scheduler::TransactionStart transactionStart) {
-        if (transactionStart == Scheduler::TransactionStart::EARLY) {
-            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
-        }
+    // Signals that a transaction has started, and changes offsets accordingly.
+    void setTransactionStart(Scheduler::TransactionStart transactionStart);
 
-        // An early transaction stays an early transaction.
-        if (transactionStart == mTransactionStart ||
-            mTransactionStart == Scheduler::TransactionStart::EARLY) {
-            return;
-        }
-        mTransactionStart = transactionStart;
-        updateOffsets();
-    }
-
-    void onTransactionHandled() {
-        if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
-        mTransactionStart = Scheduler::TransactionStart::NORMAL;
-        updateOffsets();
-    }
+    // Signals that a transaction has been completed, so that we can finish
+    // special handling for a transaction.
+    void onTransactionHandled();
 
     // Called when we send a refresh rate change to hardware composer, so that
     // we can move into early offsets.
-    void onRefreshRateChangeInitiated() {
-        if (mRefreshRateChangePending) {
-            return;
-        }
-        mRefreshRateChangePending = true;
-        updateOffsets();
-    }
+    void onRefreshRateChangeInitiated();
 
     // Called when we detect from vsync signals that the refresh rate changed.
     // This way we can move out of early offsets if no longer necessary.
-    void onRefreshRateChangeCompleted() {
-        if (!mRefreshRateChangePending) {
-            return;
-        }
-        mRefreshRateChangePending = false;
-        updateOffsets();
-    }
+    void onRefreshRateChangeCompleted();
 
-    void onRefreshed(bool usedRenderEngine) {
-        bool updateOffsetsNeeded = false;
-        if (mRemainingEarlyFrameCount > 0) {
-            mRemainingEarlyFrameCount--;
-            updateOffsetsNeeded = true;
-        }
-        if (usedRenderEngine != mLastFrameUsedRenderEngine) {
-            mLastFrameUsedRenderEngine = usedRenderEngine;
-            updateOffsetsNeeded = true;
-        }
-        if (updateOffsetsNeeded) {
-            updateOffsets();
-        }
-    }
+    // Called when the display is presenting a new frame. usedRenderEngine
+    // should be set to true if RenderEngine was involved with composing the new
+    // frame.
+    void onRefreshed(bool usedRenderEngine);
 
-    Offsets getOffsets() {
-        // Early offsets are used if we're in the middle of a refresh rate
-        // change, or if we recently begin a transaction.
-        if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
-            mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
-            return mEarlyOffsets;
-        } else if (mLastFrameUsedRenderEngine) {
-            return mEarlyGlOffsets;
-        } else {
-            return mLateOffsets;
-        }
-    }
+    // Returns the offsets that we are currently using
+    Offsets getOffsets() EXCLUDES(mMutex);
 
 private:
-    void updateOffsets() {
-        const Offsets desired = getOffsets();
-        const Offsets current = mOffsets;
+    // Returns the next offsets that we should be using
+    Offsets getNextOffsets() REQUIRES(mMutex);
+    // Returns the next offset type that we should use.
+    OffsetType getNextOffsetType();
+    // Updates offsets and persists them into the scheduler framework.
+    void updateOffsets() EXCLUDES(mMutex);
+    void updateOffsetsLocked() REQUIRES(mMutex);
+    // Updates the internal offsets and offset type.
+    void flushOffsets() REQUIRES(mMutex);
 
-        bool changed = false;
-        if (desired.sf != current.sf) {
-            if (mSfConnectionHandle != nullptr) {
-                mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
-            } else {
-                mSfEventThread->setPhaseOffset(desired.sf);
-            }
-            changed = true;
-        }
-        if (desired.app != current.app) {
-            if (mAppConnectionHandle != nullptr) {
-                mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
-            } else {
-                mAppEventThread->setPhaseOffset(desired.app);
-            }
-            changed = true;
-        }
-
-        if (changed) {
-            mOffsets = desired;
-        }
-    }
-
-    Offsets mLateOffsets;
-    Offsets mEarlyOffsets;
-    Offsets mEarlyGlOffsets;
-
-    EventThread* mSfEventThread = nullptr;
-    EventThread* mAppEventThread = nullptr;
+    mutable std::mutex mMutex;
+    std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
+    nsecs_t mThresholdForNextVsync;
 
     Scheduler* mScheduler = nullptr;
     Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
     Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
 
-    std::atomic<Offsets> mOffsets;
+    Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};
 
     std::atomic<Scheduler::TransactionStart> mTransactionStart =
             Scheduler::TransactionStart::NORMAL;
-    std::atomic<bool> mLastFrameUsedRenderEngine = false;
     std::atomic<bool> mRefreshRateChangePending = false;
     std::atomic<int> mRemainingEarlyFrameCount = 0;
+    std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+
+    bool mTraceDetailedInfo = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a15cf4a..60b3a11 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -48,6 +48,8 @@
 #include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <dvr/vr_flinger.h>
 #include <gui/BufferQueue.h>
+#include <gui/DebugEGLImageTracker.h>
+
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/IProducerListener.h>
@@ -311,6 +313,9 @@
     wideColorGamutCompositionPixelFormat =
             static_cast<ui::PixelFormat>(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888));
 
+    mColorSpaceAgnosticDataspace =
+            static_cast<ui::Dataspace>(color_space_agnostic_dataspace(Dataspace::UNKNOWN));
+
     useContextPriority = use_context_priority(true);
 
     auto tmpPrimaryDisplayOrientation = primary_display_orientation(
@@ -382,7 +387,8 @@
     mLumaSampling = atoi(value);
 
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
 
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
@@ -621,13 +627,16 @@
             mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
 
     mAppConnectionHandle =
-            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
+            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                          resyncCallback,
                                          impl::EventThread::InterceptVSyncsCallback());
-    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
-                                                       resyncCallback, [this](nsecs_t timestamp) {
-                                                           mInterceptor->saveVSyncEvent(timestamp);
-                                                       });
+    mSfConnectionHandle =
+            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
+                                         resyncCallback, [this](nsecs_t timestamp) {
+                                             mInterceptor->saveVSyncEvent(timestamp);
+                                         });
 
     mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
     mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
@@ -711,6 +720,24 @@
                 Mutex::Autolock lock(mStateLock);
                 setRefreshRateTo(type, event);
             });
+    mScheduler->setGetCurrentRefreshRateTypeCallback([this] {
+        Mutex::Autolock lock(mStateLock);
+        const auto display = getDefaultDisplayDeviceLocked();
+        if (!display) {
+            // If we don't have a default display the fallback to the default
+            // refresh rate type
+            return RefreshRateType::DEFAULT;
+        }
+
+        const int configId = display->getActiveConfig();
+        for (const auto& [type, refresh] : mRefreshRateConfigs.getRefreshRates()) {
+            if (refresh && refresh->configId == configId) {
+                return type;
+            }
+        }
+        // This should never happen, but just gracefully fallback to default.
+        return RefreshRateType::DEFAULT;
+    });
     mScheduler->setGetVsyncPeriodCallback([this] {
         Mutex::Autolock lock(mStateLock);
         return getVsyncPeriod();
@@ -940,15 +967,13 @@
         // Start receiving vsync samples now, so that we can detect a period
         // switch.
         mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
-        // We should only move to early offsets when we know that the refresh
-        // rate will change. Otherwise, we may be stuck in early offsets
-        // forever, as onRefreshRateChangeDetected will not be called.
-        if (mDesiredActiveConfig.event == Scheduler::ConfigEvent::Changed) {
-            mVsyncModulator.onRefreshRateChangeInitiated();
-        }
+        // As we called to set period, we will call to onRefreshRateChangeCompleted once
+        // DispSync model is locked.
+        mVsyncModulator.onRefreshRateChangeInitiated();
         mPhaseOffsets->setRefreshRateType(info.type);
         const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-        mVsyncModulator.setPhaseOffsets(early, gl, late);
+        mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                        mPhaseOffsets->getOffsetThresholdForNextVsync());
     }
     mDesiredActiveConfigChanged = true;
     ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
@@ -980,10 +1005,10 @@
 
     display->setActiveConfig(mUpcomingActiveConfig.configId);
 
-    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
     mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
 
     if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
@@ -992,6 +1017,19 @@
     }
 }
 
+void SurfaceFlinger::desiredActiveConfigChangeDone() {
+    std::lock_guard<std::mutex> lock(mActiveConfigLock);
+    mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
+    mDesiredActiveConfigChanged = false;
+    ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+
+    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+    mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
+    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
+}
+
 bool SurfaceFlinger::performSetActiveConfig() {
     ATRACE_CALL();
     if (mCheckPendingFence) {
@@ -1021,14 +1059,7 @@
     if (!display || display->getActiveConfig() == desiredActiveConfig.configId) {
         // display is not valid or we are already in the requested mode
         // on both cases there is nothing left to do
-        std::lock_guard<std::mutex> lock(mActiveConfigLock);
-        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
-        mDesiredActiveConfigChanged = false;
-        // Update scheduler with the correct vsync period as a no-op.
-        // Otherwise, there exists a race condition where we get stuck in the
-        // incorrect vsync period.
-        mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
-        ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+        desiredActiveConfigChangeDone();
         return false;
     }
 
@@ -1036,17 +1067,10 @@
     // allowed configs might have change by the time we process the refresh.
     // Make sure the desired config is still allowed
     if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
-        std::lock_guard<std::mutex> lock(mActiveConfigLock);
-        mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
-        mDesiredActiveConfig.configId = display->getActiveConfig();
-        mDesiredActiveConfigChanged = false;
-        // Update scheduler with the current vsync period as a no-op.
-        // Otherwise, there exists a race condition where we get stuck in the
-        // incorrect vsync period.
-        mScheduler->resyncToHardwareVsync(false, getVsyncPeriod());
-        ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
+        desiredActiveConfigChangeDone();
         return false;
     }
+
     mUpcomingActiveConfig = desiredActiveConfig;
     const auto displayId = display->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
@@ -1384,7 +1408,7 @@
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
-        ISurfaceComposer::VsyncSource vsyncSource) {
+        ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
     auto resyncCallback = mScheduler->makeResyncCallback([this] {
         Mutex::Autolock lock(mStateLock);
         return getVsyncPeriod();
@@ -1393,7 +1417,8 @@
     const auto& handle =
             vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
 
-    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
+    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+                                                    configChanged);
 }
 
 // ----------------------------------------------------------------------------
@@ -1542,10 +1567,23 @@
 
 void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mStateLock);
+
+    // Enable / Disable HWVsync from the main thread to avoid race conditions with
+    // display power state.
+    postMessageAsync(new LambdaMessage(
+            [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+}
+
+void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
+    ATRACE_CALL();
+
+    mHWCVsyncPendingState = enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable;
+
     if (const auto displayId = getInternalDisplayIdLocked()) {
-        getHwComposer().setVsyncEnabled(*displayId,
-                                        enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
+        sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
+        if (display && display->isPoweredOn()) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
+        }
     }
 }
 
@@ -1643,7 +1681,8 @@
     setTransactionFlags(eDisplayTransactionNeeded);
 }
 
-bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS {
+bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS {
+    ATRACE_CALL();
     // We are storing the last 2 present fences. If sf's phase offset is to be
     // woken up before the actual vsync but targeting the next vsync, we need to check
     // fence N-2
@@ -1652,26 +1691,46 @@
             ? mPreviousPresentFences[0]
             : mPreviousPresentFences[1];
 
-    return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
+    if (fence == Fence::NO_FENCE) {
+        return false;
+    }
+
+    if (graceTimeMs > 0 && fence->getStatus() == Fence::Status::Unsignaled) {
+        fence->wait(graceTimeMs);
+    }
+
+    return (fence->getStatus() == Fence::Status::Unsignaled);
 }
 
-nsecs_t SurfaceFlinger::getExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
     DisplayStatInfo stats;
     mScheduler->getDisplayStatInfo(&stats);
     const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime();
     // Inflate the expected present time if we're targetting the next vsync.
-    const nsecs_t correctedTime =
+    mExpectedPresentTime =
             mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
             ? presentTime
             : presentTime + stats.vsyncPeriod;
-    return correctedTime;
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
-            bool frameMissed = previousFrameMissed();
+            // calculate the expected present time once and use the cached
+            // value throughout this frame to make sure all layers are
+            // seeing this same value.
+            populateExpectedPresentTime();
+
+            // When Backpressure propagation is enabled we want to give a small grace period
+            // for the present fence to fire instead of just giving up on this frame to handle cases
+            // where present fence is just about to get signaled.
+            const int graceTimeForPresentFenceMs =
+                    (mPropagateBackpressure &&
+                     (mPropagateBackpressureClientComposition || !mHadClientComposition))
+                    ? 1
+                    : 0;
+            bool frameMissed = previousFrameMissed(graceTimeForPresentFenceMs);
             bool hwcFrameMissed = mHadDeviceComposition && frameMissed;
             bool gpuFrameMissed = mHadClientComposition && frameMissed;
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
@@ -1766,6 +1825,7 @@
     preComposition();
     rebuildLayerStacks();
     calculateWorkingSet();
+    long compositionTime = elapsedRealtimeNano();
     for (const auto& [token, display] : mDisplays) {
         beginFrame(display);
         prepareFrame(display);
@@ -1795,7 +1855,7 @@
     if (mVisibleRegionsDirty) {
         mVisibleRegionsDirty = false;
         if (mTracingEnabled) {
-            mTracing.notify("visibleRegionsDirty");
+            mTracing.notify(compositionTime, "visibleRegionsDirty");
         }
     }
 }
@@ -1873,7 +1933,14 @@
             RenderIntent renderIntent;
             pickColorMode(displayDevice, &colorMode, &targetDataspace, &renderIntent);
             display->setColorMode(colorMode, targetDataspace, renderIntent);
+
+            if (isHdrColorMode(colorMode)) {
+                targetDataspace = Dataspace::UNKNOWN;
+            } else if (mColorSpaceAgnosticDataspace != Dataspace::UNKNOWN) {
+                targetDataspace = mColorSpaceAgnosticDataspace;
+            }
         }
+
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             if (layer->isHdrY410()) {
                 layer->forceClientComposition(displayDevice);
@@ -1900,9 +1967,7 @@
 
             const auto& displayState = display->getState();
             layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport,
-                                   displayDevice->getSupportedPerFrameMetadata(),
-                                   isHdrColorMode(displayState.colorMode) ? Dataspace::UNKNOWN
-                                                                          : targetDataspace);
+                                   displayDevice->getSupportedPerFrameMetadata(), targetDataspace);
         }
     }
 
@@ -3798,6 +3863,7 @@
 
     if (uncacheBuffer.isValid()) {
         ClientCache::getInstance().erase(uncacheBuffer);
+        getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id);
     }
 
     // If a synchronous transaction is explicitly requested without any changes, force a transaction
@@ -4152,9 +4218,18 @@
     bool bufferChanged = what & layer_state_t::eBufferChanged;
     bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
     sp<GraphicBuffer> buffer;
-    if (bufferChanged && cacheIdChanged) {
-        ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
+    if (bufferChanged && cacheIdChanged && s.buffer != nullptr) {
         buffer = s.buffer;
+        bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
+        if (success) {
+            getRenderEngine().cacheExternalTextureBuffer(s.buffer);
+            success = ClientCache::getInstance()
+                              .registerErasedRecipient(s.cachedBuffer,
+                                                       wp<ClientCache::ErasedRecipient>(this));
+            if (!success) {
+                getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId());
+            }
+        }
     } else if (cacheIdChanged) {
         buffer = ClientCache::getInstance().get(s.cachedBuffer);
     } else if (bufferChanged) {
@@ -4437,6 +4512,13 @@
             new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
 }
 
+void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled) {
+    if (mHWCVsyncState != enabled) {
+        getHwComposer().setVsyncEnabled(displayId, enabled);
+        mHWCVsyncState = enabled;
+    }
+}
+
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
     if (display->isVirtual()) {
         ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
@@ -4463,6 +4545,7 @@
         // Turn on the display
         getHwComposer().setPowerMode(*displayId, mode);
         if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
             mScheduler->onScreenAcquired(mAppConnectionHandle);
             mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
         }
@@ -4488,6 +4571,9 @@
             mScheduler->onScreenReleased(mAppConnectionHandle);
         }
 
+        // Make sure HWVsync is disabled before turning off the display
+        setVsyncEnabledInHWC(*displayId, HWC2::Vsync::Disable);
+
         getHwComposer().setPowerMode(*displayId, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
@@ -4514,6 +4600,7 @@
     if (display->isPrimary()) {
         mTimeStats->setPowerMode(mode);
         mRefreshRateStats.setPowerMode(mode);
+        mScheduler->setDisplayPowerState(mode == HWC_POWER_MODE_NORMAL);
     }
 
     ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
@@ -4682,6 +4769,16 @@
     StringAppendF(&result, "Scheduler enabled.");
     StringAppendF(&result, "+  Smart 90 for video detection: %s\n\n",
                   mUseSmart90ForVideo ? "on" : "off");
+    StringAppendF(&result, "Allowed Display Configs: ");
+    for (int32_t configId : mAllowedDisplayConfigs) {
+        for (auto refresh : mRefreshRateConfigs.getRefreshRates()) {
+            if (refresh.second && refresh.second->configId == configId) {
+                StringAppendF(&result, "%dHz, ", refresh.second->fps);
+            }
+        }
+    }
+    StringAppendF(&result, "(config override by backdoor: %s)\n\n",
+                  mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
     mScheduler->dump(mAppConnectionHandle, result);
 }
 
@@ -4964,6 +5061,8 @@
 
     getRenderEngine().dump(result);
 
+    DebugEGLImageTracker::getInstance()->dump(result);
+
     if (const auto display = getDefaultDisplayDeviceLocked()) {
         display->getCompositionDisplay()->getState().undefinedRegion.dump(result,
                                                                           "undefinedRegion");
@@ -5377,7 +5476,12 @@
                 return NO_ERROR;
             }
             case 1023: { // Set native mode
+                int32_t colorMode;
+
                 mDisplayColorSetting = static_cast<DisplayColorSetting>(data.readInt32());
+                if (data.readInt32(&colorMode) == NO_ERROR) {
+                    mForceColorMode = static_cast<ColorMode>(colorMode);
+                }
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -6092,8 +6196,20 @@
         return;
     }
 
+    const auto allowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(),
+                                                      allowedConfigs.end());
+    if (allowedDisplayConfigs == mAllowedDisplayConfigs) {
+        return;
+    }
+
     ALOGV("Updating allowed configs");
-    mAllowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(), allowedConfigs.end());
+    mAllowedDisplayConfigs = std::move(allowedDisplayConfigs);
+
+    // TODO(b/140204874): This hack triggers a notification that something has changed, so
+    // that listeners that care about a change in allowed configs can get the notification.
+    // Giving current ActiveConfig so that most other listeners would just drop the event
+    mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
+                                display->getActiveConfig());
 
     // Set the highest allowed config by iterating backwards on available refresh rates
     const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
@@ -6173,6 +6289,10 @@
     return nullptr;
 }
 
+void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) {
+    getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id);
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 49a048c..49bb574 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -170,9 +170,9 @@
 
 class SurfaceFlinger : public BnSurfaceComposer,
                        public PriorityDumper,
+                       public ClientCache::ErasedRecipient,
                        private IBinder::DeathRecipient,
-                       private HWC2::ComposerCallback
-{
+                       private HWC2::ComposerCallback {
 public:
     SurfaceFlingerBE& getBE() { return mBE; }
     const SurfaceFlingerBE& getBE() const { return mBE; }
@@ -294,15 +294,19 @@
     // TODO: this should be made accessible only to EventThread
     void setPrimaryVsyncEnabled(bool enabled);
 
+    // main thread function to enable/disable h/w composer event
+    void setPrimaryVsyncEnabledInternal(bool enabled);
+
     // called on the main thread by MessageQueue when an internal message
     // is received
     // TODO: this should be made accessible only to MessageQueue
     void onMessageReceived(int32_t what);
 
-    // Returns the expected present time for this frame.
+    // populates the expected present time for this frame.
     // When we are in negative offsets, we perform a correction so that the
     // predicted vsync for the *next* frame is used instead.
-    nsecs_t getExpectedPresentTime();
+    void populateExpectedPresentTime();
+    nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; }
 
     // for debugging only
     // TODO: this should be made accessible only to HWComposer
@@ -325,6 +329,9 @@
 
     sp<Layer> fromHandle(const sp<IBinder>& handle) REQUIRES(mStateLock);
 
+    // Inherit from ClientCache::ErasedRecipient
+    void bufferErased(const client_cache_t& clientCacheId) override;
+
 private:
     friend class BufferLayer;
     friend class BufferQueueLayer;
@@ -405,7 +412,9 @@
             const sp<IGraphicBufferProducer>& bufferProducer) const override;
     status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
     sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress) override;
     status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
             bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace,
             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
@@ -500,9 +509,9 @@
     using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
 
     struct ActiveConfigInfo {
-        RefreshRateType type;
-        int configId;
-        Scheduler::ConfigEvent event;
+        RefreshRateType type = RefreshRateType::DEFAULT;
+        int configId = 0;
+        Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None;
 
         bool operator!=(const ActiveConfigInfo& other) const {
             return type != other.type || configId != other.configId || event != other.event;
@@ -514,13 +523,15 @@
     // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
     void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock);
     // Once HWC has returned the present fence, this sets the active config and a new refresh
-    // rate in SF. It also triggers HWC vsync.
+    // rate in SF.
     void setActiveConfigInternal() REQUIRES(mStateLock);
     // Active config is updated on INVALIDATE call in a state machine-like manner. When the
     // desired config was set, HWC needs to update the panel on the next refresh, and when
     // we receive the fence back, we know that the process was complete. It returns whether
     // we need to wait for the next invalidate
     bool performSetActiveConfig() REQUIRES(mStateLock);
+    // Called when active config is no longer is progress
+    void desiredActiveConfigChangeDone() REQUIRES(mStateLock);
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
 
@@ -838,7 +849,8 @@
         return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
     }
 
-    bool previousFrameMissed();
+    bool previousFrameMissed(int graceTimeMs = 0);
+    void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
 
     /*
      * Debugging & dumpsys
@@ -1113,6 +1125,7 @@
 
     ui::Dataspace mDefaultCompositionDataspace;
     ui::Dataspace mWideColorGamutCompositionDataspace;
+    ui::Dataspace mColorSpaceAgnosticDataspace;
 
     SurfaceFlingerBE mBE;
     std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
@@ -1177,6 +1190,12 @@
     // The Layer pointer is removed from the set when the destructor is called so there shouldn't
     // be any issues with a raw pointer referencing an invalid object.
     std::unordered_set<Layer*> mOffscreenLayers;
+
+    // Flags to capture the state of Vsync in HWC
+    HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
+    HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
+
+    nsecs_t mExpectedPresentTime;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 2b33ba1..768074a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -218,6 +218,14 @@
     return static_cast<int32_t>(defaultValue);
 }
 
+int64_t color_space_agnostic_dataspace(Dataspace defaultValue) {
+    auto temp = SurfaceFlingerProperties::color_space_agnostic_dataspace();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return static_cast<int64_t>(defaultValue);
+}
+
 int32_t set_idle_timer_ms(int32_t defaultValue) {
     auto temp = SurfaceFlingerProperties::set_idle_timer_ms();
     if (temp.has_value()) {
@@ -234,6 +242,14 @@
     return defaultValue;
 }
 
+int32_t set_display_power_timer_ms(int32_t defaultValue) {
+    auto temp = SurfaceFlingerProperties::set_display_power_timer_ms();
+    if (temp.has_value()) {
+        return *temp;
+    }
+    return defaultValue;
+}
+
 bool use_smart_90_for_video(bool defaultValue) {
     auto temp = SurfaceFlingerProperties::use_smart_90_for_video();
     if (temp.has_value()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 1964ccd..5f88322 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -70,10 +70,15 @@
 int32_t wcg_composition_pixel_format(
         android::hardware::graphics::common::V1_2::PixelFormat defaultValue);
 
+int64_t color_space_agnostic_dataspace(
+        android::hardware::graphics::common::V1_2::Dataspace defaultValue);
+
 int32_t set_idle_timer_ms(int32_t defaultValue);
 
 int32_t set_touch_timer_ms(int32_t defaultValue);
 
+int32_t set_display_power_timer_ms(int32_t defaultValue);
+
 bool use_smart_90_for_video(bool defaultValue);
 
 bool enable_protected_contents(bool defaultValue);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 9053f2c..5d9be0b 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -68,8 +68,9 @@
     return mEnabled;
 }
 
-void SurfaceTracing::notify(const char* where) {
+void SurfaceTracing::notify(long compositionTime, const char* where) {
     std::scoped_lock lock(mSfLock);
+    mCompositionTime = compositionTime;
     mWhere = where;
     mCanStartTrace.notify_one();
 }
@@ -160,7 +161,7 @@
     ATRACE_CALL();
 
     LayersTraceProto entry;
-    entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
+    entry.set_elapsed_realtime_nanos(mCompositionTime);
     entry.set_where(where);
     LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
     entry.mutable_layers()->Swap(&layers);
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 4773307..395d562 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -46,7 +46,7 @@
     bool disable();
     status_t writeToFile();
     bool isEnabled() const;
-    void notify(const char* where);
+    void notify(long compositionTime, const char* where);
 
     void setBufferSize(size_t bufferSizeInByte);
     void writeToFileAsync();
@@ -81,6 +81,8 @@
         std::queue<LayersTraceProto> mStorage;
     };
 
+    long mCompositionTime;
+
     void mainLoop();
     void addFirstEntry();
     LayersTraceProto traceWhenNotified();
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index ac02d12..1441f91 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1 +1,2 @@
-zzyiwei@google.com
\ No newline at end of file
+alecmouri@google.com
+zzyiwei@google.com
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index a8ec764..a4f4285 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -251,6 +251,20 @@
     prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
 }
 
+# colorSpaceAgnosticDataspace specifies the data space that
+# SurfaceFlinger expects for surfaces which are color space agnostic.
+# The variable works only when useColorManagement is specified. If
+# unspecified, the data space follows what SurfaceFlinger expects for
+# surfaces when useColorManagement is specified.
+
+prop {
+    api_name: "color_space_agnostic_dataspace"
+    type: Long
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+}
+
 # Return the native panel primary data. The data includes red, green,
 # blue and white. The primary format is CIE 1931 XYZ color space.
 # If unspecified, the primaries is sRGB gamut by default.
@@ -309,6 +323,18 @@
     prop_name: "ro.surface_flinger.set_touch_timer_ms"
 }
 
+# setDisplayPowerTimerMs indicates what is considered a timeout in milliseconds for Scheduler.
+# This value is used by the Scheduler to trigger display power inactivity callbacks that will
+# keep the display in peak refresh rate as long as display power is not in normal mode.
+# Setting this property to 0 means there is no timer.
+prop {
+    api_name: "set_display_power_timer_ms"
+    type: Integer
+    scope: Public
+    access: Readonly
+    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+}
+
 # useSmart90ForVideo indicates whether Scheduler should detect content FPS, and try to adjust the
 # screen refresh rate based on that.
 prop {
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index 0611684..b66e56e 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -1,6 +1,11 @@
 props {
   module: "android.sysprop.SurfaceFlingerProperties"
   prop {
+    api_name: "color_space_agnostic_dataspace"
+    type: Long
+    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+  }
+  prop {
     api_name: "default_composition_dataspace"
     type: Long
     prop_name: "ro.surface_flinger.default_composition_dataspace"
@@ -72,6 +77,11 @@
     prop_name: "ro.surface_flinger.running_without_sync_framework"
   }
   prop {
+    api_name: "set_display_power_timer_ms"
+    type: Integer
+    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+  }
+  prop {
     api_name: "set_idle_timer_ms"
     type: Integer
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
index 0611684..b66e56e 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-latest.txt
@@ -1,6 +1,11 @@
 props {
   module: "android.sysprop.SurfaceFlingerProperties"
   prop {
+    api_name: "color_space_agnostic_dataspace"
+    type: Long
+    prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
+  }
+  prop {
     api_name: "default_composition_dataspace"
     type: Long
     prop_name: "ro.surface_flinger.default_composition_dataspace"
@@ -72,6 +77,11 @@
     prop_name: "ro.surface_flinger.running_without_sync_framework"
   }
   prop {
+    api_name: "set_display_power_timer_ms"
+    type: Integer
+    prop_name: "ro.surface_flinger.set_display_power_timer_ms"
+  }
+  prop {
     api_name: "set_idle_timer_ms"
     type: Integer
     prop_name: "ro.surface_flinger.set_idle_timer_ms"
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index d5f6534..c93e15e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -28,6 +28,7 @@
 
 #include <binder/ProcessState.h>
 #include <gui/BufferItemConsumer.h>
+#include <gui/IProducerListener.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerState.h>
 #include <gui/Surface.h>
@@ -6059,4 +6060,97 @@
     }
 }
 
+// This test ensures that when we drop an app buffer in SurfaceFlinger, we merge
+// the dropped buffer's damage region into the next buffer's damage region. If
+// we don't do this, we'll report an incorrect damage region to hardware
+// composer, resulting in broken rendering. This test checks the BufferQueue
+// case.
+//
+// Unfortunately, we don't currently have a way to inspect the damage region
+// SurfaceFlinger sends to hardware composer from a test, so this test requires
+// the dev to manually watch the device's screen during the test to spot broken
+// rendering. Because the results can't be automatically verified, this test is
+// marked disabled.
+TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDroppingBuffers) {
+    const int width = mDisplayWidth;
+    const int height = mDisplayHeight;
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
+    const auto producer = layer->getIGraphicBufferProducer();
+    const sp<IProducerListener> dummyListener(new DummyProducerListener);
+    IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
+    ASSERT_EQ(OK,
+              producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput));
+
+    std::map<int, sp<GraphicBuffer>> slotMap;
+    auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) {
+        ASSERT_NE(nullptr, buf);
+        const auto iter = slotMap.find(slot);
+        ASSERT_NE(slotMap.end(), iter);
+        *buf = iter->second;
+    };
+
+    auto dequeue = [&](int* outSlot) {
+        ASSERT_NE(nullptr, outSlot);
+        *outSlot = -1;
+        int slot;
+        sp<Fence> fence;
+        uint64_t age;
+        FrameEventHistoryDelta timestamps;
+        const status_t dequeueResult =
+                producer->dequeueBuffer(&slot, &fence, width, height, PIXEL_FORMAT_RGBA_8888,
+                                        GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                        &age, &timestamps);
+        if (dequeueResult == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+            sp<GraphicBuffer> newBuf;
+            ASSERT_EQ(OK, producer->requestBuffer(slot, &newBuf));
+            ASSERT_NE(nullptr, newBuf.get());
+            slotMap[slot] = newBuf;
+        } else {
+            ASSERT_EQ(OK, dequeueResult);
+        }
+        *outSlot = slot;
+    };
+
+    auto queue = [&](int slot, const Region& damage, nsecs_t displayTime) {
+        IGraphicBufferProducer::QueueBufferInput input(
+                /*timestamp=*/displayTime, /*isAutoTimestamp=*/false, HAL_DATASPACE_UNKNOWN,
+                /*crop=*/Rect::EMPTY_RECT, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
+                /*transform=*/0, Fence::NO_FENCE);
+        input.setSurfaceDamage(damage);
+        IGraphicBufferProducer::QueueBufferOutput output;
+        ASSERT_EQ(OK, producer->queueBuffer(slot, input, &output));
+    };
+
+    auto fillAndPostBuffers = [&](const Color& color) {
+        int slot1;
+        ASSERT_NO_FATAL_FAILURE(dequeue(&slot1));
+        int slot2;
+        ASSERT_NO_FATAL_FAILURE(dequeue(&slot2));
+
+        sp<GraphicBuffer> buf1;
+        ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1));
+        sp<GraphicBuffer> buf2;
+        ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2));
+        fillGraphicBufferColor(buf1, Rect(width, height), color);
+        fillGraphicBufferColor(buf2, Rect(width, height), color);
+
+        const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100);
+        ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime));
+        ASSERT_NO_FATAL_FAILURE(
+                queue(slot2, Region(Rect(width / 3, height / 3, 2 * width / 3, 2 * height / 3)),
+                      displayTime));
+    };
+
+    const auto startTime = systemTime();
+    const std::array<Color, 3> colors = {Color::RED, Color::GREEN, Color::BLUE};
+    int colorIndex = 0;
+    while (nanoseconds_to_seconds(systemTime() - startTime) < 10) {
+        ASSERT_NO_FATAL_FAILURE(fillAndPostBuffers(colors[colorIndex++ % colors.size()]));
+        std::this_thread::sleep_for(1s);
+    }
+
+    ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU));
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 2e705da..0aa8cf5 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -51,6 +51,7 @@
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder;
 
     static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms;
+    static constexpr std::chrono::nanoseconds mOffsetThresholdForNextVsync = 16ms;
     static constexpr int mIterations = 100;
 };
 
@@ -78,7 +79,8 @@
 
 void DispSyncSourceTest::createDispSyncSource() {
     createDispSync();
-    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true,
+    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(),
+                                                       mOffsetThresholdForNextVsync.count(), true,
                                                        "DispSyncSourceTest");
     mDispSyncSource->setCallback(this);
 }
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index ea908a9..dbd9b84 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -55,8 +55,9 @@
     class MockEventThreadConnection : public EventThreadConnection {
     public:
         MockEventThreadConnection(android::impl::EventThread* eventThread,
-                                  ResyncCallback&& resyncCallback)
-              : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
+                                  ResyncCallback&& resyncCallback,
+                                  ISurfaceComposer::ConfigChanged configChanged)
+              : EventThreadConnection(eventThread, std::move(resyncCallback), configChanged) {}
         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
     };
 
@@ -67,7 +68,8 @@
     ~EventThreadTest() override;
 
     void createThread();
-    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder);
+    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
+                                                   ISurfaceComposer::ConfigChanged configChanged);
 
     void expectVSyncSetEnabledCallReceived(bool expectedState);
     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
@@ -110,7 +112,8 @@
             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
 
     createThread();
-    mConnection = createConnection(mConnectionEventCallRecorder);
+    mConnection = createConnection(mConnectionEventCallRecorder,
+                                   ISurfaceComposer::eConfigChangedDispatch);
 
     // A display must be connected for VSYNC events to be delivered.
     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
@@ -138,9 +141,10 @@
 }
 
 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
-        ConnectionEventRecorder& recorder) {
+        ConnectionEventRecorder& recorder, ISurfaceComposer::ConfigChanged configChanged) {
     sp<MockEventThreadConnection> connection =
-            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
+            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
+                                          configChanged);
     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
     return connection;
 }
@@ -267,7 +271,9 @@
 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
     // Create a first connection, register it, and request a vsync rate of zero.
     ConnectionEventRecorder firstConnectionEventRecorder{0};
-    sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
+    sp<MockEventThreadConnection> firstConnection =
+            createConnection(firstConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(0, firstConnection);
 
     // By itself, this should not enable vsync events
@@ -277,7 +283,8 @@
     // However if there is another connection which wants events at a nonzero rate.....
     ConnectionEventRecorder secondConnectionEventRecorder{0};
     sp<MockEventThreadConnection> secondConnection =
-            createConnection(secondConnectionEventRecorder);
+            createConnection(secondConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, secondConnection);
 
     // EventThread should enable vsync callbacks.
@@ -363,7 +370,9 @@
 
 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -387,7 +396,9 @@
 
 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -449,5 +460,18 @@
     expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7);
 }
 
+TEST_F(EventThreadTest, suppressConfigChanged) {
+    ConnectionEventRecorder suppressConnectionEventRecorder{0};
+    sp<MockEventThreadConnection> suppressConnection =
+            createConnection(suppressConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
+
+    mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 9);
+    expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9);
+
+    auto args = suppressConnectionEventRecorder.waitForCall();
+    ASSERT_FALSE(args.has_value());
+}
+
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index 96121bb..1d75011 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -23,6 +23,8 @@
 namespace android {
 namespace scheduler {
 
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
+
 class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
     nsecs_t FAKE_PHASE_OFFSET_NS = 0;
 
@@ -34,20 +36,20 @@
     nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
 
     PhaseOffsets::Offsets getOffsetsForRefreshRate(
-            RefreshRateConfigs::RefreshRateType /*refreshRateType*/) const override {
+            RefreshRateType /*refreshRateType*/) const override {
         return getCurrentOffsets();
     }
 
     // Returns early, early GL, and late offsets for Apps and SF.
     PhaseOffsets::Offsets getCurrentOffsets() const override {
-        return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
-                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
+        return Offsets{{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
     }
 
     // This function should be called when the device is switching between different
     // refresh rates, to properly update the offsets.
-    void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+    void setRefreshRateType(RefreshRateType /*refreshRateType*/) override {}
 
     nsecs_t getOffsetThresholdForNextVsync() const override { return FAKE_PHASE_OFFSET_NS; }
 
@@ -56,4 +58,4 @@
 };
 
 } // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 2b1dfa8..8e7440c 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -25,7 +25,17 @@
 protected:
     std::unique_ptr<LayerHistory> mLayerHistory;
 
+    static constexpr float MIN_REFRESH_RATE = 30.f;
     static constexpr float MAX_REFRESH_RATE = 90.f;
+    static constexpr auto RELEVANT_FRAME_THRESHOLD = 90u;
+    static constexpr uint64_t THIRTY_FPS_INTERVAL = 33'333'333;
+
+    void forceRelevancy(const std::unique_ptr<LayerHistory::LayerHandle>& testLayer) {
+        mLayerHistory->setVisibility(testLayer, true);
+        for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) {
+            mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+        }
+    };
 };
 
 LayerHistoryTest::LayerHistoryTest() {
@@ -36,31 +46,25 @@
 namespace {
 TEST_F(LayerHistoryTest, oneLayer) {
     std::unique_ptr<LayerHistory::LayerHandle> testLayer =
-            mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(testLayer, true);
+    for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+        mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+    }
 
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
-
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    // This is still 0, because the layer is not considered recently active if it
-    // has been present in less than 10 frames.
-    EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
-    // This should be MAX_REFRESH_RATE as we have more than 10 samples
-    EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+    // Add a few more. This time we should get MAX refresh rate as the layer
+    // becomes relevant
+    static constexpr auto A_FEW = 10;
+    for (auto i = 0u; i < A_FEW; i++) {
+        EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
+        mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
+    }
 }
 
 TEST_F(LayerHistoryTest, oneHDRLayer) {
     std::unique_ptr<LayerHistory::LayerHandle> testLayer =
-            mLayerHistory->createLayer("TestHDRLayer", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(testLayer, true);
 
     mLayerHistory->insert(testLayer, 0, true /*isHDR*/);
@@ -74,12 +78,13 @@
 
 TEST_F(LayerHistoryTest, explicitTimestamp) {
     std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer =
-            mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(test30FpsLayer, true);
 
     nsecs_t startTime = systemTime();
-    for (int i = 0; i < 31; i++) {
-        mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/);
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
     }
 
     EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
@@ -87,29 +92,31 @@
 
 TEST_F(LayerHistoryTest, multipleLayers) {
     std::unique_ptr<LayerHistory::LayerHandle> testLayer =
-            mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(testLayer, true);
     std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer =
-            mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(test30FpsLayer, true);
     std::unique_ptr<LayerHistory::LayerHandle> testLayer2 =
-            mLayerHistory->createLayer("TestLayer2", MAX_REFRESH_RATE);
+            mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE);
     mLayerHistory->setVisibility(testLayer2, true);
 
     nsecs_t startTime = systemTime();
-    for (int i = 0; i < 10; i++) {
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
         mLayerHistory->insert(testLayer, 0, false /*isHDR*/);
     }
     EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
 
     startTime = systemTime();
-    for (int i = 0; i < 10; i++) {
-        mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/);
+    for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
     }
     EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
 
-    for (int i = 10; i < 30; i++) {
-        mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/);
+    for (int i = 10; i < RELEVANT_FRAME_THRESHOLD; i++) {
+        mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL),
+                              false /*isHDR*/);
     }
     EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
 
@@ -119,10 +126,12 @@
         mLayerHistory->insert(testLayer2, 0, false /*isHDR*/);
     }
     EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first);
-    // After 100 ms frames become obsolete.
-    std::this_thread::sleep_for(std::chrono::milliseconds(500));
-    // Insert the 31st frame.
-    mLayerHistory->insert(test30FpsLayer, startTime + (30 * 33333333), false /*isHDR*/);
+    // After 1200 ms frames become obsolete.
+    std::this_thread::sleep_for(std::chrono::milliseconds(1500));
+
+    mLayerHistory->insert(test30FpsLayer,
+                          startTime + (RELEVANT_FRAME_THRESHOLD * THIRTY_FPS_INTERVAL),
+                          false /*isHDR*/);
     EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first);
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 1f8b111..740115e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,8 @@
     class MockEventThreadConnection : public android::EventThreadConnection {
     public:
         explicit MockEventThreadConnection(EventThread* eventThread)
-              : EventThreadConnection(eventThread, ResyncCallback()) {}
+              : EventThreadConnection(eventThread, ResyncCallback(),
+                                      ISurfaceComposer::eConfigChangedSuppress) {}
         ~MockEventThreadConnection() = default;
 
         MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -47,7 +48,7 @@
 
         std::unique_ptr<EventThread> makeEventThread(
                 const char* /* connectionName */, DispSync* /* dispSync */,
-                nsecs_t /* phaseOffsetNs */,
+                nsecs_t /* phaseOffsetNs */, nsecs_t /* offsetThresholdForNextVsync */,
                 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
             return std::move(mEventThread);
         }
@@ -81,10 +82,10 @@
 
     // 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, ResyncCallback(),
+    mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16, ResyncCallback(),
                                                      impl::EventThread::InterceptVSyncsCallback());
     EXPECT_TRUE(mConnectionHandle != nullptr);
 }
@@ -105,7 +106,10 @@
     // exceptions, just gracefully continues.
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
-            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+            returnedValue =
+                    mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -126,7 +130,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -155,7 +161,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue != nullptr);
     ASSERT_EQ(returnedValue, mEventThreadConnection);
 
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index c3d2b8d..cb6980e 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <gmock/gmock.h>
+#include <gui/ISurfaceComposer.h>
 
 #include "Scheduler/EventThread.h"
 #include "Scheduler/RefreshRateConfigs.h"
@@ -34,7 +35,8 @@
     // Scheduler::Connection. This allows plugging in mock::EventThread.
     sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) {
         sp<EventThreadConnection> eventThreadConnection =
-                new EventThreadConnection(eventThread.get(), ResyncCallback());
+                new EventThreadConnection(eventThread.get(), ResyncCallback(),
+                                          ISurfaceComposer::eConfigChangedSuppress);
         const int64_t id = sNextId++;
         mConnections.emplace(id,
                              std::make_unique<Scheduler::Connection>(new ConnectionHandle(id),
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 5b5f8e7..ed35ebf 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,8 @@
     EventThread();
     ~EventThread() override;
 
-    MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
+    MOCK_CONST_METHOD2(createEventConnection,
+                       sp<EventThreadConnection>(ResyncCallback, ISurfaceComposer::ConfigChanged));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index b0c4f3f..4d6b2be 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -41,12 +41,13 @@
         "-DVK_NO_PROTOTYPES",
         "-fvisibility=hidden",
         "-fstrict-aliasing",
-        "-Weverything",
+        "-Wextra",
         "-Werror",
         "-Wno-padded",
+        "-Wno-sign-compare",
         "-Wno-switch-enum",
-        "-Wno-undef",
-        "-Wno-format-pedantic",
+        "-Wno-unused-variable",
+        "-Wno-unused-function",
 
         // Have clang emit complete debug_info.
         "-fstandalone-debug",
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index c77fa06..7477351 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -24,7 +24,10 @@
 #include <dlfcn.h>
 #include <algorithm>
 #include <array>
+#include <climits>
 #include <new>
+#include <sstream>
+#include <string>
 
 #include <log/log.h>
 
@@ -153,15 +156,12 @@
 Hal Hal::hal_;
 
 void* LoadLibrary(const android_dlextinfo& dlextinfo,
-                  const char* subname,
-                  int subname_len) {
+                  const std::string_view subname) {
     ATRACE_CALL();
 
-    const char kLibFormat[] = "vulkan.%*s.so";
-    char* name = static_cast<char*>(
-        alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
-    sprintf(name, kLibFormat, subname_len, subname);
-    return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    std::stringstream ss;
+    ss << "vulkan." << subname << ".so";
+    return android_dlopen_ext(ss.str().c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
 }
 
 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
@@ -181,8 +181,9 @@
     char prop[PROPERTY_VALUE_MAX];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
         int prop_len = property_get(key, prop, nullptr);
-        if (prop_len > 0) {
-            so = LoadLibrary(dlextinfo, prop, prop_len);
+        if (prop_len > 0 && prop_len <= UINT_MAX) {
+            std::string_view lib_name(prop, static_cast<unsigned int>(prop_len));
+            so = LoadLibrary(dlextinfo, lib_name);
             if (so)
                 break;
         }
@@ -1207,7 +1208,8 @@
 
     if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
         // Log that the app is hitting software Vulkan implementation
-        android::GraphicsEnv::getInstance().setCpuVulkanInUse();
+        android::GraphicsEnv::getInstance().setTargetStats(
+            android::GraphicsEnv::Stats::CPU_VULKAN_IN_USE);
     }
 
     data->driver_device = dev;
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 5679412..dd91739 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <sys/prctl.h>
 
+#include <memory>
 #include <mutex>
 #include <string>
 #include <vector>
@@ -101,9 +102,7 @@
     bool EnumerateLayers(size_t library_idx,
                          std::vector<Layer>& instance_layers) const;
 
-    void* GetGPA(const Layer& layer,
-                 const char* gpa_name,
-                 size_t gpa_name_len) const;
+    void* GetGPA(const Layer& layer, const std::string_view gpa_name) const;
 
     const std::string GetFilename() { return filename_; }
 
@@ -226,17 +225,10 @@
     }
 
     // get layer properties
-    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
-        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
-    result = enumerate_instance_layers(&num_instance_layers, properties);
-    if (result != VK_SUCCESS) {
-        ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
-              path_.c_str(), result);
-        return false;
-    }
+    auto properties = std::make_unique<VkLayerProperties[]>(num_instance_layers + num_device_layers);
     if (num_device_layers > 0) {
         result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
-                                         properties + num_instance_layers);
+                                         properties.get() + num_instance_layers);
         if (result != VK_SUCCESS) {
             ALOGE(
                 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
@@ -321,21 +313,11 @@
     return true;
 }
 
-void* LayerLibrary::GetGPA(const Layer& layer,
-                           const char* gpa_name,
-                           size_t gpa_name_len) const {
-    void* gpa;
-    size_t layer_name_len =
-        std::max(size_t{2}, strlen(layer.properties.layerName));
-    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
-    strcpy(name, layer.properties.layerName);
-    strcpy(name + layer_name_len, gpa_name);
-    if (!(gpa = GetTrampoline(name))) {
-        strcpy(name, "vk");
-        strcpy(name + 2, gpa_name);
-        gpa = GetTrampoline(name);
-    }
-    return gpa;
+void* LayerLibrary::GetGPA(const Layer& layer, const std::string_view gpa_name) const {
+    std::string layer_name { layer.properties.layerName };
+    if (void* gpa = GetTrampoline((layer_name.append(gpa_name).c_str())))
+        return gpa;
+    return GetTrampoline((std::string {"vk"}.append(gpa_name)).c_str());
 }
 
 // ----------------------------------------------------------------------------
@@ -470,10 +452,9 @@
 }
 
 void* GetLayerGetProcAddr(const Layer& layer,
-                          const char* gpa_name,
-                          size_t gpa_name_len) {
+                          const std::string_view gpa_name) {
     const LayerLibrary& library = g_layer_libraries[layer.library_idx];
-    return library.GetGPA(layer, gpa_name, gpa_name_len);
+    return library.GetGPA(layer, gpa_name);
 }
 
 }  // anonymous namespace
@@ -556,13 +537,13 @@
 
 PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
     return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
-                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
+                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr"))
                   : nullptr;
 }
 
 PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
     return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
-                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
+                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr"))
                   : nullptr;
 }
 
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index cc0df08..766d9ff 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -718,8 +718,6 @@
         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
         {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
         {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
-        {VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
-        {VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
     };
     const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
     uint32_t total_num_formats = kNumFormats;
@@ -1304,7 +1302,14 @@
             // TODO(jessehall): Improve error reporting. Can we enumerate
             // possible errors and translate them to valid Vulkan result codes?
             ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
-            result = VK_ERROR_SURFACE_LOST_KHR;
+            switch (-err) {
+                case ENOMEM:
+                    result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                    break;
+                default:
+                    result = VK_ERROR_SURFACE_LOST_KHR;
+                    break;
+            }
             break;
         }
         img.buffer = buffer;
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index dedf419..ba02504 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -23,18 +23,11 @@
         "-fvisibility=hidden",
         "-fstrict-aliasing",
         "-DLOG_TAG=\"vknulldrv\"",
-        "-Weverything",
+        "-Wextra",
         "-Werror",
-        "-Wno-padded",
-        "-Wno-undef",
-        "-Wno-zero-length-array",
 
         "-DLOG_NDEBUG=0",
     ],
-    cppflags: [
-        "-Wno-c++98-compat-pedantic",
-        "-Wno-c99-extensions",
-    ],
 
     srcs: [
         "null_driver.cpp",
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
index 2514094..91d64fe 100644
--- a/vulkan/tools/Android.bp
+++ b/vulkan/tools/Android.bp
@@ -22,16 +22,8 @@
 
         "-DLOG_TAG=\"vkinfo\"",
 
-        "-Weverything",
+        "-Wextra",
         "-Werror",
-        "-Wno-padded",
-        "-Wno-undef",
-        "-Wno-switch-enum",
-    ],
-    cppflags: [
-        "-Wno-c++98-compat-pedantic",
-        "-Wno-c99-extensions",
-        "-Wno-old-style-cast",
     ],
 
     srcs: ["vkinfo.cpp"],