Merge "Unify drawing for background blur and blur regions"
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index a5e6c68..85e6969 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -72,5 +72,5 @@
     /**
      * Called when ui intensive bugreport dumps are finished.
      */
-    oneway void onUiIntensiveBugreportDumpsFinished(String callingPackage);
+    oneway void onUiIntensiveBugreportDumpsFinished();
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a81cdaf..8bdde62 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1472,6 +1472,8 @@
 
     RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
                CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
+    RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
+               CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
 
     printf("========================================================\n");
     printf("== Dropbox crashes\n");
@@ -2892,17 +2894,17 @@
     // TODO(b/158737089) reduce code repetition in if branches
     if (options_->telephony_only) {
         MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
+        onUiIntensiveBugreportDumpsFinished(calling_uid);
         MaybeCheckUserConsent(calling_uid, calling_package);
         DumpstateTelephonyOnly(calling_package);
     } else if (options_->wifi_only) {
         MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
+        onUiIntensiveBugreportDumpsFinished(calling_uid);
         MaybeCheckUserConsent(calling_uid, calling_package);
         DumpstateWifiOnly();
     } else if (options_->limited_only) {
         MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
+        onUiIntensiveBugreportDumpsFinished(calling_uid);
         MaybeCheckUserConsent(calling_uid, calling_package);
         DumpstateLimitedOnly();
     } else {
@@ -2911,7 +2913,7 @@
 
         // Take screenshot and get consent only after critical dumpsys has finished.
         MaybeTakeEarlyScreenshot();
-        onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
+        onUiIntensiveBugreportDumpsFinished(calling_uid);
         MaybeCheckUserConsent(calling_uid, calling_package);
 
         // Dump state for the default case. This also drops root.
@@ -3001,16 +3003,14 @@
     TakeScreenshot();
 }
 
-void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
-                                                    const std::string& calling_package) {
+void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
     if (calling_uid == AID_SHELL || !CalledByApi()) {
         return;
     }
     if (listener_ != nullptr) {
         // Let listener know ui intensive bugreport dumps are finished, then it can do event
         // handling if required.
-        android::String16 package(calling_package.c_str());
-        listener_->onUiIntensiveBugreportDumpsFinished(package);
+        listener_->onUiIntensiveBugreportDumpsFinished();
     }
 }
 
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9582c9d..3b9b1b7 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -549,8 +549,7 @@
 
     void MaybeTakeEarlyScreenshot();
 
-    void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
-                                             const std::string& calling_package);
+    void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid);
 
     void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package);
 
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 1c6583e..70bdbcc 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -173,12 +173,9 @@
         return binder::Status::ok();
     }
 
-    binder::Status onUiIntensiveBugreportDumpsFinished(const android::String16& callingpackage)
-        override {
+    binder::Status onUiIntensiveBugreportDumpsFinished() override {
         std::lock_guard <std::mutex> lock(lock_);
-        std::string callingpackageUtf8 = std::string(String8(callingpackage).string());
-        dprintf(out_fd_, "\rCalling package of ui intensive bugreport dumps finished: %s",
-                callingpackageUtf8.c_str());
+        dprintf(out_fd_, "\rUi intensive bugreport dumps finished");
         return binder::Status::ok();
     }
 
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 6b93692..fdeea24 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -68,8 +68,7 @@
     MOCK_METHOD1(onError, binder::Status(int32_t error_code));
     MOCK_METHOD0(onFinished, binder::Status());
     MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
-    MOCK_METHOD1(onUiIntensiveBugreportDumpsFinished,
-        binder::Status(const android::String16& callingpackage));
+    MOCK_METHOD0(onUiIntensiveBugreportDumpsFinished, binder::Status());
 
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f583c9b..594880a 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -450,16 +450,22 @@
             AddArg("--boot-image-merge");
         }
 
+        // The percent won't exceed 100, otherwise, don't set it and use the
+        // default one set in profman.
         uint32_t min_new_classes_percent_change = ::android::base::GetUintProperty<uint32_t>(
-            "dalvik.vm.bgdexopt.new-classes-percent", /*default*/-1);
-        if (min_new_classes_percent_change >= 0 && min_new_classes_percent_change <= 100) {
+            "dalvik.vm.bgdexopt.new-classes-percent",
+            /*default*/std::numeric_limits<uint32_t>::max());
+        if (min_new_classes_percent_change <= 100) {
           AddArg("--min-new-classes-percent-change=" +
                  std::to_string(min_new_classes_percent_change));
         }
 
+        // The percent won't exceed 100, otherwise, don't set it and use the
+        // default one set in profman.
         uint32_t min_new_methods_percent_change = ::android::base::GetUintProperty<uint32_t>(
-            "dalvik.vm.bgdexopt.new-methods-percent", /*default*/-1);
-        if (min_new_methods_percent_change >=0 && min_new_methods_percent_change <= 100) {
+            "dalvik.vm.bgdexopt.new-methods-percent",
+            /*default*/std::numeric_limits<uint32_t>::max());
+        if (min_new_methods_percent_change <= 100) {
           AddArg("--min-new-methods-percent-change=" +
                  std::to_string(min_new_methods_percent_change));
         }
diff --git a/data/etc/cec_config.xml b/data/etc/cec_config.xml
index 5defb2f..480e0ec 100644
--- a/data/etc/cec_config.xml
+++ b/data/etc/cec_config.xml
@@ -30,7 +30,7 @@
   </setting>
   <setting name="power_state_change_on_active_source_lost"
            value-type="string"
-           user-configurable="false">
+           user-configurable="true">
     <allowed-values>
       <value string-value="none" />
       <value string-value="standby_now" />
@@ -39,7 +39,7 @@
   </setting>
   <setting name="system_audio_mode_muting"
            value-type="int"
-           user-configurable="false">
+           user-configurable="true">
     <allowed-values>
       <value int-value="0" />
       <value int-value="1" />
diff --git a/include/input/NamedEnum.h b/include/input/NamedEnum.h
index 1d987fe..6562348 100644
--- a/include/input/NamedEnum.h
+++ b/include/input/NamedEnum.h
@@ -115,7 +115,7 @@
     // Do not specialize it to a large number to avoid performance issues.
     // The recommended maximum enum number to specialize is 64.
     template <typename E>
-    static const std::string string(E val, const char* fallbackFormat = "0x%08x") {
+    static const std::string string(E val, const char* fallbackFormat = "%02d") {
         std::string result;
         std::optional<std::string_view> enumString = enum_name(val);
         result += enumString ? enumString.value() : base::StringPrintf(fallbackFormat, val);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 26b997e..015954d 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -147,6 +147,7 @@
         "-Wextra",
         "-Werror",
         "-Wzero-as-null-pointer-constant",
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
     ],
     product_variables: {
         binder32bit: {
@@ -173,6 +174,15 @@
         misc_undefined: ["integer"],
     },
     min_sdk_version: "29",
+
+    tidy: true,
+    tidy_flags: [
+        // Only check our headers
+        "--header-filter=^.*frameworks/native/libs/binder/.*.h$",
+    ],
+    tidy_checks_as_errors: [
+        "*",
+    ],
 }
 
 // AIDL interface between libbinder and framework.jar
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index c183d29..8264154 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -223,13 +223,14 @@
         if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
             using android::internal::Stability;
 
-            auto stability = Stability::get(this);
-            auto required = privateVendor ? Stability::VENDOR : Stability::getLocalStability();
+            auto category = Stability::getCategory(this);
+            Stability::Level required = privateVendor ? Stability::VENDOR
+                : Stability::getLocalLevel();
 
-            if (CC_UNLIKELY(!Stability::check(stability, required))) {
+            if (CC_UNLIKELY(!Stability::check(category, required))) {
                 ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
-                    Stability::stabilityString(stability).c_str(),
-                    Stability::stabilityString(required).c_str());
+                    category.debugString().c_str(),
+                    Stability::levelString(required).c_str());
                 return BAD_TYPE;
             }
         }
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 64c1ff6..da342ff 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -208,7 +208,7 @@
     }
 
     for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
-        long remain = length;
+        size_t remain = length;
 
         char* c = buffer;
         if (!oneLine && !cStyle) {
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
index 4198e49..5f3d670 100644
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -42,6 +42,7 @@
 
 // ----------------------------------------------------------------------
 
+// NOLINTNEXTLINE(google-default-arguments)
 status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
         uint32_t flags) {
     switch(code) {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index a3a2f87..d4c7acf 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -135,7 +135,7 @@
         out << "target.ptr=" << btd->target.ptr;
     }
     out << " (cookie " << btd->cookie << ")" << endl
-        << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(long)btd->flags << endl
+        << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(uint64_t)btd->flags << endl
         << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
         << " bytes)" << endl
         << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
@@ -150,7 +150,7 @@
     uint32_t code = (uint32_t)*cmd++;
     size_t cmdIndex = code & 0xff;
     if (code == BR_ERROR) {
-        out << "BR_ERROR: " << (void*)(long)(*cmd++) << endl;
+        out << "BR_ERROR: " << (void*)(uint64_t)(*cmd++) << endl;
         return cmd;
     } else if (cmdIndex >= N) {
         out << "Unknown reply: " << code << endl;
@@ -177,21 +177,21 @@
         case BR_DECREFS: {
             const int32_t b = *cmd++;
             const int32_t c = *cmd++;
-            out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")";
+            out << ": target=" << (void*)(uint64_t)b << " (cookie " << (void*)(uint64_t)c << ")";
         } break;
 
         case BR_ATTEMPT_ACQUIRE: {
             const int32_t p = *cmd++;
             const int32_t b = *cmd++;
             const int32_t c = *cmd++;
-            out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c
+            out << ": target=" << (void*)(uint64_t)b << " (cookie " << (void*)(uint64_t)c
                 << "), pri=" << p;
         } break;
 
         case BR_DEAD_BINDER:
         case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
             const int32_t c = *cmd++;
-            out << ": death cookie " << (void*)(long)c;
+            out << ": death cookie " << (void*)(uint64_t)c;
         } break;
 
         default:
@@ -232,7 +232,7 @@
 
         case BC_FREE_BUFFER: {
             const int32_t buf = *cmd++;
-            out << ": buffer=" << (void*)(long)buf;
+            out << ": buffer=" << (void*)(uint64_t)buf;
         } break;
 
         case BC_INCREFS:
@@ -247,7 +247,7 @@
         case BC_ACQUIRE_DONE: {
             const int32_t b = *cmd++;
             const int32_t c = *cmd++;
-            out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")";
+            out << ": target=" << (void*)(uint64_t)b << " (cookie " << (void*)(uint64_t)c << ")";
         } break;
 
         case BC_ATTEMPT_ACQUIRE: {
@@ -260,12 +260,12 @@
         case BC_CLEAR_DEATH_NOTIFICATION: {
             const int32_t h = *cmd++;
             const int32_t c = *cmd++;
-            out << ": handle=" << h << " (death cookie " << (void*)(long)c << ")";
+            out << ": handle=" << h << " (death cookie " << (void*)(uint64_t)c << ")";
         } break;
 
         case BC_DEAD_BINDER_DONE: {
             const int32_t c = *cmd++;
-            out << ": death cookie " << (void*)(long)c;
+            out << ": death cookie " << (void*)(uint64_t)c;
         } break;
 
         default:
@@ -895,21 +895,21 @@
                             tr.data_size,
                             reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                             tr.offsets_size/sizeof(binder_size_t),
-                            freeBuffer, this);
+                            freeBuffer);
                     } else {
                         err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                         freeBuffer(nullptr,
                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                             tr.data_size,
                             reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
-                            tr.offsets_size/sizeof(binder_size_t), this);
+                            tr.offsets_size/sizeof(binder_size_t));
                     }
                 } else {
                     freeBuffer(nullptr,
                         reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                         tr.data_size,
                         reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
-                        tr.offsets_size/sizeof(binder_size_t), this);
+                        tr.offsets_size/sizeof(binder_size_t));
                     continue;
                 }
             }
@@ -1077,7 +1077,7 @@
 
 sp<BBinder> the_context_object;
 
-void IPCThreadState::setTheContextObject(sp<BBinder> obj)
+void IPCThreadState::setTheContextObject(const sp<BBinder>& obj)
 {
     the_context_object = obj;
 }
@@ -1183,7 +1183,7 @@
                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                 tr.data_size,
                 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
-                tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
+                tr.offsets_size/sizeof(binder_size_t), freeBuffer);
 
             const void* origServingStackPointer = mServingStackPointer;
             mServingStackPointer = &origServingStackPointer; // anything on the stack
@@ -1370,7 +1370,7 @@
 void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
                                 size_t /*dataSize*/,
                                 const binder_size_t* /*objects*/,
-                                size_t /*objectsSize*/, void* /*cookie*/)
+                                size_t /*objectsSize*/)
 {
     //ALOGI("Freeing parcel %p", &parcel);
     IF_LOG_COMMANDS() {
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 6d728dc..ca067e2 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -221,7 +221,7 @@
 
     const bool isVendorService =
         strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
-    const long timeout = 5000;
+    constexpr int64_t timeout = 5000;
     int64_t startTime = uptimeMillis();
     // Vendor code can't access system properties
     if (!gSystemBootCompleted && !isVendorService) {
@@ -234,7 +234,7 @@
 #endif
     }
     // retry interval in millisecond; note that vendor services stay at 100ms
-    const long sleepTime = gSystemBootCompleted ? 1000 : 100;
+    const useconds_t sleepTime = gSystemBootCompleted ? 1000 : 100;
 
     ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
           ProcessState::self()->getDriverName().c_str());
@@ -310,7 +310,7 @@
     // 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)) {}
+        explicit Defer(std::function<void()>&& f) : mF(std::move(f)) {}
         ~Defer() { mF(); }
     private:
         std::function<void()> mF;
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index b21af96..4714234 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -75,6 +75,7 @@
 
 // ----------------------------------------------------------------------
 
+// NOLINTNEXTLINE(google-default-arguments)
 status_t BnUidObserver::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 58df52d..b1b2aa0 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -171,7 +171,8 @@
     if (status != OK) return status;
 
     internal::Stability::tryMarkCompilationUnit(binder.get());
-    return writeInt32(internal::Stability::get(binder.get()));
+    auto category = internal::Stability::getCategory(binder.get());
+    return writeInt32(category.repr());
 }
 
 status_t Parcel::finishUnflattenBinder(
@@ -181,7 +182,7 @@
     status_t status = readInt32(&stability);
     if (status != OK) return status;
 
-    status = internal::Stability::set(binder.get(), stability, true /*log*/);
+    status = internal::Stability::setRepr(binder.get(), stability, true /*log*/);
     if (status != OK) return status;
 
     *out = binder;
@@ -2498,7 +2499,7 @@
 }
 
 void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
-    const binder_size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie)
+    const binder_size_t* objects, size_t objectsCount, release_func relFunc)
 {
     binder_size_t minOffset = 0;
     freeDataNoInit();
@@ -2513,7 +2514,6 @@
     mNextObjectHint = 0;
     mObjectsSorted = false;
     mOwner = relFunc;
-    mOwnerCookie = relCookie;
     for (size_t i = 0; i < mObjectsSize; i++) {
         binder_size_t offset = mObjects[i];
         if (offset < minOffset) {
@@ -2614,7 +2614,7 @@
     if (mOwner) {
         LOG_ALLOC("Parcel %p: freeing other owner data", this);
         //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
-        mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
+        mOwner(this, mData, mDataSize, mObjects, mObjectsSize);
     } else {
         LOG_ALLOC("Parcel %p: freeing allocated data", this);
         releaseObjects();
@@ -2777,7 +2777,7 @@
             memcpy(objects, mObjects, objectsSize*sizeof(binder_size_t));
         }
         //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
-        mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
+        mOwner(this, mData, mDataSize, mObjects, mObjectsSize);
         mOwner = nullptr;
 
         LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 97a6c94..c807cfe 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -34,10 +34,22 @@
 using android::sp;
 using android::status_t;
 using android::UNEXPECTED_NULL;
+
+using android::binder::VAL_BOOLEAN;
+using android::binder::VAL_INTEGER;
+using android::binder::VAL_LONG;
+using android::binder::VAL_DOUBLE;
+using android::binder::VAL_STRING;
+using android::binder::VAL_BOOLEANARRAY;
+using android::binder::VAL_INTARRAY;
+using android::binder::VAL_LONGARRAY;
+using android::binder::VAL_DOUBLEARRAY;
+using android::binder::VAL_STRINGARRAY;
+using android::binder::VAL_PERSISTABLEBUNDLE;
+
 using std::map;
 using std::set;
 using std::vector;
-using namespace ::android::binder;
 
 enum {
     // Keep them in sync with BUNDLE_MAGIC* in frameworks/base/core/java/android/os/BaseBundle.java.
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 6115aec..339c538 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "Stability"
+
 #include <binder/Stability.h>
 
 #include <binder/BpBinder.h>
@@ -21,34 +23,59 @@
 namespace android {
 namespace internal {
 
+// the libbinder parcel format is currently unstable
+
+// oldest version which is supported
+constexpr uint8_t kBinderWireFormatOldest = 1;
+// current version
+constexpr uint8_t kBinderWireFormatVersion = 1;
+
+Stability::Category Stability::Category::currentFromLevel(Level level) {
+    return {
+        .version = kBinderWireFormatVersion,
+        .reserved = {0},
+        .level = level,
+    };
+}
+
+std::string Stability::Category::debugString() {
+    return levelString(level) + " wire protocol version "
+        + std::to_string(version);
+}
+
 void Stability::markCompilationUnit(IBinder* binder) {
-    status_t result = set(binder, getLocalStability(), true /*log*/);
+    auto stability = Category::currentFromLevel(getLocalLevel());
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 void Stability::markVintf(IBinder* binder) {
-    status_t result = set(binder, Level::VINTF, true /*log*/);
+    auto stability = Category::currentFromLevel(Level::VINTF);
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
-    ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
+    auto stability = getCategory(binder.get());
+    ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str());
 }
 
 void Stability::markVndk(IBinder* binder) {
-    status_t result = set(binder, Level::VENDOR, true /*log*/);
+    auto stability = Category::currentFromLevel(Level::VENDOR);
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) {
-    return check(get(binder.get()), Level::VINTF);
+    return check(getCategory(binder.get()), Level::VINTF);
 }
 
 void Stability::tryMarkCompilationUnit(IBinder* binder) {
-    (void) set(binder, getLocalStability(), false /*log*/);
+    auto stability = Category::currentFromLevel(getLocalLevel());
+    (void) setRepr(binder, stability.repr(), false /*log*/);
 }
 
-Stability::Level Stability::getLocalStability() {
+Stability::Level Stability::getLocalLevel() {
 #ifdef __ANDROID_VNDK__
     #ifdef __ANDROID_APEX__
         // TODO(b/142684679) avoid use_vendor on system APEXes
@@ -67,65 +94,81 @@
 #endif
 }
 
-status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
-    Level currentStability = get(binder);
+status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) {
+    auto current = getCategory(binder);
+    auto setting = Category::fromRepr(representation);
+
+    // If we have ahold of a binder with a newer declared version, then it
+    // should support older versions, and we will simply write our parcels with
+    // the current wire parcel format.
+    if (setting.version < kBinderWireFormatOldest) {
+        // always log, because this shouldn't happen
+        ALOGE("Cannot accept binder with older binder wire protocol version "
+              "%u. Versions less than %u are unsupported.", setting.version,
+               kBinderWireFormatOldest);
+        return BAD_TYPE;
+    }
 
     // null binder is always written w/ 'UNDECLARED' stability
     if (binder == nullptr) {
-        if (stability == UNDECLARED) {
+        if (setting.level == UNDECLARED) {
             return OK;
         } else {
             if (log) {
                 ALOGE("Null binder written with stability %s.",
-                    stabilityString(stability).c_str());
+                    levelString(setting.level).c_str());
             }
             return BAD_TYPE;
         }
     }
 
-    if (!isDeclaredStability(stability)) {
+    if (!isDeclaredLevel(setting.level)) {
         if (log) {
-            ALOGE("Can only set known stability, not %d.", stability);
+            ALOGE("Can only set known stability, not %u.", setting.level);
         }
         return BAD_TYPE;
     }
 
-    if (currentStability != Level::UNDECLARED && currentStability != stability) {
+    if (current.repr() != 0 && current != setting) {
         if (log) {
-            ALOGE("Interface being set with %s but it is already marked as %s.",
-                stabilityString(stability).c_str(), stabilityString(currentStability).c_str());
+            ALOGE("Interface being set with %s but it is already marked as %s",
+                  setting.debugString().c_str(),
+                  current.debugString().c_str());
         }
         return BAD_TYPE;
     }
 
-    if (currentStability == stability) return OK;
+    if (current == setting) return OK;
 
     BBinder* local = binder->localBinder();
     if (local != nullptr) {
-        local->mStability = static_cast<int32_t>(stability);
+        local->mStability = setting.repr();
     } else {
-        binder->remoteBinder()->mStability = static_cast<int32_t>(stability);
+        binder->remoteBinder()->mStability = setting.repr();
     }
 
     return OK;
 }
 
-Stability::Level Stability::get(IBinder* binder) {
-    if (binder == nullptr) return UNDECLARED;
+Stability::Category Stability::getCategory(IBinder* binder) {
+    if (binder == nullptr) {
+        return Category::currentFromLevel(Level::UNDECLARED);
+    }
 
     BBinder* local = binder->localBinder();
     if (local != nullptr) {
-        return static_cast<Stability::Level>(local->mStability);
+        return Category::fromRepr(local->mStability);
     }
 
-    return static_cast<Stability::Level>(binder->remoteBinder()->mStability);
+    return Category::fromRepr(binder->remoteBinder()->mStability);
 }
 
-bool Stability::check(int32_t provided, Level required) {
-    bool stable = (provided & required) == required;
+bool Stability::check(Category provided, Level required) {
+    bool stable = (provided.level & required) == required;
 
-    if (!isDeclaredStability(provided) && provided != UNDECLARED) {
-        ALOGE("Unknown stability when checking interface stability %d.", provided);
+    if (provided.level != UNDECLARED && !isDeclaredLevel(provided.level)) {
+        ALOGE("Unknown stability when checking interface stability %d.",
+              provided.level);
 
         stable = false;
     }
@@ -133,18 +176,18 @@
     return stable;
 }
 
-bool Stability::isDeclaredStability(int32_t stability) {
+bool Stability::isDeclaredLevel(Level stability) {
     return stability == VENDOR || stability == SYSTEM || stability == VINTF;
 }
 
-std::string Stability::stabilityString(int32_t stability) {
-    switch (stability) {
+std::string Stability::levelString(Level level) {
+    switch (level) {
         case Level::UNDECLARED: return "undeclared stability";
         case Level::VENDOR: return "vendor stability";
         case Level::SYSTEM: return "system stability";
         case Level::VINTF: return "vintf stability";
     }
-    return "unknown stability " + std::to_string(stability);
+    return "unknown stability " + std::to_string(level);
 }
 
 }  // namespace internal
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 64ab7a9..b5a078c 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -245,10 +245,5 @@
     return ret;
 }
 
-std::stringstream& operator<< (std::stringstream& stream, const Status& s) {
-    stream << s.toString8().string();
-    return stream;
-}
-
 }  // namespace binder
 }  // namespace android
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
index ac4b4ca..f92d557 100644
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ b/libs/binder/include/binder/IMediaResourceMonitor.h
@@ -45,6 +45,7 @@
 
 class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
 public:
+    // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
             uint32_t flags = 0);
 };
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index a3712c9..4da8aa1 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -146,7 +146,7 @@
             void                blockUntilThreadAvailable();
 
             // Service manager registration
-            void                setTheContextObject(sp<BBinder> obj);
+            void                setTheContextObject(const sp<BBinder>& obj);
 
             // WARNING: DO NOT USE THIS API
             //
@@ -185,9 +185,8 @@
     static  void                threadDestructor(void *st);
     static  void                freeBuffer(Parcel* parcel,
                                            const uint8_t* data, size_t dataSize,
-                                           const binder_size_t* objects, size_t objectsSize,
-                                           void* cookie);
-    
+                                           const binder_size_t* objects, size_t objectsSize);
+
     const   sp<ProcessState>    mProcess;
             Vector<BBinder*>    mPendingStrongDerefs;
             Vector<RefBase::weakref_type*> mPendingWeakDerefs;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 138d957..ece25a0 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -33,18 +33,20 @@
 #include <binder/Parcelable.h>
 
 #ifdef BINDER_IPC_32BIT
+//NOLINTNEXTLINE(google-runtime-int) b/173188702
 typedef unsigned int binder_size_t;
 #else
+//NOLINTNEXTLINE(google-runtime-int) b/173188702
 typedef unsigned long long binder_size_t;
 #endif
 
+struct flat_binder_object;
 
 // ---------------------------------------------------------------------------
 namespace android {
 
 template <typename T> class Flattenable;
 template <typename T> class LightFlattenable;
-struct flat_binder_object;
 class IBinder;
 class IPCThreadState;
 class ProcessState;
@@ -485,24 +487,21 @@
     // uid.
     uid_t               readCallingWorkSourceUid() const;
 
+    void                print(TextOutput& to, uint32_t flags = 0) const;
+
 private:
     typedef void        (*release_func)(Parcel* parcel,
                                         const uint8_t* data, size_t dataSize,
-                                        const binder_size_t* objects, size_t objectsSize,
-                                        void* cookie);
-                        
+                                        const binder_size_t* objects, size_t objectsSize);
+
     uintptr_t           ipcData() const;
     size_t              ipcDataSize() const;
     uintptr_t           ipcObjects() const;
     size_t              ipcObjectsCount() const;
     void                ipcSetDataReference(const uint8_t* data, size_t dataSize,
                                             const binder_size_t* objects, size_t objectsCount,
-                                            release_func relFunc, void* relCookie);
-    
-public:
-    void                print(TextOutput& to, uint32_t flags = 0) const;
+                                            release_func relFunc);
 
-private:
                         Parcel(const Parcel& o);
     Parcel&             operator=(const Parcel& o);
     
@@ -609,7 +608,9 @@
     mutable bool        mDeallocZero;
 
     release_func        mOwner;
-    void*               mOwnerCookie;
+
+    // TODO(167966510): reserved for binder/version/stability
+    void*               mReserved = reinterpret_cast<void*>(0xAAAAAAAA);
 
     class Blob {
     public:
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 4ba6ba8..9896fd7 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -43,22 +43,22 @@
     android::status_t readFromParcel(const android::Parcel* parcel) override;
 
     inline bool operator!=(const ParcelFileDescriptor& rhs) const {
-        return mFd != rhs.mFd;
+        return mFd.get() != rhs.mFd.get();
     }
     inline bool operator<(const ParcelFileDescriptor& rhs) const {
-        return mFd < rhs.mFd;
+        return mFd.get() < rhs.mFd.get();
     }
     inline bool operator<=(const ParcelFileDescriptor& rhs) const {
-        return mFd <= rhs.mFd;
+        return mFd.get() <= rhs.mFd.get();
     }
     inline bool operator==(const ParcelFileDescriptor& rhs) const {
-        return mFd == rhs.mFd;
+        return mFd.get() == rhs.mFd.get();
     }
     inline bool operator>(const ParcelFileDescriptor& rhs) const {
-        return mFd > rhs.mFd;
+        return mFd.get() > rhs.mFd.get();
     }
     inline bool operator>=(const ParcelFileDescriptor& rhs) const {
-        return mFd >= rhs.mFd;
+        return mFd.get() >= rhs.mFd.get();
     }
 private:
     android::base::unique_fd mFd;
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 6566285..12272ba 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -26,6 +26,29 @@
 
 namespace internal {
 
+// Stability encodes how a binder changes over time. There are two levels of
+// stability:
+// 1). the interface stability - this is how a particular set of API calls (a
+//   particular ordering of things like writeInt32/readInt32) are changed over
+//   time. If one release, we have 'writeInt32' and the next release, we have
+//   'writeInt64', then this interface doesn't have a very stable
+//   Stability::Level. Usually this ordering is controlled by a .aidl file.
+// 2). the wire format stability - this is how these API calls map to actual
+//   bytes that are written to the wire (literally, this is how they are written
+//   to the kernel inside of IBinder::transact, but it may be expanded to other
+//   wires in the future). For instance, writeInt32 in binder translates to
+//   writing a 4-byte little-endian integer in two's complement. You can imagine
+//   in the future, we change writeInt32/readInt32 to instead write 8-bytes with
+//   that integer and some check bits. In this case, the wire format changes,
+//   but as long as a client libbinder knows to keep on writing a 4-byte value
+//   to old servers, and new servers know how to interpret the 8-byte result,
+//   they can still communicate.
+//
+// Every binder object has a stability level associated with it, and when
+// communicating with a binder, we make sure that the command we sent is one
+// that it knows how to process. The summary of stability of a binder is
+// represented by a Stability::Category object.
+
 // WARNING: These APIs are only ever expected to be called by auto-generated code.
 //     Instead of calling them, you should set the stability of a .aidl interface
 class Stability final {
@@ -73,7 +96,7 @@
 
     static void tryMarkCompilationUnit(IBinder* binder);
 
-    enum Level : int32_t {
+    enum Level : uint8_t {
         UNDECLARED = 0,
 
         VENDOR = 0b000011,
@@ -81,19 +104,54 @@
         VINTF = 0b111111,
     };
 
+    // This is the format of stability passed on the wire.
+    struct Category {
+        static inline Category fromRepr(int32_t representation) {
+            return *reinterpret_cast<Category*>(&representation);
+        }
+        int32_t repr() const {
+            return *reinterpret_cast<const int32_t*>(this);
+        }
+        static inline Category currentFromLevel(Level level);
+
+        bool operator== (const Category& o) const {
+            return repr() == o.repr();
+        }
+        bool operator!= (const Category& o) const {
+            return !(*this == o);
+        }
+
+        std::string debugString();
+
+        // This is the version of the wire protocol associated with the host
+        // process of a particular binder. As the wire protocol changes, if
+        // sending a transaction to a binder with an old version, the Parcel
+        // class must write parcels according to the version documented here.
+        uint8_t version;
+
+        uint8_t reserved[2];
+
+        // bitmask of Stability::Level
+        Level level;
+    };
+    static_assert(sizeof(Category) == sizeof(int32_t));
+
     // returns the stability according to how this was built
-    static Level getLocalStability();
+    static Level getLocalLevel();
 
     // applies stability to binder if stability level is known
     __attribute__((warn_unused_result))
-    static status_t set(IBinder* binder, int32_t stability, bool log);
+    static status_t setRepr(IBinder* binder, int32_t representation, bool log);
 
-    static Level get(IBinder* binder);
+    // get stability information as encoded on the wire
+    static Category getCategory(IBinder* binder);
 
-    static bool check(int32_t provided, Level required);
+    // whether a transaction on binder is allowed, if the transaction
+    // is done from a context with a specific stability level
+    static bool check(Category provided, Level required);
 
-    static bool isDeclaredStability(int32_t stability);
-    static std::string stabilityString(int32_t stability);
+    static bool isDeclaredLevel(Level level);
+    static std::string levelString(Level level);
 
     Stability();
 };
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index 7d889b6..c30ae01 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -18,7 +18,8 @@
 #define ANDROID_BINDER_STATUS_H
 
 #include <cstdint>
-#include <sstream>
+#include <sstream> // historical
+#include <ostream>
 
 #include <binder/Parcel.h>
 #include <utils/String8.h>
@@ -153,8 +154,9 @@
     String8 mMessage;
 };  // class Status
 
-// For gtest output logging
-std::stringstream& operator<< (std::stringstream& stream, const Status& s);
+static inline std::ostream& operator<< (std::ostream& o, const Status& s) {
+    return o << s.toString8();
+}
 
 }  // namespace binder
 }  // namespace android
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index 0fe7f5b..5a719b8 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -17,10 +17,6 @@
 #ifndef _BINDER_MODULE_H_
 #define _BINDER_MODULE_H_
 
-#ifdef __cplusplus
-namespace android {
-#endif
-
 /* obtain structures and constants from the kernel header */
 
 // TODO(b/31559095): bionic on host
@@ -36,6 +32,10 @@
 #include <sys/ioctl.h>
 #include <linux/android/binder.h>
 
+#ifdef __cplusplus
+namespace android {
+#endif
+
 #ifndef BR_FROZEN_REPLY
 // Temporary definition of BR_FROZEN_REPLY. For production
 // this will come from UAPI binder.h
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index cecc759..a57beee 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -98,6 +98,14 @@
             "30",
         ],
     },
+    tidy: true,
+    tidy_flags: [
+        // Only check our headers
+        "--header-filter=^.*frameworks/native/libs/binder/.*.h$",
+    ],
+    tidy_checks_as_errors: [
+        "*",
+    ],
 }
 
 ndk_headers {
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index b927f6f..5e2e1bd 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -367,7 +367,7 @@
                            mDeathRecipients.end());
 }
 
-binder_status_t AIBinder_DeathRecipient::linkToDeath(sp<IBinder> binder, void* cookie) {
+binder_status_t AIBinder_DeathRecipient::linkToDeath(const sp<IBinder>& binder, void* cookie) {
     CHECK(binder != nullptr);
 
     std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
@@ -386,7 +386,7 @@
     return STATUS_OK;
 }
 
-binder_status_t AIBinder_DeathRecipient::unlinkToDeath(sp<IBinder> binder, void* cookie) {
+binder_status_t AIBinder_DeathRecipient::unlinkToDeath(const sp<IBinder>& binder, void* cookie) {
     CHECK(binder != nullptr);
 
     std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 0fa47c6..6236e81 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -161,8 +161,8 @@
     };
 
     explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
-    binder_status_t linkToDeath(::android::sp<::android::IBinder>, void* cookie);
-    binder_status_t unlinkToDeath(::android::sp<::android::IBinder> binder, void* cookie);
+    binder_status_t linkToDeath(const ::android::sp<::android::IBinder>&, void* cookie);
+    binder_status_t unlinkToDeath(const ::android::sp<::android::IBinder>& binder, void* cookie);
 
    private:
     // When the user of this API deletes a Bp object but not the death recipient, the
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 8d60226..2d85f90 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -74,6 +74,9 @@
      * ownership of that other object.
      */
     SpAIBinder& operator=(const SpAIBinder& other) {
+        if (this == &other) {
+            return *this;
+        }
         AIBinder_incStrong(other.mBinder);
         set(other.mBinder);
         return *this;
@@ -170,8 +173,10 @@
     ScopedAResource& operator=(const ScopedAResource&) = delete;
 
     // move-constructing/assignment is okay
-    ScopedAResource(ScopedAResource&& other) : mT(std::move(other.mT)) { other.mT = DEFAULT; }
-    ScopedAResource& operator=(ScopedAResource&& other) {
+    ScopedAResource(ScopedAResource&& other) noexcept : mT(std::move(other.mT)) {
+        other.mT = DEFAULT;
+    }
+    ScopedAResource& operator=(ScopedAResource&& other) noexcept {
         set(other.mT);
         other.mT = DEFAULT;
         return *this;
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 55c5de9..d54de49 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -548,7 +548,7 @@
 }
 
 // Return true if all the required libraries from vndk and sphal namespace are
-// linked to the Game Driver namespace correctly.
+// linked to the updatable gfx driver namespace correctly.
 bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
     const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
     if (llndkLibraries.empty()) {
diff --git a/libs/input/tests/NamedEnum_test.cpp b/libs/input/tests/NamedEnum_test.cpp
index 4e93f71..74a0044 100644
--- a/libs/input/tests/NamedEnum_test.cpp
+++ b/libs/input/tests/NamedEnum_test.cpp
@@ -86,9 +86,9 @@
 
 TEST(NamedEnum, RuntimeUnknownNamedEnumAsString) {
     TestEnums e = static_cast<TestEnums>(0x5);
-    ASSERT_EQ(NamedEnum::string(e), "0x00000005");
+    ASSERT_EQ(NamedEnum::string(e), "05");
     e = static_cast<TestEnums>(0x9);
-    ASSERT_EQ(NamedEnum::string(e), "0x00000009");
+    ASSERT_EQ(NamedEnum::string(e, "0x%08x"), "0x00000009");
 }
 
 TEST(NamedEnum, CompileTimeFlagName) {
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index f799ce4..636fbde 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -1052,7 +1052,7 @@
 Gralloc4Allocator::Gralloc4Allocator(const Gralloc4Mapper& mapper) : mMapper(mapper) {
     mAllocator = IAllocator::getService();
     if (mAllocator == nullptr) {
-        ALOGW("allocator 3.x is not supported");
+        ALOGW("allocator 4.x is not supported");
         return;
     }
 }
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 1afc693..76fd7f0 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -514,6 +514,8 @@
         if (so) {
             return so;
         }
+        ALOGE("Could not load %s from updatable gfx driver namespace: %s.", name.c_str(),
+              dlerror());
     }
     return nullptr;
 }
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index 33520b2..8073a93 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -19,6 +19,25 @@
     },
     {
       "name": "libinputservice_test"
+    },
+    {
+      "name": "CtsInputTestCases"
+    },
+    {
+      "name": "CtsViewTestCases",
+      "options": [
+        {
+          "include-filter": "android.view.cts.MotionEventTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsSecurityTestCases",
+      "options": [
+        {
+          "include-filter": "android.security.cts.MotionEventTest"
+        }
+      ]
     }
   ]
 }
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index c2d165e..9fea298 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -50,12 +50,18 @@
 private:
     void notifyConfigurationChanged(nsecs_t) override {}
 
-    std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>&,
-                                       const sp<IBinder>&, const std::string& name) override {
-        ALOGE("The window is not responding : %s", name.c_str());
-        return 0s;
+    void notifyNoFocusedWindowAnr(
+            const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
+        ALOGE("There is no focused window for %s", applicationHandle->getName().c_str());
     }
 
+    void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken,
+                                      const std::string& reason) override {
+        ALOGE("Connection is not responding: %s", reason.c_str());
+    }
+
+    void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {}
+
     void notifyInputChannelBroken(const sp<IBinder>&) override {}
 
     void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index e5d208a..ff5f6d8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2336,7 +2336,7 @@
 }
 
 std::string InputDispatcher::getApplicationWindowLabel(
-        const std::shared_ptr<InputApplicationHandle>& applicationHandle,
+        const InputApplicationHandle* applicationHandle,
         const sp<InputWindowHandle>& windowHandle) {
     if (applicationHandle != nullptr) {
         if (windowHandle != nullptr) {
@@ -4922,24 +4922,21 @@
     sp<IBinder> connectionToken = connection.inputChannel->getConnectionToken();
     updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
 
-    std::unique_ptr<CommandEntry> commandEntry =
-            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
-    commandEntry->inputApplicationHandle = nullptr;
+    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
+            &InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible);
     commandEntry->connectionToken = connectionToken;
     commandEntry->reason = std::move(reason);
     postCommandLocked(std::move(commandEntry));
 }
 
-void InputDispatcher::onAnrLocked(const std::shared_ptr<InputApplicationHandle>& application) {
-    std::string reason = android::base::StringPrintf("%s does not have a focused window",
-                                                     application->getName().c_str());
+void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) {
+    std::string reason =
+            StringPrintf("%s does not have a focused window", application->getName().c_str());
+    updateLastAnrStateLocked(*application, reason);
 
-    updateLastAnrStateLocked(application, reason);
-
-    std::unique_ptr<CommandEntry> commandEntry =
-            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
-    commandEntry->inputApplicationHandle = application;
-    commandEntry->reason = std::move(reason);
+    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
+            &InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible);
+    commandEntry->inputApplicationHandle = std::move(application);
     postCommandLocked(std::move(commandEntry));
 }
 
@@ -4956,9 +4953,9 @@
     updateLastAnrStateLocked(windowLabel, reason);
 }
 
-void InputDispatcher::updateLastAnrStateLocked(
-        const std::shared_ptr<InputApplicationHandle>& application, const std::string& reason) {
-    const std::string windowLabel = getApplicationWindowLabel(application, nullptr);
+void InputDispatcher::updateLastAnrStateLocked(const InputApplicationHandle& application,
+                                               const std::string& reason) {
+    const std::string windowLabel = getApplicationWindowLabel(&application, nullptr);
     updateLastAnrStateLocked(windowLabel, reason);
 }
 
@@ -5006,24 +5003,36 @@
     mLock.lock();
 }
 
-void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) {
     mLock.unlock();
-    const sp<IBinder>& token = commandEntry->connectionToken;
-    const std::chrono::nanoseconds timeoutExtension =
-            mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);
+
+    mPolicy->notifyNoFocusedWindowAnr(commandEntry->inputApplicationHandle);
+
+    mLock.lock();
+}
+
+void InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible(
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConnectionUnresponsive(commandEntry->connectionToken, commandEntry->reason);
 
     mLock.lock();
 
-    if (timeoutExtension > 0s) {
-        extendAnrTimeoutsLocked(commandEntry->inputApplicationHandle, token, timeoutExtension);
-    } else {
-        // stop waking up for events in this connection, it is already not responding
-        sp<Connection> connection = getConnectionLocked(token);
-        if (connection == nullptr) {
-            return;
-        }
-        cancelEventsForAnrLocked(connection);
+    // stop waking up for events in this connection, it is already not responding
+    sp<Connection> connection = getConnectionLocked(commandEntry->connectionToken);
+    if (connection == nullptr) {
+        return;
     }
+    cancelEventsForAnrLocked(connection);
+}
+
+void InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConnectionResponsive(commandEntry->connectionToken);
+
+    mLock.lock();
 }
 
 void InputDispatcher::doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) {
@@ -5034,35 +5043,6 @@
     mLock.lock();
 }
 
-void InputDispatcher::extendAnrTimeoutsLocked(
-        const std::shared_ptr<InputApplicationHandle>& application,
-        const sp<IBinder>& connectionToken, std::chrono::nanoseconds timeoutExtension) {
-    if (connectionToken == nullptr && application != nullptr) {
-        // The ANR happened because there's no focused window
-        mNoFocusedWindowTimeoutTime = now() + timeoutExtension.count();
-        mAwaitedFocusedApplication = application;
-    }
-
-    sp<Connection> connection = getConnectionLocked(connectionToken);
-    if (connection == nullptr) {
-        // It's possible that the connection already disappeared. No action necessary.
-        return;
-    }
-
-    ALOGI("Raised ANR, but the policy wants to keep waiting on %s for %" PRId64 "ms longer",
-          connection->inputChannel->getName().c_str(), millis(timeoutExtension));
-
-    connection->responsive = true;
-    const nsecs_t newTimeout = now() + timeoutExtension.count();
-    for (DispatchEntry* entry : connection->waitQueue) {
-        if (newTimeout >= entry->timeoutTime) {
-            // Already removed old entries when connection was marked unresponsive
-            entry->timeoutTime = newTimeout;
-            mAnrTracker.insert(entry->timeoutTime, connectionToken);
-        }
-    }
-}
-
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
         CommandEntry* commandEntry) {
     KeyEntry& entry = *(commandEntry->keyEntry);
@@ -5150,10 +5130,19 @@
     if (dispatchEntryIt != connection->waitQueue.end()) {
         dispatchEntry = *dispatchEntryIt;
         connection->waitQueue.erase(dispatchEntryIt);
-        mAnrTracker.erase(dispatchEntry->timeoutTime,
-                          connection->inputChannel->getConnectionToken());
+        const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken();
+        mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
         if (!connection->responsive) {
             connection->responsive = isConnectionResponsive(*connection);
+            if (connection->responsive) {
+                // The connection was unresponsive, and now it's responsive. Tell the policy
+                // about it so that it can stop ANR.
+                std::unique_ptr<CommandEntry> connectionResponsiveCommand =
+                        std::make_unique<CommandEntry>(
+                                &InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible);
+                connectionResponsiveCommand->connectionToken = connectionToken;
+                postCommandLocked(std::move(connectionResponsiveCommand));
+            }
         }
         traceWaitQueueLength(connection);
         if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 5387c40..5704a5a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -419,9 +419,6 @@
     // Once a connection becomes unresponsive, its entries are removed from AnrTracker to
     // prevent unneeded wakeups.
     AnrTracker mAnrTracker GUARDED_BY(mLock);
-    void extendAnrTimeoutsLocked(const std::shared_ptr<InputApplicationHandle>& application,
-                                 const sp<IBinder>& connectionToken,
-                                 std::chrono::nanoseconds timeoutExtension) REQUIRES(mLock);
 
     // Contains the last window which received a hover event.
     sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock);
@@ -475,9 +472,8 @@
                                        int32_t y) const REQUIRES(mLock);
     bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
     std::string dumpWindowForTouchOcclusion(const InputWindowInfo* info, bool isTouchWindow) const;
-    std::string getApplicationWindowLabel(
-            const std::shared_ptr<InputApplicationHandle>& applicationHandle,
-            const sp<InputWindowHandle>& windowHandle);
+    std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle,
+                                          const sp<InputWindowHandle>& windowHandle);
 
     // Manage the dispatch cycle for a single connection.
     // These methods are deliberately not Interruptible because doing all of the work
@@ -554,11 +550,11 @@
     void notifyFocusChangedLocked(const sp<IBinder>& oldFocus, const sp<IBinder>& newFocus)
             REQUIRES(mLock);
     void onAnrLocked(const Connection& connection) REQUIRES(mLock);
-    void onAnrLocked(const std::shared_ptr<InputApplicationHandle>& application) REQUIRES(mLock);
+    void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock);
     void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock);
     void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason)
             REQUIRES(mLock);
-    void updateLastAnrStateLocked(const std::shared_ptr<InputApplicationHandle>& application,
+    void updateLastAnrStateLocked(const InputApplicationHandle& application,
                                   const std::string& reason) REQUIRES(mLock);
     void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason)
             REQUIRES(mLock);
@@ -568,7 +564,11 @@
             REQUIRES(mLock);
     void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
     void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
-    void doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
+    void doNotifyConnectionUnresponsiveLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
+    void doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry)
+            REQUIRES(mLock);
     void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
     void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry)
             REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 463c5f1..1125257 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -45,11 +45,25 @@
     /* Notifies the system that a configuration change has occurred. */
     virtual void notifyConfigurationChanged(nsecs_t when) = 0;
 
-    /* Notifies the system that an application is not responding.
-     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
-    virtual std::chrono::nanoseconds notifyAnr(
-            const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
-            const sp<IBinder>& token, const std::string& reason) = 0;
+    /* Notifies the system that an application does not have a focused window.
+     */
+    virtual void notifyNoFocusedWindowAnr(
+            const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0;
+
+    /* Notifies the system that a connection just became unresponsive. This indicates that ANR
+     * should be raised for this connection. The connection is identified via token.
+     * The string reason contains information about the input event that we haven't received
+     * a response for.
+     */
+    virtual void notifyConnectionUnresponsive(const sp<IBinder>& token,
+                                              const std::string& reason) = 0;
+
+    /* Notifies the system that a connection just became responsive. This is only called after the
+     * connection was first marked "unresponsive". This indicates that ANR dialog (if any) should
+     * no longer should be shown to the user. The connection is eligible to cause a new ANR in the
+     * future.
+     */
+    virtual void notifyConnectionResponsive(const sp<IBinder>& token) = 0;
 
     /* Notifies the system that an input channel is unrecoverably broken. */
     virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 40471b2..5ab2ae3 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -126,35 +126,62 @@
 
     // This function must be called soon after the expected ANR timer starts,
     // because we are also checking how much time has passed.
-    void assertNotifyAnrWasCalled(
+    void assertNotifyNoFocusedWindowAnrWasCalled(
             std::chrono::nanoseconds timeout,
-            const std::shared_ptr<InputApplicationHandle>& expectedApplication,
-            const sp<IBinder>& expectedToken) {
-        std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData;
-        ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
-        ASSERT_EQ(expectedApplication, anrData.first);
-        ASSERT_EQ(expectedToken, anrData.second);
+            const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
+        std::shared_ptr<InputApplicationHandle> application;
+        { // acquire lock
+            std::unique_lock lock(mLock);
+            android::base::ScopedLockAssertion assumeLocked(mLock);
+            ASSERT_NO_FATAL_FAILURE(
+                    application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
+        } // release lock
+        ASSERT_EQ(expectedApplication, application);
     }
 
-    std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
-            std::chrono::nanoseconds timeout) {
-        const std::chrono::time_point start = std::chrono::steady_clock::now();
+    void assertNotifyConnectionUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
+                                                     const sp<IBinder>& expectedConnectionToken) {
+        sp<IBinder> connectionToken = getUnresponsiveConnectionToken(timeout);
+        ASSERT_EQ(expectedConnectionToken, connectionToken);
+    }
+
+    void assertNotifyConnectionResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
+        sp<IBinder> connectionToken = getResponsiveConnectionToken();
+        ASSERT_EQ(expectedConnectionToken, connectionToken);
+    }
+
+    sp<IBinder> getUnresponsiveConnectionToken(std::chrono::nanoseconds timeout) {
         std::unique_lock lock(mLock);
-        std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
         android::base::ScopedLockAssertion assumeLocked(mLock);
+        return getAnrTokenLockedInterruptible(timeout, mAnrConnectionTokens, lock);
+    }
+
+    sp<IBinder> getResponsiveConnectionToken() {
+        std::unique_lock lock(mLock);
+        android::base::ScopedLockAssertion assumeLocked(mLock);
+        return getAnrTokenLockedInterruptible(0s, mResponsiveConnectionTokens, lock);
+    }
+
+    // All three ANR-related callbacks behave the same way, so we use this generic function to wait
+    // for a specific container to become non-empty. When the container is non-empty, return the
+    // first entry from the container and erase it.
+    template <class T>
+    T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
+                                     std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
+        const std::chrono::time_point start = std::chrono::steady_clock::now();
+        std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
 
         // If there is an ANR, Dispatcher won't be idle because there are still events
         // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
         // before checking if ANR was called.
-        // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
-        // it some time to act. 100ms seems reasonable.
-        mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
-            return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
-        });
+        // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
+        // to provide it some time to act. 100ms seems reasonable.
+        mNotifyAnr.wait_for(lock, timeToWait,
+                            [&storage]() REQUIRES(mLock) { return !storage.empty(); });
         const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
-        if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
-            ADD_FAILURE() << "Did not receive ANR callback";
-            return {};
+        if (storage.empty()) {
+            ADD_FAILURE() << "Did not receive the ANR callback";
+            return nullptr;
         }
         // Ensure that the ANR didn't get raised too early. We can't be too strict here because
         // the dispatcher started counting before this function was called
@@ -165,17 +192,18 @@
                           << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
                           << "ms instead";
         }
-        std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> result =
-                std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
-        mAnrApplications.pop();
-        mAnrWindowTokens.pop();
-        return result;
+        T token = storage.front();
+        storage.pop();
+        return token;
     }
 
     void assertNotifyAnrWasNotCalled() {
         std::scoped_lock lock(mLock);
         ASSERT_TRUE(mAnrApplications.empty());
-        ASSERT_TRUE(mAnrWindowTokens.empty());
+        ASSERT_TRUE(mAnrConnectionTokens.empty());
+        ASSERT_TRUE(mResponsiveConnectionTokens.empty())
+                << "ANR was not called, but please also consume the 'connection is responsive' "
+                   "signal";
     }
 
     void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
@@ -183,8 +211,6 @@
         mConfig.keyRepeatDelay = delay;
     }
 
-    void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
-
 private:
     std::mutex mLock;
     std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
@@ -194,23 +220,33 @@
 
     // ANR handling
     std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
-    std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
+    std::queue<sp<IBinder>> mAnrConnectionTokens GUARDED_BY(mLock);
+    std::queue<sp<IBinder>> mResponsiveConnectionTokens GUARDED_BY(mLock);
     std::condition_variable mNotifyAnr;
-    std::chrono::nanoseconds mAnrTimeout = 0ms;
 
     void notifyConfigurationChanged(nsecs_t when) override {
         std::scoped_lock lock(mLock);
         mConfigurationChangedTime = when;
     }
 
-    std::chrono::nanoseconds notifyAnr(const std::shared_ptr<InputApplicationHandle>& application,
-                                       const sp<IBinder>& windowToken,
-                                       const std::string&) override {
+    void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken,
+                                      const std::string&) override {
         std::scoped_lock lock(mLock);
-        mAnrApplications.push(application);
-        mAnrWindowTokens.push(windowToken);
+        mAnrConnectionTokens.push(connectionToken);
         mNotifyAnr.notify_all();
-        return mAnrTimeout;
+    }
+
+    void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {
+        std::scoped_lock lock(mLock);
+        mResponsiveConnectionTokens.push(connectionToken);
+        mNotifyAnr.notify_all();
+    }
+
+    void notifyNoFocusedWindowAnr(
+            const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
+        std::scoped_lock lock(mLock);
+        mAnrApplications.push(applicationHandle);
+        mNotifyAnr.notify_all();
     }
 
     void notifyInputChannelBroken(const sp<IBinder>&) override {}
@@ -811,6 +847,12 @@
                      expectedFlags);
     }
 
+    void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
+                              int32_t expectedFlags = 0) {
+        consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
+                     expectedFlags);
+    }
+
     void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
         ASSERT_NE(mInputReceiver, nullptr)
                 << "Cannot consume events from a window with no receiver";
@@ -1761,9 +1803,11 @@
     std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
     ASSERT_TRUE(consumeSeq);
 
-    mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(DISPATCHING_TIMEOUT,
+                                                             monitor.getToken());
     monitor.finishEvent(*consumeSeq);
     ASSERT_TRUE(mDispatcher->waitForIdle());
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(monitor.getToken());
 }
 
 TEST_F(InputDispatcherTest, TestMoveEvent) {
@@ -2882,13 +2926,13 @@
     std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
     ASSERT_TRUE(sequenceNum);
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
 
-    // The remaining lines are not really needed for the test, but kept as a sanity check
     mWindow->finishEvent(*sequenceNum);
     mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
                           ADISPLAY_ID_DEFAULT, 0 /*flags*/);
     ASSERT_TRUE(mDispatcher->waitForIdle());
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
 }
 
 // Send a key to the app and have the app not respond right away.
@@ -2898,7 +2942,7 @@
     std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
     ASSERT_TRUE(sequenceNum);
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
     ASSERT_TRUE(mDispatcher->waitForIdle());
 }
 
@@ -2924,19 +2968,16 @@
                       InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
+    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
     ASSERT_TRUE(mDispatcher->waitForIdle());
 }
 
 // We have a focused application, but no focused window
-// If the policy wants to keep waiting on the focused window to be added, make sure
-// that this timeout extension is honored and ANR is raised again.
-TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
+// Make sure that we don't notify policy twice about the same ANR.
+TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
     mWindow->setFocusable(false);
     mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
     mWindow->consumeFocusEvent(false);
-    const std::chrono::duration timeout = 5ms;
-    mFakePolicy->setAnrTimeout(timeout);
 
     // Once a focused event arrives, we get an ANR for this application
     // We specify the injection timeout to be smaller than the application timeout, to ensure that
@@ -2947,14 +2988,14 @@
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
     const std::chrono::duration appTimeout =
             mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
+    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
 
-    // After the extended time has passed, ANR should be raised again
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
+    std::this_thread::sleep_for(appTimeout);
+    // ANR should not be raised again. It is up to policy to do that if it desires.
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 
-    // If we stop extending the timeout, dispatcher should go to idle.
-    // Another ANR may be raised during this time
-    mFakePolicy->setAnrTimeout(0ms);
+    // If we now get a focused window, the ANR should stop, but the policy handles that via
+    // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
     ASSERT_TRUE(mDispatcher->waitForIdle());
 }
 
@@ -2971,7 +3012,7 @@
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
 
     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
+    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
 
     // Future focused events get dropped right away
     ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
@@ -3006,7 +3047,7 @@
     // We have now sent down and up. Let's consume first event and then ANR on the second.
     mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
 }
 
 // If an app is not responding to a key event, gesture monitors should continue to receive
@@ -3023,7 +3064,7 @@
 
     // Stuck on the ACTION_UP
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
 
     // New tap will go to the gesture monitor, but not to the window
     tapOnWindow();
@@ -3032,6 +3073,7 @@
 
     mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
     mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
     mWindow->assertNoEvents();
     monitor.assertNoEvents();
 }
@@ -3050,7 +3092,7 @@
     mWindow->consumeMotionDown();
     // Stuck on the ACTION_UP
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
 
     // New tap will go to the gesture monitor, but not to the window
     tapOnWindow();
@@ -3059,6 +3101,7 @@
 
     mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
     mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
     mWindow->assertNoEvents();
     monitor.assertNoEvents();
 }
@@ -3075,46 +3118,43 @@
     mWindow->consumeMotionDown();
     // Block on ACTION_UP
     const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
     mWindow->consumeMotionUp(); // Now the connection should be healthy again
     mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
     mWindow->assertNoEvents();
 
     tapOnWindow();
     mWindow->consumeMotionDown();
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
     mWindow->consumeMotionUp();
 
     mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
+    mFakePolicy->assertNotifyAnrWasNotCalled();
     mWindow->assertNoEvents();
 }
 
-// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
-// is honored
-TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
-    const std::chrono::duration timeout = 5ms;
-    mFakePolicy->setAnrTimeout(timeout);
-
+// If a connection remains unresponsive for a while, make sure policy is only notified once about
+// it.
+TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
     ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
               injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                                WINDOW_LOCATION));
 
     const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
-                                          mWindow->getToken());
-
-    // Since the policy wanted to extend ANR, make sure it is called again after the extension
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
-    mFakePolicy->setAnrTimeout(0ms);
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
     std::this_thread::sleep_for(windowTimeout);
-    // We are not checking if ANR has been called, because it may have been called again by the
-    // time we set the timeout to 0
-
-    // When the policy finally says stop, we should get ACTION_CANCEL
+    // 'notifyConnectionUnresponsive' should only be called once per connection
+    mFakePolicy->assertNotifyAnrWasNotCalled();
+    // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
     mWindow->consumeMotionDown();
     mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
                           ADISPLAY_ID_DEFAULT, 0 /*flags*/);
     mWindow->assertNoEvents();
+    mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
 /**
@@ -3278,17 +3318,22 @@
                                FOCUSED_WINDOW_LOCATION));
     std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
     ASSERT_TRUE(unfocusedSequenceNum);
-    std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
-    ASSERT_TRUE(focusedSequenceNum);
 
     const std::chrono::duration timeout =
             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
-                                          mFocusedWindow->getToken());
-
-    mFocusedWindow->finishEvent(*focusedSequenceNum);
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
+    // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
+    // sequence to make it consistent
+    mFocusedWindow->consumeMotionCancel();
     mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
+    mFocusedWindow->consumeMotionDown();
+    // This cancel is generated because the connection was unresponsive
+    mFocusedWindow->consumeMotionCancel();
+    mFocusedWindow->assertNoEvents();
+    mUnfocusedWindow->assertNoEvents();
     ASSERT_TRUE(mDispatcher->waitForIdle());
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
 // If we have 2 windows with identical timeouts that are both unresponsive,
@@ -3301,19 +3346,31 @@
 
     tapOnFocusedWindow();
     // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
-    std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData1 =
-            mFakePolicy->getNotifyAnrData(10ms);
-    std::pair<std::shared_ptr<InputApplicationHandle>, sp<IBinder>> anrData2 =
-            mFakePolicy->getNotifyAnrData(0ms);
+    sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveConnectionToken(10ms);
+    sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveConnectionToken(0ms);
 
     // We don't know which window will ANR first. But both of them should happen eventually.
-    ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
-                mFocusedWindow->getToken() == anrData2.second);
-    ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
-                mUnfocusedWindow->getToken() == anrData2.second);
+    ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
+                mFocusedWindow->getToken() == anrConnectionToken2);
+    ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
+                mUnfocusedWindow->getToken() == anrConnectionToken2);
 
     ASSERT_TRUE(mDispatcher->waitForIdle());
     mFakePolicy->assertNotifyAnrWasNotCalled();
+
+    mFocusedWindow->consumeMotionDown();
+    mFocusedWindow->consumeMotionUp();
+    mUnfocusedWindow->consumeMotionOutside();
+
+    sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveConnectionToken();
+    sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveConnectionToken();
+
+    // Both applications should be marked as responsive, in any order
+    ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
+                mFocusedWindow->getToken() == responsiveToken2);
+    ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
+                mUnfocusedWindow->getToken() == responsiveToken2);
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
 // If a window is already not responding, the second tap on the same window should be ignored.
@@ -3330,8 +3387,7 @@
     ASSERT_TRUE(upEventSequenceNum);
     const std::chrono::duration timeout =
             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
-                                          mFocusedWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
 
     // Tap once again
     // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
@@ -3351,7 +3407,8 @@
     ASSERT_TRUE(mDispatcher->waitForIdle());
     // The second tap did not go to the focused window
     mFocusedWindow->assertNoEvents();
-    // should not have another ANR after the window just became healthy again
+    // Since all events are finished, connection should be deemed healthy again
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
     mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
@@ -3437,6 +3494,7 @@
     mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
     mFocusedWindow->assertNoEvents();
     mUnfocusedWindow->assertNoEvents();
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
 // When the touch stream is split across 2 windows, and one of them does not respond,
@@ -3462,8 +3520,7 @@
 
     const std::chrono::duration timeout =
             mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
-                                          mFocusedWindow->getToken());
+    mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
 
     mUnfocusedWindow->consumeMotionDown();
     mFocusedWindow->consumeMotionDown();
@@ -3481,10 +3538,12 @@
     } else {
         ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
     }
-
     ASSERT_TRUE(mDispatcher->waitForIdle());
+    mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
+
     mUnfocusedWindow->assertNoEvents();
     mFocusedWindow->assertNoEvents();
+    mFakePolicy->assertNotifyAnrWasNotCalled();
 }
 
 /**
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b8b2fbc..27facd6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5660,9 +5660,14 @@
     const bool supportsProtected = getRenderEngine().supportsProtectedContent();
     bool hasProtectedLayer = false;
     if (allowProtected && supportsProtected) {
-        traverseLayers([&](Layer* layer) {
-            hasProtectedLayer = hasProtectedLayer || (layer->isVisible() && layer->isProtected());
-        });
+        hasProtectedLayer = schedule([=]() {
+                                bool protectedLayerFound = false;
+                                traverseLayers([&](Layer* layer) {
+                                    protectedLayerFound = protectedLayerFound ||
+                                            (layer->isVisible() && layer->isProtected());
+                                });
+                                return protectedLayerFound;
+                            }).get();
     }
 
     const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index fe9e737..28a3a81 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -716,23 +716,27 @@
     ATRACE_CALL();
     std::lock_guard<std::mutex> lock(mMutex);
 
-    // Only update layer stats if we're allowed to do so.
+    // Only update layer stats if we're already tracking the layer in TimeStats.
+    // Otherwise, continue tracking the statistic but use a default layer name instead.
     // As an implementation detail, we do this because this method is expected to be
-    // called from FrameTimeline, which is allowed to do jank analysis well after a frame is
-    // presented. This means that we can't rely on TimeStats to flush layer records over to the
-    // aggregated stats.
-    if (!canAddNewAggregatedStats(uid, layerName)) {
-        return;
-    }
+    // called from FrameTimeline, whose jank classification includes transaction jank
+    // that occurs without a buffer. But, in general those layer names are not suitable as
+    // aggregation keys: e.g., it's normal and expected for Window Manager to include the hash code
+    // for an animation leash. So while we can show that jank in dumpsys, aggregating based on the
+    // layer blows up the stats size, so as a workaround drop those stats. This assumes that
+    // TimeStats will flush the first present fence for a layer *before* FrameTimeline does so that
+    // the first jank record is not dropped.
 
-    // Defensively initialize the stats in case FrameTimeline flushes its signaled present fences
-    // before TimeStats does.
+    bool useDefaultLayerKey = false;
+    static const std::string kDefaultLayerName = "none";
     if (!mTimeStats.stats.count({uid, layerName})) {
-        mTimeStats.stats[{uid, layerName}].uid = uid;
-        mTimeStats.stats[{uid, layerName}].layerName = layerName;
+        mTimeStats.stats[{uid, kDefaultLayerName}].uid = uid;
+        mTimeStats.stats[{uid, kDefaultLayerName}].layerName = kDefaultLayerName;
+        useDefaultLayerKey = true;
     }
 
-    TimeStatsHelper::TimeStatsLayer& timeStatsLayer = mTimeStats.stats[{uid, layerName}];
+    TimeStatsHelper::TimeStatsLayer& timeStatsLayer =
+            mTimeStats.stats[{uid, useDefaultLayerKey ? kDefaultLayerName : layerName}];
     updateJankPayload<TimeStatsHelper::TimeStatsLayer>(timeStatsLayer, reasons);
 }
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 6f09a8c..d7fdab5 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -183,6 +183,8 @@
                 .library_namespace = library_namespace,
             };
             so = android_dlopen_ext(lib_name.c_str(), LIB_DL_FLAGS, &dlextinfo);
+            ALOGE("Could not load %s from updatable gfx driver namespace: %s.",
+                  lib_name.c_str(), dlerror());
         } else {
             // load built-in driver
             so = android_load_sphal_library(lib_name.c_str(), LIB_DL_FLAGS);