Merge "OomKillRecord: Track new oom/mark_victim tracepoint fields" into main
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index 58434f1..22b6489 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -2,7 +2,6 @@
 ctate@google.com
 dplotnikov@google.com
 jji@google.com
-kwekua@google.com
 omakoto@google.com
 suprabh@google.com
 varunshah@google.com
diff --git a/apex/jobscheduler/framework/java/android/app/job/OWNERS b/apex/jobscheduler/framework/java/android/app/job/OWNERS
index b4a45f5..0b1e559 100644
--- a/apex/jobscheduler/framework/java/android/app/job/OWNERS
+++ b/apex/jobscheduler/framework/java/android/app/job/OWNERS
@@ -4,4 +4,3 @@
 omakoto@google.com
 ctate@android.com
 ctate@google.com
-kwekua@google.com
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/OWNERS b/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
index 96ec75f..b5c568b 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
+++ b/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
@@ -1,5 +1,4 @@
 dplotnikov@google.com
-kwekua@google.com
 mwachens@google.com
 suprabh@google.com
-yamasani@google.com
\ No newline at end of file
+yamasani@google.com
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index 34a1fa2..e8acff7 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -28,4 +28,8 @@
         "liblog",
         "libbase",
     ],
+    visibility: [
+        "//frameworks/base/apex:__subpackages__",
+        "//visibility:any_system_partition",
+    ],
 }
diff --git a/api/coverage/tools/Android.bp b/api/coverage/tools/Android.bp
index 3e16912..caaca99 100644
--- a/api/coverage/tools/Android.bp
+++ b/api/coverage/tools/Android.bp
@@ -30,3 +30,24 @@
         type: "full",
     },
 }
+
+java_test_host {
+    name: "extract-flagged-apis-test",
+    srcs: ["ExtractFlaggedApisTest.kt"],
+    libs: [
+        "extract_flagged_apis_proto",
+        "junit",
+        "libprotobuf-java-full",
+    ],
+    static_libs: [
+        "truth",
+        "truth-liteproto-extension",
+        "truth-proto-extension",
+    ],
+    data: [
+        ":extract-flagged-apis",
+    ],
+    test_options: {
+        unit_test: true,
+    },
+}
diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt
index d5adfd0..5178f09 100644
--- a/api/coverage/tools/ExtractFlaggedApis.kt
+++ b/api/coverage/tools/ExtractFlaggedApis.kt
@@ -28,12 +28,10 @@
     val builder = FlagApiMap.newBuilder()
     for (pkg in cb.getPackages().packages) {
         val packageName = pkg.qualifiedName()
-        pkg.allClasses()
-            .filter { it.methods().size > 0 }
-            .forEach {
-                extractFlaggedApisFromClass(it, it.methods(), packageName, builder)
-                extractFlaggedApisFromClass(it, it.constructors(), packageName, builder)
-            }
+        pkg.allClasses().forEach {
+            extractFlaggedApisFromClass(it, it.methods(), packageName, builder)
+            extractFlaggedApisFromClass(it, it.constructors(), packageName, builder)
+        }
     }
     val flagApiMap = builder.build()
     FileWriter(args[1]).use { it.write(flagApiMap.toString()) }
@@ -45,6 +43,7 @@
     packageName: String,
     builder: FlagApiMap.Builder
 ) {
+    if (methods.isEmpty()) return
     val classFlag =
         classItem.modifiers
             .findAnnotation("android.annotation.FlaggedApi")
diff --git a/api/coverage/tools/ExtractFlaggedApisTest.kt b/api/coverage/tools/ExtractFlaggedApisTest.kt
new file mode 100644
index 0000000..ee5aaf1
--- /dev/null
+++ b/api/coverage/tools/ExtractFlaggedApisTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.platform.coverage
+
+import com.google.common.truth.extensions.proto.ProtoTruth.assertThat
+import com.google.protobuf.TextFormat
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.StandardOpenOption
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ExtractFlaggedApisTest {
+
+    companion object {
+        const val COMMAND = "java -jar extract-flagged-apis.jar %s %s"
+    }
+
+    private var apiTextFile: Path = Files.createTempFile("current", ".txt")
+    private var flagToApiMap: Path = Files.createTempFile("flag_api_map", ".textproto")
+
+    @Before
+    fun setup() {
+        apiTextFile = Files.createTempFile("current", ".txt")
+        flagToApiMap = Files.createTempFile("flag_api_map", ".textproto")
+    }
+
+    @After
+    fun cleanup() {
+        Files.deleteIfExists(apiTextFile)
+        Files.deleteIfExists(flagToApiMap)
+    }
+
+    @Test
+    fun extractFlaggedApis_onlyMethodFlag_useMethodFlag() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.net.ipsec.ike {
+              public final class IkeSession implements java.lang.AutoCloseable {
+                method @FlaggedApi("com.android.ipsec.flags.dumpsys_api") public void dump(@NonNull java.io.PrintWriter);
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.net.ipsec.ike")
+                .setClassName("IkeSession")
+                .setMethodName("dump")
+        api.addParameters("java.io.PrintWriter")
+        addFlaggedApi(expected, api, "com.android.ipsec.flags.dumpsys_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_onlyClassFlag_useClassFlag() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.net.ipsec.ike {
+              @FlaggedApi("com.android.ipsec.flags.dumpsys_api") public final class IkeSession implements java.lang.AutoCloseable {
+                method public void dump(@NonNull java.io.PrintWriter);
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.net.ipsec.ike")
+                .setClassName("IkeSession")
+                .setMethodName("dump")
+        api.addParameters("java.io.PrintWriter")
+        addFlaggedApi(expected, api, "com.android.ipsec.flags.dumpsys_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    @Test
+    fun extractFlaggedApis_flaggedConstructorsAreFlaggedApis() {
+        val apiText =
+            """
+            // Signature format: 2.0
+            package android.app.pinner {
+              @FlaggedApi("android.app.pinner_service_client_api") public class PinnerServiceClient {
+                ctor @FlaggedApi("android.app.pinner_service_client_api") public PinnerServiceClient();
+              }
+            }
+        """
+                .trimIndent()
+        Files.write(apiTextFile, apiText.toByteArray(Charsets.UTF_8), StandardOpenOption.APPEND)
+
+        val process = Runtime.getRuntime().exec(createCommand())
+        process.waitFor()
+
+        val content = Files.readAllBytes(flagToApiMap).toString(Charsets.UTF_8)
+        val result = TextFormat.parse(content, FlagApiMap::class.java)
+
+        val expected = FlagApiMap.newBuilder()
+        val api =
+            JavaMethod.newBuilder()
+                .setPackageName("android.app.pinner")
+                .setClassName("PinnerServiceClient")
+                .setMethodName("PinnerServiceClient")
+        addFlaggedApi(expected, api, "android.app.pinner_service_client_api")
+        assertThat(result).isEqualTo(expected.build())
+    }
+
+    private fun addFlaggedApi(builder: FlagApiMap.Builder, api: JavaMethod.Builder, flag: String) {
+        if (builder.containsFlagToApi(flag)) {
+            val updatedApis =
+                builder.getFlagToApiOrThrow(flag).toBuilder().addJavaMethods(api).build()
+            builder.putFlagToApi(flag, updatedApis)
+        } else {
+            val apis = FlaggedApis.newBuilder().addJavaMethods(api).build()
+            builder.putFlagToApi(flag, apis)
+        }
+    }
+
+    private fun createCommand(): Array<String> {
+        val command =
+            String.format(COMMAND, apiTextFile.toAbsolutePath(), flagToApiMap.toAbsolutePath())
+        return command.split(" ").toTypedArray()
+    }
+}
diff --git a/cmds/incident_helper/OWNERS b/cmds/incident_helper/OWNERS
index cede4ea..29f44ab 100644
--- a/cmds/incident_helper/OWNERS
+++ b/cmds/incident_helper/OWNERS
@@ -1,3 +1,2 @@
 joeo@google.com
-kwekua@google.com
 yanmin@google.com
diff --git a/cmds/locksettings/TEST_MAPPING b/cmds/locksettings/TEST_MAPPING
index 7a449ef..af54a2d 100644
--- a/cmds/locksettings/TEST_MAPPING
+++ b/cmds/locksettings/TEST_MAPPING
@@ -11,5 +11,10 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            "name": "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes"
+        }
     ]
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0e66010a..1ac887b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1050,6 +1050,8 @@
         public boolean managed;
         public boolean mallocInfo;
         public boolean runGc;
+        // compression format to dump bitmaps, null if no bitmaps to be dumped
+        public String dumpBitmaps;
         String path;
         ParcelFileDescriptor fd;
         RemoteCallback finishCallback;
@@ -1442,11 +1444,12 @@
         }
 
         @Override
-        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
-                ParcelFileDescriptor fd, RemoteCallback finishCallback) {
+        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String dumpBitmaps,
+                String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
             DumpHeapData dhd = new DumpHeapData();
             dhd.managed = managed;
             dhd.mallocInfo = mallocInfo;
+            dhd.dumpBitmaps = dumpBitmaps;
             dhd.runGc = runGc;
             dhd.path = path;
             try {
@@ -6731,6 +6734,9 @@
             System.runFinalization();
             System.gc();
         }
+        if (dhd.dumpBitmaps != null) {
+            Bitmap.dumpAll(dhd.dumpBitmaps);
+        }
         try (ParcelFileDescriptor fd = dhd.fd) {
             if (dhd.managed) {
                 Debug.dumpHprofData(dhd.path, fd.getFileDescriptor());
@@ -6758,6 +6764,9 @@
         if (dhd.finishCallback != null) {
             dhd.finishCallback.sendResult(null);
         }
+        if (dhd.dumpBitmaps != null) {
+            Bitmap.dumpAll(null); // clear dump
+        }
     }
 
     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 260e985..b84475e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -392,7 +392,7 @@
     oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
     // Cause the specified process to dump the specified heap.
     boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
-            boolean runGc, in String path, in ParcelFileDescriptor fd,
+            boolean runGc, in String dumpBitmaps, in String path, in ParcelFileDescriptor fd,
             in RemoteCallback finishCallback);
     @UnsupportedAppUsage
     boolean isUserRunning(int userid, int flags);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 5541e7a..40f3c1a 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -116,7 +116,8 @@
     void scheduleSuicide();
     void dispatchPackageBroadcast(int cmd, in String[] packages);
     void scheduleCrash(in String msg, int typeId, in Bundle extras);
-    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
+    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc,
+            in String dumpBitmaps, in String path,
             in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
     void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
             in String[] args);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cbbe785..6dd0a90 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1247,7 +1247,7 @@
      * surface has no buffer or crop, the surface is boundless and only constrained
      * by the size of its parent bounds.
      *
-     * @param session  The surface session, must not be null.
+     * @param session  The surface session.
      * @param name     The surface name, must not be null.
      * @param w        The surface initial width.
      * @param h        The surface initial height.
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index c14d8d8..8063be6 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -45,8 +45,8 @@
     static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
     static Runnable[] sTmpWatchers = new Runnable[1];
     static long sLastGcTime;
-    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
-            new BinderProxyLimitListenerDelegate();
+    static final BinderProxyCountEventListenerDelegate sBinderProxyCountEventListenerDelegate =
+            new BinderProxyCountEventListenerDelegate();
 
     static final class GcWatcher {
         @Override
@@ -226,15 +226,24 @@
      * @param low   The threshold a binder count must drop below before the callback
      *              can be called again. (This is to avoid many repeated calls to the
      *              callback in a brief period of time)
+     * @param warning The threshold between {@code high} and {@code low} where if the binder count
+     *                exceeds that, the warning callback would be triggered.
      */
-    public static final native void nSetBinderProxyCountWatermarks(int high, int low);
+    public static final native void nSetBinderProxyCountWatermarks(int high, int low, int warning);
 
     /**
      * Interface for callback invocation when the Binder Proxy limit is reached. onLimitReached will
      * be called with the uid of the app causing too many Binder Proxies
      */
-    public interface BinderProxyLimitListener {
+    public interface BinderProxyCountEventListener {
         public void onLimitReached(int uid);
+
+        /**
+         * Call when the number of binder proxies from the uid of the app reaches
+         * the warning threshold.
+         */
+        default void onWarningThresholdReached(int uid) {
+        }
     }
 
     /**
@@ -243,7 +252,17 @@
      * @param uid The uid of the bad behaving app sending too many binders
      */
     public static void binderProxyLimitCallbackFromNative(int uid) {
-       sBinderProxyLimitListenerDelegate.notifyClient(uid);
+        sBinderProxyCountEventListenerDelegate.notifyLimitReached(uid);
+    }
+
+    /**
+     * Callback used by native code to trigger a callback in java code. The callback will be
+     * triggered when too many binder proxies from a uid hits the warning limit.
+     * @param uid The uid of the bad behaving app sending too many binders
+     */
+    @SuppressWarnings("unused")
+    public static void binderProxyWarningCallbackFromNative(int uid) {
+        sBinderProxyCountEventListenerDelegate.notifyWarningReached(uid);
     }
 
     /**
@@ -252,41 +271,45 @@
      * @param handler must not be null, callback will be posted through the handler;
      *
      */
-    public static void setBinderProxyCountCallback(BinderProxyLimitListener listener,
+    public static void setBinderProxyCountCallback(BinderProxyCountEventListener listener,
             @NonNull Handler handler) {
         Preconditions.checkNotNull(handler,
                 "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
-                        + "BinderProxyLimitListener");
-        sBinderProxyLimitListenerDelegate.setListener(listener, handler);
+                        + "BinderProxyCountEventListener");
+        sBinderProxyCountEventListenerDelegate.setListener(listener, handler);
     }
 
     /**
      * Clear the Binder Proxy callback
      */
     public static void clearBinderProxyCountCallback() {
-        sBinderProxyLimitListenerDelegate.setListener(null, null);
+        sBinderProxyCountEventListenerDelegate.setListener(null, null);
     }
 
-    static private class BinderProxyLimitListenerDelegate {
-        private BinderProxyLimitListener mBinderProxyLimitListener;
+    private static class BinderProxyCountEventListenerDelegate {
+        private BinderProxyCountEventListener mBinderProxyCountEventListener;
         private Handler mHandler;
 
-        void setListener(BinderProxyLimitListener listener, Handler handler) {
+        void setListener(BinderProxyCountEventListener listener, Handler handler) {
             synchronized (this) {
-                mBinderProxyLimitListener = listener;
+                mBinderProxyCountEventListener = listener;
                 mHandler = handler;
             }
         }
 
-        void notifyClient(final int uid) {
+        void notifyLimitReached(final int uid) {
             synchronized (this) {
-                if (mBinderProxyLimitListener != null) {
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            mBinderProxyLimitListener.onLimitReached(uid);
-                        }
-                    });
+                if (mBinderProxyCountEventListener != null) {
+                    mHandler.post(() -> mBinderProxyCountEventListener.onLimitReached(uid));
+                }
+            }
+        }
+
+        void notifyWarningReached(final int uid) {
+            synchronized (this) {
+                if (mBinderProxyCountEventListener != null) {
+                    mHandler.post(() ->
+                            mBinderProxyCountEventListener.onWarningThresholdReached(uid));
                 }
             }
         }
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index d687ef3..1a27367 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -109,3 +109,6 @@
 
 # PerformanceHintManager
 per-file android_os_PerformanceHintManager.cpp = file:/ADPF_OWNERS
+
+# IF Tools
+per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/OWNERS
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index d2d5186..2068bd7 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -88,6 +88,7 @@
     jclass mClass;
     jmethodID mForceGc;
     jmethodID mProxyLimitCallback;
+    jmethodID mProxyWarningCallback;
 
 } gBinderInternalOffsets;
 
@@ -1240,7 +1241,7 @@
     gCollectedAtRefs = gNumLocalRefsCreated + gNumDeathRefsCreated;
 }
 
-static void android_os_BinderInternal_proxyLimitcallback(int uid)
+static void android_os_BinderInternal_proxyLimitCallback(int uid)
 {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
@@ -1254,6 +1255,20 @@
     }
 }
 
+static void android_os_BinderInternal_proxyWarningCallback(int uid)
+{
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
+                              gBinderInternalOffsets.mProxyWarningCallback,
+                              uid);
+
+    if (env->ExceptionCheck()) {
+        ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
+        binder_report_exception(env, excep.get(),
+                                "*** Uncaught exception in binderProxyWarningCallbackFromNative");
+    }
+}
+
 static void android_os_BinderInternal_setBinderProxyCountEnabled(JNIEnv* env, jobject clazz,
                                                                  jboolean enable)
 {
@@ -1278,9 +1293,10 @@
 }
 
 static void android_os_BinderInternal_setBinderProxyCountWatermarks(JNIEnv* env, jobject clazz,
-                                                                    jint high, jint low)
+                                                                    jint high, jint low,
+                                                                    jint warning)
 {
-    BpBinder::setBinderProxyCountWatermarks(high, low);
+    BpBinder::setBinderProxyCountWatermarks(high, low, warning);
 }
 
 // ----------------------------------------------------------------------------
@@ -1295,7 +1311,7 @@
     { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
     { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
     { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
-    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
+    { "nSetBinderProxyCountWatermarks", "(III)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
 };
 
 const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
@@ -1307,6 +1323,8 @@
     gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
     gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
     gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");
+    gBinderInternalOffsets.mProxyWarningCallback =
+        GetStaticMethodIDOrDie(env, clazz, "binderProxyWarningCallbackFromNative", "(I)V");
 
     jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
     gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass);
@@ -1315,7 +1333,8 @@
     gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put",
                                                    "(II)V");
 
-    BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);
+    BpBinder::setBinderProxyCountEventCallback(android_os_BinderInternal_proxyLimitCallback,
+                                               android_os_BinderInternal_proxyWarningCallback);
 
     return RegisterMethodsOrDie(
         env, kBinderInternalPathName,
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 00d90cc..1a95520 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -11,7 +11,6 @@
 # Frameworks
 ogunwale@google.com
 jjaggi@google.com
-kwekua@google.com
 roosa@google.com
 per-file package_item_info.proto = file:/PACKAGE_MANAGER_OWNERS
 per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 6924248..3c2bc0d 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -4,7 +4,6 @@
 cinek@google.com
 dsandler@android.com
 dsandler@google.com
-dupin@google.com
 hackbod@android.com
 hackbod@google.com
 ilyamaty@google.com
@@ -46,7 +45,7 @@
 # Wear
 per-file res/*-watch/* = file:/WEAR_OWNERS
 
-# Peformance
+# Performance
 per-file res/values/config.xml = file:/PERFORMANCE_OWNERS
 per-file res/values/symbols.xml = file:/PERFORMANCE_OWNERS
 
@@ -60,3 +59,11 @@
 
 # TV Input Framework
 per-file res/values/config_tv_external_input_logging.xml = file:/services/core/java/com/android/server/tv/OWNERS
+
+# SysUi Color Team
+per-file res/values/colors.xml = arteiro@google.com
+per-file res/values/attrs.xml = arteiro@google.com
+per-file res/values/styles.xml = arteiro@google.com
+per-file res/values/symbols.xml = arteiro@google.com
+per-file res/values/themes_device_defaults.xml = arteiro@google.com
+per-file res/values/styles_material.xml = arteiro@google.com
\ No newline at end of file
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index c8625b9..9bb72d9 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -28,7 +28,7 @@
          standard SMS rate. The user is warned when the destination phone number matches the
          "pattern" or "premium" regexes, and does not match the "free" or "standard" regexes. -->
 
-    <!-- Harmonised European Short Codes are 6 digit numbers starting with 116 (free helplines).
+    <!-- Harmonised European Short Codes are 7 digit numbers starting with 116 (free helplines).
          Premium patterns include short codes from: http://aonebill.com/coverage&tariffs
          and http://mobilcent.com/info-worldwide.asp and extracted from:
          http://smscoin.net/software/engine/WordPress/Paid+SMS-registration/ -->
@@ -39,8 +39,8 @@
     <!-- Albania: 5 digits, known short codes listed -->
     <shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
 
-    <!-- Argentina: 5 digits, known short codes listed -->
-    <shortcode country="ar" pattern="\\d{5}" free="11711|28291|44077|78887" />
+    <!-- Argentina: 6 digits, known short codes listed -->
+    <shortcode country="ar" pattern="\\d{1,6}" free="11711|28291|44077|78887|191289|39010" />
 
     <!-- Armenia: 3-5 digits, emergency numbers 10[123] -->
     <shortcode country="am" pattern="\\d{3,5}" premium="11[2456]1|3024" free="10[123]|71522|71512|71502" />
@@ -67,7 +67,7 @@
     <shortcode country="bh" pattern="\\d{1,5}" free="81181|85999" />
 
     <!-- Brazil: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000" />
+    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963|4141|8000|2652" />
 
     <!-- Belarus: 4 digits -->
     <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
@@ -163,7 +163,7 @@
     <shortcode country="in" pattern="\\d{1,5}" free="59336|53969" />
 
     <!-- Indonesia: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363|93457" />
+    <shortcode country="id" pattern="\\d{1,5}" free="99477|6006|46645|363|93457|99265" />
 
     <!-- Ireland: 5 digits, 5xxxx (50xxx=free, 5[12]xxx=standard), plus EU:
          http://www.comreg.ie/_fileupload/publications/ComReg1117.pdf -->
@@ -172,6 +172,9 @@
     <!-- Israel: 1-5 digits, known premium codes listed -->
     <shortcode country="il" pattern="\\d{1,5}" premium="4422|4545" free="37477|6681" />
 
+    <!-- Iran: 4-6 digits, known premium codes listed -->
+    <shortcode country="ir" pattern="\\d{4,6}" free="700791|700792" />
+
     <!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU:
          https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf -->
     <shortcode country="it" pattern="\\d{5}" premium="44[0-4]\\d{2}|47[0-4]\\d{2}|48[0-4]\\d{2}|44[5-9]\\d{4}|47[5-9]\\d{4}|48[5-9]\\d{4}|455\\d{2}|499\\d{2}" free="116\\d{3}|4112503|40\\d{0,12}" standard="430\\d{2}|431\\d{2}|434\\d{4}|435\\d{4}|439\\d{7}" />
@@ -219,11 +222,11 @@
     <!-- Mozambique: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="mz" pattern="\\d{1,5}" free="1714" />
 
-    <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
-    <shortcode country="mx" pattern="\\d{4,6}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346" />
+    <!-- Mexico: 4-7 digits (not confirmed), known premium codes listed -->
+    <shortcode country="mx" pattern="\\d{4,7}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963|91101|45453|550346|3030303" />
 
     <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
-    <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" />
+    <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668|66966" />
 
     <!-- Namibia: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="na" pattern="\\d{1,5}" free="40005" />
@@ -255,6 +258,9 @@
     <!-- Palestine: 5 digits, known premium codes listed -->
     <shortcode country="ps" pattern="\\d{1,5}" free="37477|6681" />
 
+    <!-- Paraguay: 6 digits, known premium codes listed -->
+    <shortcode country="py" pattern="\\d{6}" free="191289" />
+
     <!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}|8012|80921" />
 
@@ -275,7 +281,7 @@
     <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)|8424" free="6954|8501" standard="2037|2044"/>
 
     <!-- Rwanda: 4 digits -->
-    <shortcode country="rw" pattern="\\d{4}" free="5060" />
+    <shortcode country="rw" pattern="\\d{4}" free="5060|5061" />
 
     <!-- Saudi Arabia -->
     <shortcode country="sa" pattern="\\d{1,5}" free="8145" />
@@ -309,7 +315,10 @@
     <shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
 
     <!-- Tanzania: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234" />
+    <shortcode country="tz" pattern="\\d{1,5}" free="15046|15234|15324" />
+
+    <!-- Tunisia: 5 digits, known premium codes listed -->
+    <shortcode country="tn" pattern="\\d{5}" free="85799" />
 
     <!-- Turkey -->
     <shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493|3193" />
@@ -324,8 +333,11 @@
          visual voicemail code for T-Mobile: 122 -->
     <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567|244444" free="122|87902|21696|24614|28003|30356|33669|40196|41064|41270|43753|44034|46645|52413|56139|57969|61785|66975|75136|76227|81398|83952|85140|86566|86799|95737|96684|99245|611611|96831" />
 
-    <!--Uruguay : 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="uy" pattern="\\d{1,5}" free="55002" />
+    <!--Uruguay : 1-6 digits (standard system default, not country specific) -->
+    <shortcode country="uy" pattern="\\d{1,6}" free="55002|191289" />
+
+    <!-- Venezuela: 1-6 digits (standard system default, not country specific) -->
+    <shortcode country="ve" pattern="\\d{1,6}" free="538352" />
 
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055|8079" />
@@ -336,6 +348,9 @@
     <!-- South Africa -->
     <shortcode country="za" pattern="\\d{1,5}" free="44136|30791|36056|33009" />
 
+    <!-- Yemen -->
+    <shortcode country="ye" pattern="\\d{1,4}" free="5081" />
+
     <!-- Zimbabwe -->
     <shortcode country="zw" pattern="\\d{1,5}" free="33679" />
 
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 1a3ec27..871feb6 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -116,6 +116,8 @@
         ":BinderDeathRecipientHelperApp1",
         ":BinderDeathRecipientHelperApp2",
         ":com.android.cts.helpers.aosp",
+        ":BinderProxyCountingTestApp",
+        ":BinderProxyCountingTestService",
     ],
 }
 
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 05b309b..bf2a5b8 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -22,6 +22,8 @@
         <option name="test-file-name" value="FrameworksCoreTests.apk" />
         <option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
         <option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
+        <option name="test-file-name" value="BinderProxyCountingTestApp.apk" />
+        <option name="test-file-name" value="BinderProxyCountingTestService.apk" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
diff --git a/core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml b/core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml
index a971730..c8407b8 100644
--- a/core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml
+++ b/core/tests/coretests/BinderProxyCountingTestApp/AndroidManifest.xml
@@ -16,6 +16,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.coretests.binderproxycountingtestapp">
 
+    <queries>
+        <package android:name="com.android.frameworks.coretests.binderproxycountingtestservice" />
+    </queries>
     <application>
         <service android:name=".BpcTestAppCmdService"
                  android:exported="true"/>
diff --git a/core/tests/coretests/BinderProxyCountingTestApp/src/com/android/frameworks/coretests/binderproxycountingtestapp/BpcTestAppCmdService.java b/core/tests/coretests/BinderProxyCountingTestApp/src/com/android/frameworks/coretests/binderproxycountingtestapp/BpcTestAppCmdService.java
index 5aae1203..a7e97d3 100644
--- a/core/tests/coretests/BinderProxyCountingTestApp/src/com/android/frameworks/coretests/binderproxycountingtestapp/BpcTestAppCmdService.java
+++ b/core/tests/coretests/BinderProxyCountingTestApp/src/com/android/frameworks/coretests/binderproxycountingtestapp/BpcTestAppCmdService.java
@@ -17,14 +17,15 @@
 package com.android.frameworks.coretests.binderproxycountingtestapp;
 
 import android.app.Service;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.database.ContentObserver;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.provider.Settings;
 import android.util.Log;
 
 import com.android.frameworks.coretests.aidl.IBinderProxyCountingService;
@@ -49,24 +50,20 @@
 
     private IBpcTestAppCmdService.Stub mBinder = new IBpcTestAppCmdService.Stub() {
 
-        private ArrayList<BroadcastReceiver> mBrList = new ArrayList();
+        private ArrayList<ContentObserver> mCoList = new ArrayList();
         private ArrayList<ITestRemoteCallback> mTrcList = new ArrayList();
+        private Handler mHandler = new Handler();
 
         @Override
         public void createSystemBinders(int count) {
             int i = 0;
             while (i++ < count) {
-                BroadcastReceiver br = new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-
-                    }
-                };
-                IntentFilter filt = new IntentFilter(Intent.ACTION_POWER_DISCONNECTED);
-                synchronized (mBrList) {
-                    mBrList.add(br);
+                final ContentObserver co = new ContentObserver(mHandler) {};
+                synchronized (mCoList) {
+                    mCoList.add(co);
                 }
-                registerReceiver(br, filt);
+                getContentResolver().registerContentObserver(
+                        Settings.System.CONTENT_URI, false, co);
             }
         }
 
@@ -74,11 +71,11 @@
         public void releaseSystemBinders(int count) {
             int i = 0;
             while (i++ < count) {
-                BroadcastReceiver br;
-                synchronized (mBrList) {
-                    br = mBrList.remove(0);
+                ContentObserver co;
+                synchronized (mCoList) {
+                    co = mCoList.remove(0);
                 }
-                unregisterReceiver(br);
+                getContentResolver().unregisterContentObserver(co);
             }
         }
 
@@ -117,9 +114,9 @@
 
         @Override
         public void releaseAllBinders() {
-            synchronized (mBrList) {
-                while (mBrList.size() > 0) {
-                    unregisterReceiver(mBrList.remove(0));
+            synchronized (mCoList) {
+                while (mCoList.size() > 0) {
+                    getContentResolver().unregisterContentObserver(mCoList.remove(0));
                 }
             }
             synchronized (mTrcList) {
@@ -179,4 +176,4 @@
     public IBinder onBind(Intent intent) {
         return mBinder;
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BpcTestServiceCmdService.java b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BpcTestServiceCmdService.java
index 6bed2a2..0f1accc 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BpcTestServiceCmdService.java
+++ b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BpcTestServiceCmdService.java
@@ -55,8 +55,8 @@
         }
 
         @Override
-        public void setBinderProxyWatermarks(int high, int low) {
-            BinderInternal.nSetBinderProxyCountWatermarks(high, low);
+        public void setBinderProxyWatermarks(int high, int low, int warning) {
+            BinderInternal.nSetBinderProxyCountWatermarks(high, low, warning);
         }
 
         @Override
@@ -68,12 +68,23 @@
         public void setBinderProxyCountCallback(IBpcCallbackObserver observer) {
             if (observer != null) {
                 BinderInternal.setBinderProxyCountCallback(
-                        new BinderInternal.BinderProxyLimitListener() {
+                        new BinderInternal.BinderProxyCountEventListener() {
                             @Override
                             public void onLimitReached(int uid) {
                                 try {
                                     synchronized (observer) {
-                                        observer.onCallback(uid);
+                                        observer.onLimitReached(uid);
+                                    }
+                                } catch (Exception e) {
+                                    Log.e(TAG, e.toString());
+                                }
+                            }
+
+                            @Override
+                            public void onWarningThresholdReached(int uid) {
+                                try {
+                                    synchronized (observer) {
+                                        observer.onWarningThresholdReached(uid);
                                     }
                                 } catch (Exception e) {
                                     Log.e(TAG, e.toString());
@@ -98,4 +109,4 @@
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcCallbackObserver.aidl b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcCallbackObserver.aidl
index c4ebd56..ada7d92 100644
--- a/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcCallbackObserver.aidl
+++ b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcCallbackObserver.aidl
@@ -17,5 +17,6 @@
 package com.android.frameworks.coretests.aidl;
 
 interface IBpcCallbackObserver {
-    void onCallback(int uid);
-}
\ No newline at end of file
+    void onLimitReached(int uid);
+    void onWarningThresholdReached(int uid);
+}
diff --git a/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcTestServiceCmdService.aidl b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcTestServiceCmdService.aidl
index abdab41..cdcda9d 100644
--- a/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcTestServiceCmdService.aidl
+++ b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBpcTestServiceCmdService.aidl
@@ -20,7 +20,7 @@
 interface IBpcTestServiceCmdService {
    void forceGc();
    int getBinderProxyCount(int uid);
-   void setBinderProxyWatermarks(int high, int low);
+   void setBinderProxyWatermarks(int high, int low, int warning);
    void enableBinderProxyLimit(boolean enable);
    void setBinderProxyCountCallback(IBpcCallbackObserver observer);
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
index bcd9521..84d2995 100644
--- a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
@@ -88,9 +88,10 @@
 
     private static final int BIND_SERVICE_TIMEOUT_SEC = 5;
     private static final int TOO_MANY_BINDERS_TIMEOUT_SEC = 2;
+    private static final int TOO_MANY_BINDERS_WITH_KILL_TIMEOUT_SEC = 30;
 
-    // Keep in sync with sBinderProxyCountLimit in BpBinder.cpp
-    private static final int BINDER_PROXY_LIMIT = 2500;
+    // Keep in sync with BINDER_PROXY_HIGH_WATERMARK in ActivityManagerService.java
+    private static final int BINDER_PROXY_LIMIT = 6000;
 
     private static Context sContext;
     private static UiDevice sUiDevice;
@@ -175,18 +176,26 @@
         }
     }
 
-    private CountDownLatch createBinderLimitLatch() throws RemoteException {
-        final CountDownLatch latch = new CountDownLatch(1);
+    private CountDownLatch[] createBinderLimitLatch() throws RemoteException {
+        final CountDownLatch[] latches = new CountDownLatch[] {
+            new CountDownLatch(1), new CountDownLatch(1)
+        };
         sBpcTestServiceCmdService.setBinderProxyCountCallback(
                 new IBpcCallbackObserver.Stub() {
                     @Override
-                    public void onCallback(int uid) {
+                    public void onLimitReached(int uid) {
                         if (uid == sTestPkgUid) {
-                            latch.countDown();
+                            latches[0].countDown();
+                        }
+                    }
+                    @Override
+                    public void onWarningThresholdReached(int uid) {
+                        if (uid == sTestPkgUid) {
+                            latches[1].countDown();
                         }
                     }
                 });
-        return latch;
+        return latches;
     }
 
     /**
@@ -227,6 +236,7 @@
     @Test
     public void testBinderProxyLimitBoundary() throws Exception {
         final int binderProxyLimit = 2000;
+        final int binderProxyWarning = 1900;
         final int rearmThreshold = 1800;
         try {
             sTestAppConnection = bindService(sTestAppConsumer, sTestAppIntent);
@@ -238,19 +248,33 @@
             // Get the baseline of binders naturally held by the test Package
             int baseBinderCount = sBpcTestServiceCmdService.getBinderProxyCount(sTestPkgUid);
 
-            final CountDownLatch binderLimitLatch = createBinderLimitLatch();
-            sBpcTestServiceCmdService.setBinderProxyWatermarks(binderProxyLimit, rearmThreshold);
+            final CountDownLatch[] binderLatches = createBinderLimitLatch();
+            sBpcTestServiceCmdService.setBinderProxyWatermarks(binderProxyLimit, rearmThreshold,
+                    binderProxyWarning);
+
+            // Create Binder Proxies up to the warning;
+            sBpcTestAppCmdService.createTestBinders(binderProxyWarning - baseBinderCount);
+            if (binderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                fail("Received BinderProxyLimitCallback for uid " + sTestPkgUid
+                        + " when proxy warning should not have been triggered");
+            }
+
+            // Create one more Binder to trigger the warning
+            sBpcTestAppCmdService.createTestBinders(1);
+            if (!binderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                fail("Timed out waiting for uid " + sTestPkgUid + " to trigger the warning");
+            }
 
             // Create Binder Proxies up to the limit
-            sBpcTestAppCmdService.createTestBinders(binderProxyLimit - baseBinderCount);
-            if (binderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            sBpcTestAppCmdService.createTestBinders(binderProxyLimit - binderProxyWarning - 1);
+            if (binderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 fail("Received BinderProxyLimitCallback for uid " + sTestPkgUid
                         + " when proxy limit should not have been reached");
             }
 
             // Create one more Binder to cross the limit
             sBpcTestAppCmdService.createTestBinders(1);
-            if (!binderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            if (!binderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 fail("Timed out waiting for uid " + sTestPkgUid + " to hit limit");
             }
 
@@ -274,12 +298,20 @@
             sBpcTestServiceCmdService.forceGc();
             int baseBinderCount = sBpcTestServiceCmdService.getBinderProxyCount(sTestPkgUid);
             for (int testLimit : testLimits) {
-                final CountDownLatch binderLimitLatch = createBinderLimitLatch();
+                final CountDownLatch[] binderLatches = createBinderLimitLatch();
                 // Change the BinderProxyLimit
-                sBpcTestServiceCmdService.setBinderProxyWatermarks(testLimit, baseBinderCount + 10);
+                sBpcTestServiceCmdService.setBinderProxyWatermarks(testLimit, baseBinderCount + 10,
+                        testLimit - 10);
+
+                // Trigger the new Binder Proxy warning
+                sBpcTestAppCmdService.createTestBinders(testLimit - 9 - baseBinderCount);
+                if (!binderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                    fail("Timed out waiting for uid " + sTestPkgUid + " to trigger the warning");
+                }
+
                 // Exceed the new Binder Proxy Limit
-                sBpcTestAppCmdService.createTestBinders(testLimit + 1);
-                if (!binderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                sBpcTestAppCmdService.createTestBinders(10);
+                if (!binderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                     fail("Timed out waiting for uid " + sTestPkgUid + " to hit limit");
                 }
 
@@ -297,6 +329,7 @@
     public void testRearmCallbackThreshold() throws Exception {
         final int binderProxyLimit = 2000;
         final int exceedBinderProxyLimit = binderProxyLimit + 10;
+        final int binderProxyWarning = 1900;
         final int rearmThreshold = 1800;
         try {
             sTestAppConnection = bindService(sTestAppConsumer, sTestAppIntent);
@@ -305,11 +338,19 @@
             sBpcTestServiceCmdService.enableBinderProxyLimit(true);
 
             sBpcTestServiceCmdService.forceGc();
-            final CountDownLatch firstBinderLimitLatch = createBinderLimitLatch();
-            sBpcTestServiceCmdService.setBinderProxyWatermarks(binderProxyLimit, rearmThreshold);
+            int baseBinderCount = sBpcTestServiceCmdService.getBinderProxyCount(sTestPkgUid);
+            final CountDownLatch[] firstBinderLatches = createBinderLimitLatch();
+            sBpcTestServiceCmdService.setBinderProxyWatermarks(binderProxyLimit, rearmThreshold,
+                    binderProxyWarning);
+            // Trigger the Binder Proxy Waring
+            sBpcTestAppCmdService.createTestBinders(binderProxyWarning - baseBinderCount + 1);
+            if (!firstBinderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                fail("Timed out waiting for uid " + sTestPkgUid + " to trigger warning");
+            }
+
             // Exceed the Binder Proxy Limit
-            sBpcTestAppCmdService.createTestBinders(exceedBinderProxyLimit);
-            if (!firstBinderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            sBpcTestAppCmdService.createTestBinders(exceedBinderProxyLimit - binderProxyWarning);
+            if (!firstBinderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 fail("Timed out waiting for uid " + sTestPkgUid + " to hit limit");
             }
 
@@ -321,11 +362,20 @@
             sBpcTestServiceCmdService.forceGc();
             currentBinderCount = sBpcTestServiceCmdService.getBinderProxyCount(sTestPkgUid);
 
-            final CountDownLatch secondBinderLimitLatch = createBinderLimitLatch();
+            final CountDownLatch[] secondBinderLatches = createBinderLimitLatch();
+
+            // Exceed the Binder Proxy warning which should not cause a callback since there has
+            // been no rearm
+            sBpcTestAppCmdService.createTestBinders(binderProxyWarning - currentBinderCount + 1);
+            if (secondBinderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                fail("Received BinderProxyLimitCallback for uid " + sTestPkgUid
+                        + " when the callback has not been rearmed yet");
+            }
+
             // Exceed the Binder Proxy limit which should not cause a callback since there has
             // been no rearm
-            sBpcTestAppCmdService.createTestBinders(exceedBinderProxyLimit - currentBinderCount);
-            if (secondBinderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            sBpcTestAppCmdService.createTestBinders(exceedBinderProxyLimit - binderProxyWarning);
+            if (secondBinderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 fail("Received BinderProxyLimitCallback for uid " + sTestPkgUid
                         + " when the callback has not been rearmed yet");
             }
@@ -337,10 +387,16 @@
 
             sBpcTestServiceCmdService.forceGc();
             currentBinderCount = sBpcTestServiceCmdService.getBinderProxyCount(sTestPkgUid);
+            // Trigger the Binder Proxy Waring
+            sBpcTestAppCmdService.createTestBinders(binderProxyWarning - currentBinderCount + 1);
+            if (!secondBinderLatches[1].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+                fail("Timed out waiting for uid " + sTestPkgUid + " to trigger warning");
+            }
+
             // Exceed the Binder Proxy limit for the last time
             sBpcTestAppCmdService.createTestBinders(exceedBinderProxyLimit - currentBinderCount);
 
-            if (!secondBinderLimitLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            if (!secondBinderLatches[0].await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 fail("Timed out waiting for uid " + sTestPkgUid + " to hit limit");
             }
             sBpcTestAppCmdService.releaseTestBinders(currentBinderCount);
@@ -373,7 +429,7 @@
                 // is not unexpected
             }
 
-            if (!binderDeathLatch.await(TOO_MANY_BINDERS_TIMEOUT_SEC, TimeUnit.SECONDS)) {
+            if (!binderDeathLatch.await(TOO_MANY_BINDERS_WITH_KILL_TIMEOUT_SEC, TimeUnit.SECONDS)) {
                 sBpcTestAppCmdService.releaseSystemBinders(exceedBinderProxyLimit);
                 fail("Timed out waiting for uid " + sTestPkgUid + " to die.");
             }
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 250362b..319f115 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -41,12 +41,15 @@
 import libcore.util.NativeAllocationRegistry;
 
 import java.io.IOException;
+import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
 import java.lang.ref.WeakReference;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
 
 public final class Bitmap implements Parcelable {
     private static final String TAG = "Bitmap";
@@ -120,6 +123,11 @@
     }
 
     /**
+     * @hide
+     */
+    private static final WeakHashMap<Bitmap, Void> sAllBitmaps = new WeakHashMap<>();
+
+    /**
      * Private constructor that must receive an already allocated native bitmap
      * int (pointer).
      */
@@ -162,6 +170,9 @@
                     Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
         }
         registry.registerNativeAllocation(this, nativeBitmap);
+        synchronized (Bitmap.class) {
+          sAllBitmaps.put(this, null);
+        }
     }
 
     /**
@@ -1510,6 +1521,86 @@
     }
 
     /**
+     * @hide
+     */
+    private static final class DumpData {
+        private int count;
+        private int format;
+        private long[] natives;
+        private byte[][] buffers;
+        private int max;
+
+        public DumpData(@NonNull CompressFormat format, int max) {
+            this.max = max;
+            this.format = format.nativeInt;
+            this.natives = new long[max];
+            this.buffers = new byte[max][];
+            this.count = 0;
+        }
+
+        public void add(long nativePtr, byte[] buffer) {
+            natives[count] = nativePtr;
+            buffers[count] = buffer;
+            count = (count >= max) ? max : count + 1;
+        }
+
+        public int size() {
+            return count;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    private static DumpData dumpData = null;
+
+
+    /**
+     * @hide
+     *
+     * Dump all the bitmaps with their contents compressed into dumpData
+     *
+     * @param format  format of the compressed image, null to clear dump data
+     */
+    public static void dumpAll(@Nullable String format) {
+        if (format == null) {
+            /* release the dump data */
+            dumpData = null;
+            return;
+        }
+        final CompressFormat fmt;
+        if (format.equals("jpg") || format.equals("jpeg")) {
+            fmt = CompressFormat.JPEG;
+        } else if (format.equals("png")) {
+            fmt = CompressFormat.PNG;
+        } else if (format.equals("webp")) {
+            fmt = CompressFormat.WEBP_LOSSLESS;
+        } else {
+            Log.w(TAG, "No bitmaps dumped: unrecognized format " + format);
+            return;
+        }
+
+        final ArrayList<Bitmap> allBitmaps;
+        synchronized (Bitmap.class) {
+          allBitmaps = new ArrayList<>(sAllBitmaps.size());
+          for (Bitmap bitmap : sAllBitmaps.keySet()) {
+            if (bitmap != null && !bitmap.isRecycled()) {
+              allBitmaps.add(bitmap);
+            }
+          }
+        }
+
+        dumpData = new DumpData(fmt, allBitmaps.size());
+        for (Bitmap bitmap : allBitmaps) {
+            ByteArrayOutputStream bas = new ByteArrayOutputStream();
+            if (bitmap.compress(fmt, 90, bas)) {
+                dumpData.add(bitmap.getNativeInstance(), bas.toByteArray());
+            }
+        }
+        Log.i(TAG, dumpData.size() + "/" + allBitmaps.size() + " bitmaps dumped");
+    }
+
+    /**
      * Number of bytes of temp storage we use for communicating between the
      * native compressor and the java OutputStream.
      */
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index efbbfc2..24aea37 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -229,4 +229,24 @@
                     "Keystore error while trying to get apps affected by SID.");
         }
     }
+
+    /**
+    * Deletes all keys in all KeyMint devices.
+    * Called by RecoverySystem before rebooting to recovery in order to delete all KeyMint keys,
+    * including synthetic password protector keys (used by LockSettingsService), as well as keys
+    * protecting DE and metadata encryption keys (used by vold). This ensures that FBE-encrypted
+    * data is unrecoverable even if the data wipe in recovery is interrupted or skipped.
+    */
+    public static void deleteAllKeys() throws KeyStoreException {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().deleteAllKeys();
+        } catch (RemoteException | NullPointerException e) {
+            throw new KeyStoreException(SYSTEM_ERROR,
+                    "Failure to connect to Keystore while trying to delete all keys.");
+        } catch (ServiceSpecificException e) {
+            throw new KeyStoreException(e.errorCode,
+                    "Keystore error while trying to delete all keys.");
+        }
+    }
 }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 2cac2e1..2f2215f 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -17,7 +17,6 @@
 package android.security;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.os.StrictMode;
 
 /**
  * This class provides some constants and helper methods related to Android's Keystore service.
@@ -38,17 +37,4 @@
     public static KeyStore getInstance() {
         return KEY_STORE;
     }
-
-    /**
-     * Add an authentication record to the keystore authorization table.
-     *
-     * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
-     * @return 0 on success, otherwise an error value corresponding to a
-     * {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
-     */
-    public int addAuthToken(byte[] authToken) {
-        StrictMode.noteDiskWrite();
-
-        return Authorization.addAuthToken(authToken);
-    }
 }
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/KeyStoreAuthorization.java
similarity index 82%
rename from keystore/java/android/security/Authorization.java
rename to keystore/java/android/security/KeyStoreAuthorization.java
index 6404c4b..14d715f 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/KeyStoreAuthorization.java
@@ -33,15 +33,21 @@
  * @hide This is the client side for IKeystoreAuthorization AIDL.
  * It shall only be used by biometric authentication providers and Gatekeeper.
  */
-public class Authorization {
-    private static final String TAG = "KeystoreAuthorization";
+public class KeyStoreAuthorization {
+    private static final String TAG = "KeyStoreAuthorization";
 
     public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
 
+    private static final KeyStoreAuthorization sInstance = new KeyStoreAuthorization();
+
+    public static KeyStoreAuthorization getInstance() {
+        return sInstance;
+    }
+
     /**
      * @return an instance of IKeystoreAuthorization
      */
-    public static IKeystoreAuthorization getService() {
+    private IKeystoreAuthorization getService() {
         return IKeystoreAuthorization.Stub.asInterface(
                     ServiceManager.checkService("android.security.authorization"));
     }
@@ -52,7 +58,7 @@
      * @param authToken created by Android authenticators.
      * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
      */
-    public static int addAuthToken(@NonNull HardwareAuthToken authToken) {
+    public int addAuthToken(@NonNull HardwareAuthToken authToken) {
         StrictMode.noteSlowCall("addAuthToken");
         try {
             getService().addAuthToken(authToken);
@@ -70,7 +76,7 @@
      * @param authToken
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public static int addAuthToken(@NonNull byte[] authToken) {
+    public int addAuthToken(@NonNull byte[] authToken) {
         return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
     }
 
@@ -82,7 +88,7 @@
      *                   is LSKF (or equivalent) and thus has made the synthetic password available
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public static int onDeviceUnlocked(int userId, @Nullable byte[] password) {
+    public int onDeviceUnlocked(int userId, @Nullable byte[] password) {
         StrictMode.noteDiskWrite();
         try {
             getService().onDeviceUnlocked(userId, password);
@@ -103,7 +109,7 @@
      * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
+    public int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
             boolean weakUnlockEnabled) {
         StrictMode.noteDiskWrite();
         try {
@@ -125,14 +131,17 @@
      * @return the last authentication time or
      * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}.
      */
-    public static long getLastAuthenticationTime(
-            long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
+    public long getLastAuthTime(long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
         try {
             return getService().getLastAuthTime(userId, authenticatorTypes);
         } catch (RemoteException | NullPointerException e) {
-            Log.w(TAG, "Can not connect to keystore", e);
+            Log.w(TAG, "Error getting last auth time: " + e);
             return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
         } catch (ServiceSpecificException e) {
+            // This is returned when the feature flag test fails in keystore2
+            if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
+                throw new UnsupportedOperationException();
+            }
             return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
         }
     }
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index d7b5914..9d4b426 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -304,7 +304,7 @@
     _ZipEntryRO *zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
     const int32_t error = ExtractEntryToFile(mHandle, &(zipEntry->entry), fd);
     if (error) {
-        ALOGW("ExtractToMemory failed with %s", ErrorCodeString(error));
+        ALOGW("ExtractToFile failed with %s", ErrorCodeString(error));
         return false;
     }
 
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 4b63fbf..55b5e81 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -367,7 +367,7 @@
 
 void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
                                        ASurfaceControl* aSurfaceControl,
-                                       int8_t visibility) {
+                                       ASurfaceTransactionVisibility visibility) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
 
@@ -496,7 +496,7 @@
 
 void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
                                                ASurfaceControl* aSurfaceControl,
-                                               int8_t transparency) {
+                                               ASurfaceTransactionTransparency transparency) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
 
diff --git a/nfc/TEST_MAPPING b/nfc/TEST_MAPPING
index 5b5ea37..49c778d 100644
--- a/nfc/TEST_MAPPING
+++ b/nfc/TEST_MAPPING
@@ -5,6 +5,9 @@
     },
     {
       "name": "CtsNfcTestCases"
+    },
+    {
+      "name": "CtsNdefTestCases"
     }
   ]
 }
diff --git a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
index a8d8f9a..75a8bdf 100644
--- a/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/java/com/android/server/PackageWatchdog.java
@@ -137,17 +137,6 @@
     static final int DEFAULT_BOOT_LOOP_TRIGGER_COUNT = 5;
 
     static final long DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS = TimeUnit.MINUTES.toMillis(10);
-    // Boot loop at which packageWatchdog starts first mitigation
-    private static final String BOOT_LOOP_THRESHOLD =
-            "persist.device_config.configuration.boot_loop_threshold";
-    @VisibleForTesting
-    static final int DEFAULT_BOOT_LOOP_THRESHOLD = 15;
-    // Once boot_loop_threshold is surpassed next mitigation would be triggered after
-    // specified number of reboots.
-    private static final String BOOT_LOOP_MITIGATION_INCREMENT =
-            "persist.device_config.configuration..boot_loop_mitigation_increment";
-    @VisibleForTesting
-    static final int DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT = 2;
 
     // Threshold level at which or above user might experience significant disruption.
     private static final String MAJOR_USER_IMPACT_LEVEL_THRESHOLD =
@@ -253,15 +242,8 @@
         mConnectivityModuleConnector = connectivityModuleConnector;
         mSystemClock = clock;
         mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
-        if (Flags.recoverabilityDetection()) {
-            mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    SystemProperties.getInt(BOOT_LOOP_MITIGATION_INCREMENT,
-                            DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-        } else {
-            mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
-        }
+        mBootThreshold = new BootThreshold(DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
+                DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS);
 
         loadFromFile();
         sPackageWatchdog = this;
@@ -526,10 +508,16 @@
     /**
      * Called when the system server boots. If the system server is detected to be in a boot loop,
      * query each observer and perform the mitigation action with the lowest user impact.
+     *
+     * Note: PackageWatchdog considers system_server restart loop as bootloop. Full reboots
+     * are not counted in bootloop.
      */
     @SuppressWarnings("GuardedBy")
     public void noteBoot() {
         synchronized (mLock) {
+            // if boot count has reached threshold, start mitigation.
+            // We wait until threshold number of restarts only for the first time. Perform
+            // mitigations for every restart after that.
             boolean mitigate = mBootThreshold.incrementAndTest();
             if (mitigate) {
                 if (!Flags.recoverabilityDetection()) {
@@ -557,17 +545,13 @@
                 }
                 if (currentObserverToNotify != null) {
                     if (Flags.recoverabilityDetection()) {
-                        if (currentObserverImpact < getUserImpactLevelLimit()
-                                || (currentObserverImpact >= getUserImpactLevelLimit()
-                                        && mBootThreshold.getCount() >= getBootLoopThreshold())) {
-                            int currentObserverMitigationCount =
-                                    currentObserverInternal.getBootMitigationCount() + 1;
-                            currentObserverInternal.setBootMitigationCount(
-                                    currentObserverMitigationCount);
-                            saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
-                            currentObserverToNotify.executeBootLoopMitigation(
-                                    currentObserverMitigationCount);
-                        }
+                        int currentObserverMitigationCount =
+                                currentObserverInternal.getBootMitigationCount() + 1;
+                        currentObserverInternal.setBootMitigationCount(
+                                currentObserverMitigationCount);
+                        saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
+                        currentObserverToNotify.executeBootLoopMitigation(
+                                currentObserverMitigationCount);
                     } else {
                         mBootThreshold.setMitigationCount(mitigationCount);
                         mBootThreshold.saveMitigationCountToMetadata();
@@ -647,11 +631,6 @@
                 DEFAULT_MAJOR_USER_IMPACT_LEVEL_THRESHOLD);
     }
 
-    private int getBootLoopThreshold() {
-        return SystemProperties.getInt(BOOT_LOOP_THRESHOLD,
-                DEFAULT_BOOT_LOOP_THRESHOLD);
-    }
-
     /** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */
     @Retention(SOURCE)
     @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0,
@@ -1827,16 +1806,10 @@
 
         private final int mBootTriggerCount;
         private final long mTriggerWindow;
-        private final int mBootMitigationIncrement;
 
         BootThreshold(int bootTriggerCount, long triggerWindow) {
-            this(bootTriggerCount, triggerWindow, /*bootMitigationIncrement=*/ 1);
-        }
-
-        BootThreshold(int bootTriggerCount, long triggerWindow, int bootMitigationIncrement) {
             this.mBootTriggerCount = bootTriggerCount;
             this.mTriggerWindow = triggerWindow;
-            this.mBootMitigationIncrement = bootMitigationIncrement;
         }
 
         public void reset() {
@@ -1915,6 +1888,7 @@
             } else {
                 readMitigationCountFromMetadataIfNecessary();
             }
+
             final long now = mSystemClock.uptimeMillis();
             if (now - getStart() < 0) {
                 Slog.e(TAG, "Window was less than zero. Resetting start to current time.");
@@ -1939,20 +1913,32 @@
                 setCount(count);
                 EventLogTags.writeRescueNote(Process.ROOT_UID, count, window);
                 if (Flags.recoverabilityDetection()) {
-                    boolean mitigate = (count >= mBootTriggerCount)
-                            && (count - mBootTriggerCount) % mBootMitigationIncrement == 0;
-                    return mitigate;
+                    // After a reboot (e.g. by WARM_REBOOT or mainline rollback) we apply
+                    // mitigations without waiting for DEFAULT_BOOT_LOOP_TRIGGER_COUNT.
+                    return (count >= mBootTriggerCount)
+                            || (performedMitigationsDuringWindow() && count > 1);
                 }
                 return count >= mBootTriggerCount;
             }
         }
 
         @GuardedBy("mLock")
+        private boolean performedMitigationsDuringWindow() {
+            for (ObserverInternal observerInternal: mAllObservers.values()) {
+                if (observerInternal.getBootMitigationCount() > 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @GuardedBy("mLock")
         private void resetAllObserversBootMitigationCount() {
             for (int i = 0; i < mAllObservers.size(); i++) {
                 final ObserverInternal observer = mAllObservers.valueAt(i);
                 observer.setBootMitigationCount(0);
             }
+            saveAllObserversBootMitigationCountToMetadata(METADATA_FILE);
         }
 
         @GuardedBy("mLock")
diff --git a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
index 7093ba4..f86eb61 100644
--- a/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
+++ b/packages/CrashRecovery/services/java/com/android/server/RescueParty.java
@@ -139,7 +139,7 @@
     static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG =
             "namespace_to_package_mapping";
     @VisibleForTesting
-    static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 10;
+    static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 1440;
 
     private static final String NAME = "rescue-party-observer";
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 76c2282..d596288 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -99,9 +99,10 @@
         if (Build.IS_DEBUGGABLE) {
             // b/71353150 - looking for leaked binder proxies
             BinderInternal.nSetBinderProxyCountEnabled(true);
-            BinderInternal.nSetBinderProxyCountWatermarks(1000,900);
+            BinderInternal.nSetBinderProxyCountWatermarks(
+                    /* high= */ 1000, /* low= */ 900, /* warning= */ 950);
             BinderInternal.setBinderProxyCountCallback(
-                    new BinderInternal.BinderProxyLimitListener() {
+                    new BinderInternal.BinderProxyCountEventListener() {
                         @Override
                         public void onLimitReached(int uid) {
                             Slog.w(SystemUIApplication.TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index 3349345..c429329 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -345,9 +345,7 @@
             }
         }
 
-        if (mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
-            Log.d(TAG, "ignoring old pipeline callback because new mobile icon is enabled");
-        } else {
+        if (!mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
             for (int i = 0; i < SIM_SLOTS; i++) {
                 mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
             }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 267f278..7b0bc8f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -169,7 +169,9 @@
         "android.hardware.health-V3-java", // AIDL
         "android.hardware.health-translate-java",
         "android.hardware.light-V1-java",
+        "android.hardware.security.authgraph-V1-java",
         "android.hardware.security.rkp-V3-java",
+        "android.hardware.security.secretkeeper-V1-java",
         "android.hardware.tv.cec-V1.1-java",
         "android.hardware.tv.hdmi.cec-V1-java",
         "android.hardware.tv.hdmi.connection-V1-java",
@@ -206,6 +208,7 @@
         "service-jobscheduler-deviceidle.flags-aconfig-java",
         "net_flags_lib",
         "core_os_flags_lib",
+        "connectivity_flags_lib",
     ],
     javac_shard_size: 50,
     javacflags: [
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 09c1dea..d35892e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -413,6 +413,7 @@
 import com.android.internal.os.BinderCallHeavyHitterWatcher.BinderCallHeavyHitterListener;
 import com.android.internal.os.BinderCallHeavyHitterWatcher.HeavyHitterContainer;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.os.BinderInternal.BinderProxyCountEventListener;
 import com.android.internal.os.BinderTransactionNameResolver;
 import com.android.internal.os.ByteTransferPipe;
 import com.android.internal.os.IResultReceiver;
@@ -610,8 +611,8 @@
     private static final int MINIMUM_MEMORY_GROWTH_THRESHOLD = 10 * 1000; // 10 MB
 
     /**
-     * The number of binder proxies we need to have before we start warning and
-     * dumping debug info.
+     * The number of binder proxies we need to have before we start dumping debug info
+     * and kill the offenders.
      */
     private static final int BINDER_PROXY_HIGH_WATERMARK = 6000;
 
@@ -621,6 +622,11 @@
      */
     private static final int BINDER_PROXY_LOW_WATERMARK = 5500;
 
+    /**
+     * The number of binder proxies we need to have before we start warning.
+     */
+    private static final int BINDER_PROXY_WARNING_WATERMARK = 5750;
+
     // Max character limit for a notification title. If the notification title is larger than this
     // the notification will not be legible to the user.
     private static final int MAX_BUGREPORT_TITLE_SIZE = 100;
@@ -8926,33 +8932,10 @@
 
             t.traceBegin("setBinderProxies");
             BinderInternal.nSetBinderProxyCountWatermarks(BINDER_PROXY_HIGH_WATERMARK,
-                    BINDER_PROXY_LOW_WATERMARK);
+                    BINDER_PROXY_LOW_WATERMARK, BINDER_PROXY_WARNING_WATERMARK);
             BinderInternal.nSetBinderProxyCountEnabled(true);
-            BinderInternal.setBinderProxyCountCallback(
-                    (uid) -> {
-                        Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
-                                + Process.myUid());
-                        BinderProxy.dumpProxyDebugInfo();
-                        if (uid == Process.SYSTEM_UID) {
-                            Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
-                        } else {
-                            killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
-                                    ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
-                                    ApplicationExitInfo.SUBREASON_EXCESSIVE_BINDER_OBJECTS,
-                                    "Too many Binders sent to SYSTEM");
-                            // We need to run a GC here, because killing the processes involved
-                            // actually isn't guaranteed to free up the proxies; in fact, if the
-                            // GC doesn't run for a long time, we may even exceed the global
-                            // proxy limit for a process (20000), resulting in system_server itself
-                            // being killed.
-                            // Note that the GC here might not actually clean up all the proxies,
-                            // because the binder reference decrements will come in asynchronously;
-                            // but if new processes belonging to the UID keep adding proxies, we
-                            // will get another callback here, and run the GC again - this time
-                            // cleaning up the old proxies.
-                            VMRuntime.getRuntime().requestConcurrentGC();
-                        }
-                    }, BackgroundThread.getHandler());
+            BinderInternal.setBinderProxyCountCallback(new MyBinderProxyCountEventListener(),
+                    BackgroundThread.getHandler());
             t.traceEnd(); // setBinderProxies
 
             t.traceEnd(); // ActivityManagerStartApps
@@ -8967,6 +8950,45 @@
         }
     }
 
+    private class MyBinderProxyCountEventListener implements BinderProxyCountEventListener {
+        @Override
+        public void onLimitReached(int uid) {
+            Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
+                    + Process.myUid());
+            BinderProxy.dumpProxyDebugInfo();
+            if (uid == Process.SYSTEM_UID) {
+                Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
+            } else {
+                killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+                        ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+                        ApplicationExitInfo.SUBREASON_EXCESSIVE_BINDER_OBJECTS,
+                        "Too many Binders sent to SYSTEM");
+                // We need to run a GC here, because killing the processes involved
+                // actually isn't guaranteed to free up the proxies; in fact, if the
+                // GC doesn't run for a long time, we may even exceed the global
+                // proxy limit for a process (20000), resulting in system_server itself
+                // being killed.
+                // Note that the GC here might not actually clean up all the proxies,
+                // because the binder reference decrements will come in asynchronously;
+                // but if new processes belonging to the UID keep adding proxies, we
+                // will get another callback here, and run the GC again - this time
+                // cleaning up the old proxies.
+                VMRuntime.getRuntime().requestConcurrentGC();
+            }
+        }
+
+        @Override
+        public void onWarningThresholdReached(int uid) {
+            if (com.android.server.am.Flags.logExcessiveBinderProxies()) {
+                Slog.w(TAG, "Uid " + uid + " sent too many ("
+                        + BINDER_PROXY_WARNING_WATERMARK + ") Binders to uid " + Process.myUid());
+                FrameworkStatsLog.write(
+                        FrameworkStatsLog.EXCESSIVE_BINDER_PROXY_COUNT_REPORTED,
+                        uid);
+            }
+        }
+    }
+
     private void watchDeviceProvisioning(Context context) {
         // setting system property based on whether device is provisioned
 
@@ -17297,7 +17319,8 @@
 
     @Override
     public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
-            boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
+            boolean runGc, String dumpBitmaps,
+            String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
         try {
             // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
             // its own permission (same as profileControl).
@@ -17331,7 +17354,8 @@
                         }
                     }, null);
 
-                thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
+                thread.dumpHeap(managed, mallocInfo, runGc, dumpBitmaps,
+                                path, fd, intermediateCallback);
                 fd = null;
                 return true;
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index c8f6303..7c66731 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1231,6 +1231,7 @@
         final PrintWriter err = getErrPrintWriter();
         boolean managed = true;
         boolean mallocInfo = false;
+        String dumpBitmaps = null;
         int userId = UserHandle.USER_CURRENT;
         boolean runGc = false;
 
@@ -1249,6 +1250,11 @@
             } else if (opt.equals("-m")) {
                 managed = false;
                 mallocInfo = true;
+            } else if (opt.equals("-b")) {
+                dumpBitmaps = getNextArg();
+                if (dumpBitmaps == null) {
+                    dumpBitmaps = "png"; // default to PNG in dumping bitmaps
+                }
             } else {
                 err.println("Error: Unknown option: " + opt);
                 return -1;
@@ -1280,8 +1286,8 @@
             }
         }, null);
 
-        if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, heapFile, fd,
-                finishCallback)) {
+        if (!mInterface.dumpHeap(process, userId, managed, mallocInfo, runGc, dumpBitmaps,
+                heapFile, fd, finishCallback)) {
             err.println("HEAP DUMP FAILED on process " + process);
             return -1;
         }
@@ -4270,11 +4276,14 @@
             pw.println("      --user <USER_ID> | current: When supplying a process name,");
             pw.println("          specify user of process to profile; uses current user if not");
             pw.println("          specified.");
-            pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] <PROCESS> <FILE>");
+            pw.println("  dumpheap [--user <USER_ID> current] [-n] [-g] [-b <format>] ");
+            pw.println("           <PROCESS> <FILE>");
             pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
             pw.println("        be either a process name or pid.  Options are:");
             pw.println("      -n: dump native heap instead of managed heap");
             pw.println("      -g: force GC before dumping the heap");
+            pw.println("      -b <format>: dump contents of bitmaps in the format specified,");
+            pw.println("         which can be \"png\", \"jpg\" or \"webp\".");
             pw.println("      --user <USER_ID> | current: When supplying a process name,");
             pw.println("          specify user of process to dump; uses current user if not specified.");
             pw.println("  set-debug-app [-w] [--persistent] <PACKAGE>");
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 2e0aec9..9b091b3 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1046,7 +1046,9 @@
                                     + mProfile.mApp + " to " + mDumpUri.getPath());
                         }
                         thread.dumpHeap(/* managed= */ true,
-                                /* mallocInfo= */ false, /* runGc= */ false,
+                                /* mallocInfo= */ false,
+                                /* runGc= */ false,
+                                /* dumpbitmaps= */ null,
                                 mDumpUri.getPath(), fd,
                                 /* finishCallback= */ null);
                     } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index bf7cc10..11db302 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -9,7 +9,6 @@
 sudheersai@google.com
 suprabh@google.com
 varunshah@google.com
-kwekua@google.com
 bookatz@google.com
 jji@google.com
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index e876527..4dfa71b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -350,6 +350,7 @@
     // LMK_UPDATE_PROPS
     // LMK_KILL_OCCURRED
     // LMK_START_MONITORING
+    // LMK_BOOT_COMPLETED
     static final byte LMK_TARGET = 0;
     static final byte LMK_PROCPRIO = 1;
     static final byte LMK_PROCREMOVE = 2;
@@ -360,6 +361,7 @@
     static final byte LMK_UPDATE_PROPS = 7;
     static final byte LMK_KILL_OCCURRED = 8; // Msg to subscribed clients on kill occurred event
     static final byte LMK_START_MONITORING = 9; // Start monitoring if delayed earlier
+    static final byte LMK_BOOT_COMPLETED = 10;
 
     // Low Memory Killer Daemon command codes.
     // These must be kept in sync with async_event_type definitions in lmkd.h
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index d9e8ddd..c666915 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -28,3 +28,10 @@
     description: "Restrict network access for certain applications in BFGS process state"
     bug: "304347838"
 }
+
+flag {
+    namespace: "backstage_power"
+    name: "log_excessive_binder_proxies"
+    description: "Log the excessive incoming binder proxies into statsd"
+    bug: "298263955"
+}
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index c507300..69e87fc 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -56,7 +56,7 @@
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -111,7 +111,7 @@
     @NonNull private final BiometricContext mBiometricContext;
     private final IStatusBarService mStatusBarService;
     @VisibleForTesting final IBiometricSysuiReceiver mSysuiReceiver;
-    private final KeyStore mKeyStore;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final Random mRandom;
     private final ClientDeathReceiver mClientDeathReceiver;
     final PreAuthInfo mPreAuthInfo;
@@ -158,7 +158,7 @@
             @NonNull BiometricContext biometricContext,
             @NonNull IStatusBarService statusBarService,
             @NonNull IBiometricSysuiReceiver sysuiReceiver,
-            @NonNull KeyStore keystore,
+            @NonNull KeyStoreAuthorization keyStoreAuthorization,
             @NonNull Random random,
             @NonNull ClientDeathReceiver clientDeathReceiver,
             @NonNull PreAuthInfo preAuthInfo,
@@ -172,8 +172,8 @@
             @NonNull PromptInfo promptInfo,
             boolean debugEnabled,
             @NonNull List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties) {
-        this(context, biometricContext, statusBarService, sysuiReceiver, keystore, random,
-                clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId,
+        this(context, biometricContext, statusBarService, sysuiReceiver, keyStoreAuthorization,
+                random, clientDeathReceiver, preAuthInfo, token, requestId, operationId, userId,
                 sensorReceiver, clientReceiver, opPackageName, promptInfo, debugEnabled,
                 fingerprintSensorProperties, BiometricFrameworkStatsLogger.getInstance());
     }
@@ -183,7 +183,7 @@
             @NonNull BiometricContext biometricContext,
             @NonNull IStatusBarService statusBarService,
             @NonNull IBiometricSysuiReceiver sysuiReceiver,
-            @NonNull KeyStore keystore,
+            @NonNull KeyStoreAuthorization keyStoreAuthorization,
             @NonNull Random random,
             @NonNull ClientDeathReceiver clientDeathReceiver,
             @NonNull PreAuthInfo preAuthInfo,
@@ -203,7 +203,7 @@
         mBiometricContext = biometricContext;
         mStatusBarService = statusBarService;
         mSysuiReceiver = sysuiReceiver;
-        mKeyStore = keystore;
+        mKeyStoreAuthorization = keyStoreAuthorization;
         mRandom = random;
         mClientDeathReceiver = clientDeathReceiver;
         mPreAuthInfo = preAuthInfo;
@@ -814,14 +814,14 @@
             switch (reason) {
                 case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
                     if (credentialAttestation != null) {
-                        mKeyStore.addAuthToken(credentialAttestation);
+                        mKeyStoreAuthorization.addAuthToken(credentialAttestation);
                     } else {
                         Slog.e(TAG, "credentialAttestation is null");
                     }
                 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
                 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
                     if (mTokenEscrow != null) {
-                        final int result = mKeyStore.addAuthToken(mTokenEscrow);
+                        final int result = mKeyStoreAuthorization.addAuthToken(mTokenEscrow);
                         Slog.d(TAG, "addAuthToken: " + result);
                     } else {
                         Slog.e(TAG, "mTokenEscrow is null");
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 91a68ea..bccbee9 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -65,15 +65,11 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.security.Authorization;
 import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.authorization.IKeystoreAuthorization;
-import android.security.authorization.ResponseCode;
+import android.security.KeyStoreAuthorization;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -123,11 +119,9 @@
     @VisibleForTesting
     IStatusBarService mStatusBarService;
     @VisibleForTesting
-    KeyStore mKeyStore;
-    @VisibleForTesting
     ITrustManager mTrustManager;
     @VisibleForTesting
-    IKeystoreAuthorization mKeystoreAuthorization;
+    KeyStoreAuthorization mKeyStoreAuthorization;
     @VisibleForTesting
     IGateKeeperService mGateKeeper;
 
@@ -672,19 +666,7 @@
             int[] authTypesArray = hardwareAuthenticators.stream()
                     .mapToInt(Integer::intValue)
                     .toArray();
-            try {
-                return mKeystoreAuthorization.getLastAuthTime(secureUserId, authTypesArray);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Error getting last auth time: " + e);
-                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-            } catch (ServiceSpecificException e) {
-                // This is returned when the feature flag test fails in keystore2
-                if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
-                    throw new UnsupportedOperationException();
-                }
-
-                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
-            }
+            return mKeyStoreAuthorization.getLastAuthTime(secureUserId, authTypesArray);
         }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@@ -1009,8 +991,8 @@
             return ActivityManager.getService();
         }
 
-        public IKeystoreAuthorization getKeystoreAuthorizationService() {
-            return Authorization.getService();
+        public KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
         }
 
         public IGateKeeperService getGateKeeperService() {
@@ -1034,10 +1016,6 @@
             return new SettingObserver(context, handler, callbacks);
         }
 
-        public KeyStore getKeyStore() {
-            return KeyStore.getInstance();
-        }
-
         /**
          * Allows to enable/disable debug logs.
          */
@@ -1130,7 +1108,7 @@
         mBiometricContext = injector.getBiometricContext(context);
         mUserManager = injector.getUserManager(context);
         mBiometricCameraManager = injector.getBiometricCameraManager(context);
-        mKeystoreAuthorization = injector.getKeystoreAuthorizationService();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mGateKeeper = injector.getGateKeeperService();
 
         try {
@@ -1150,7 +1128,6 @@
 
     @Override
     public void onStart() {
-        mKeyStore = mInjector.getKeyStore();
         mStatusBarService = mInjector.getStatusBarService();
         mTrustManager = mInjector.getTrustManager();
         mInjector.publishBinderService(this, mImpl);
@@ -1458,7 +1435,7 @@
 
         final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
         mAuthSession = new AuthSession(getContext(), mBiometricContext, mStatusBarService,
-                createSysuiReceiver(requestId), mKeyStore, mRandom,
+                createSysuiReceiver(requestId), mKeyStoreAuthorization, mRandom,
                 createClientDeathReceiver(requestId), preAuthInfo, token, requestId,
                 operationId, userId, createBiometricSensorReceiver(requestId), receiver,
                 opPackageName, promptInfo, debugEnabled,
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 6eba23f..749e12b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -30,7 +30,7 @@
 import android.hardware.biometrics.BiometricRequestConstants;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 import android.util.EventLog;
 import android.util.Slog;
 
@@ -255,7 +255,7 @@
 
             // For BP, BiometricService will add the authToken to Keystore.
             if (!isBiometricPrompt() && mIsStrongBiometric) {
-                final int result = KeyStore.getInstance().addAuthToken(byteToken);
+                final int result = KeyStoreAuthorization.getInstance().addAuthToken(byteToken);
                 if (result != 0) {
                     Slog.d(TAG, "Error adding auth token : " + result);
                 } else {
diff --git a/services/core/java/com/android/server/connectivity/Android.bp b/services/core/java/com/android/server/connectivity/Android.bp
new file mode 100644
index 0000000..a374ec2
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/Android.bp
@@ -0,0 +1,10 @@
+aconfig_declarations {
+    name: "connectivity_flags",
+    package: "com.android.server.connectivity",
+    srcs: ["flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "connectivity_flags_lib",
+    aconfig_declarations: "connectivity_flags",
+}
diff --git a/services/core/java/com/android/server/connectivity/flags.aconfig b/services/core/java/com/android/server/connectivity/flags.aconfig
new file mode 100644
index 0000000..32593d4
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.connectivity"
+
+flag {
+    name: "replace_vpn_profile_store"
+    namespace: "android_core_networking"
+    description: "This flag controls the usage of VpnBlobStore to replace LegacyVpnProfileStore."
+    bug: "307903113"
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 0f40ca0..2783fef 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -198,8 +198,7 @@
                 File signatureFile = new File(dir, FONT_SIGNATURE_FILE);
                 if (!signatureFile.exists()) {
                     Slog.i(TAG, "The signature file is missing.");
-                    FileUtils.deleteContentsAndDir(dir);
-                    continue;
+                    return;
                 }
                 byte[] signature;
                 try {
@@ -224,10 +223,36 @@
 
                 FontFileInfo fontFileInfo = validateFontFile(fontFile, signature);
                 if (fontConfig == null) {
-                    fontConfig = getSystemFontConfig();
+                    // Use preinstalled font config for checking revision number.
+                    fontConfig = mConfigSupplier.apply(Collections.emptyMap());
                 }
                 addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, true /* deleteOldFile */);
             }
+
+            // Treat as error if post script name of font family was not installed.
+            for (int i = 0; i < config.fontFamilies.size(); ++i) {
+                FontUpdateRequest.Family family = config.fontFamilies.get(i);
+                for (int j = 0; j < family.getFonts().size(); ++j) {
+                    FontUpdateRequest.Font font = family.getFonts().get(j);
+                    if (mFontFileInfoMap.containsKey(font.getPostScriptName())) {
+                        continue;
+                    }
+
+                    if (fontConfig == null) {
+                        fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+                    }
+
+                    if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) {
+                        continue;
+                    }
+
+                    Slog.e(TAG, "Unknown font that has PostScript name "
+                            + font.getPostScriptName() + " is requested in FontFamily "
+                            + family.getName());
+                    return;
+                }
+            }
+
             success = true;
         } catch (Throwable t) {
             // If something happened during loading system fonts, clear all contents in finally
@@ -239,6 +264,7 @@
                 mFontFileInfoMap.clear();
                 mLastModifiedMillis = 0;
                 FileUtils.deleteContents(mFilesDir);
+                mConfigFile.delete();
             }
         }
     }
@@ -487,8 +513,7 @@
         return shouldAddToMap;
     }
 
-    private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
-        String psName = info.getPostScriptName();
+    private FontConfig.Font getFontByPostScriptName(String psName, FontConfig fontConfig) {
         FontConfig.Font targetFont = null;
         for (int i = 0; i < fontConfig.getFontFamilies().size(); i++) {
             FontConfig.FontFamily family = fontConfig.getFontFamilies().get(i);
@@ -513,6 +538,13 @@
                 }
             }
         }
+        return targetFont;
+    }
+
+    private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
+        String psName = info.getPostScriptName();
+        FontConfig.Font targetFont = getFontByPostScriptName(psName, fontConfig);
+
         if (targetFont == null) {
             return -1;
         }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a9a9d87b..ba99d2e 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -103,7 +103,7 @@
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.security.AndroidKeyStoreMaintenance;
-import android.security.Authorization;
+import android.security.KeyStoreAuthorization;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.security.keystore.recovery.KeyChainProtectionParams;
@@ -289,6 +289,7 @@
     private final SyntheticPasswordManager mSpManager;
 
     private final KeyStore mKeyStore;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
     private final UnifiedProfilePasswordCache mUnifiedProfilePasswordCache;
 
@@ -623,6 +624,10 @@
             }
         }
 
+        public KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
+        }
+
         public @NonNull UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(KeyStore ks) {
             return new UnifiedProfilePasswordCache(ks);
         }
@@ -646,6 +651,7 @@
         mInjector = injector;
         mContext = injector.getContext();
         mKeyStore = injector.getKeyStore();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mRecoverableKeyStoreManager = injector.getRecoverableKeyStoreManager();
         mHandler = injector.getHandler(injector.getServiceThread());
         mStrongAuth = injector.getStrongAuth();
@@ -1434,7 +1440,7 @@
     }
 
     private void unlockKeystore(int userId, SyntheticPassword sp) {
-        Authorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword());
+        mKeyStoreAuthorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword());
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING
index ddf3d76..256d9ba 100644
--- a/services/core/java/com/android/server/locksettings/TEST_MAPPING
+++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING
@@ -24,5 +24,11 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            // TODO(b/332974906): Promote in presubmit-large.
+            "name": "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes"
+        }
     ]
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 994d3ca..6f8a46b 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -786,7 +786,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -813,7 +813,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -848,7 +848,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -875,7 +875,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -902,7 +902,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -929,7 +929,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -954,7 +954,7 @@
             }
         }
         if (deadCallbackHolders != null) {
-            mControllerCallbackHolders.removeAll(deadCallbackHolders);
+            removeControllerHoldersSafely(deadCallbackHolders);
         }
     }
 
@@ -979,7 +979,7 @@
             }
         }
         // After notifying clear all listeners
-        mControllerCallbackHolders.clear();
+        removeControllerHoldersSafely(null);
     }
 
     private PlaybackState getStateWithUpdatedPosition() {
@@ -1027,6 +1027,17 @@
         return -1;
     }
 
+    private void removeControllerHoldersSafely(
+            Collection<ISessionControllerCallbackHolder> holders) {
+        synchronized (mLock) {
+            if (holders == null) {
+                mControllerCallbackHolders.clear();
+            } else {
+                mControllerCallbackHolders.removeAll(holders);
+            }
+        }
+    }
+
     private PlaybackInfo getVolumeAttributes() {
         int volumeType;
         AudioAttributes attributes;
diff --git a/services/core/java/com/android/server/power/batterysaver/OWNERS b/services/core/java/com/android/server/power/batterysaver/OWNERS
index cf23bea..dc2d0b3 100644
--- a/services/core/java/com/android/server/power/batterysaver/OWNERS
+++ b/services/core/java/com/android/server/power/batterysaver/OWNERS
@@ -1,3 +1,2 @@
-kwekua@google.com
 omakoto@google.com
-yamasani@google.com
\ No newline at end of file
+yamasani@google.com
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index c2e2dad..dc46184 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -30,6 +30,7 @@
 import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NO_PROVIDER;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.apex.CompressedApexInfo;
 import android.apex.CompressedApexInfoList;
 import android.content.Context;
@@ -37,6 +38,7 @@
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.hardware.boot.IBootControl;
+import android.hardware.security.secretkeeper.ISecretkeeper;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.os.Binder;
@@ -52,6 +54,7 @@
 import android.os.ShellCallback;
 import android.os.SystemProperties;
 import android.provider.DeviceConfig;
+import android.security.AndroidKeyStoreMaintenance;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.FastImmutableArraySet;
@@ -67,6 +70,7 @@
 import com.android.server.SystemService;
 import com.android.server.pm.ApexManager;
 import com.android.server.recoverysystem.hal.BootControlHIDL;
+import com.android.server.utils.Slogf;
 
 import libcore.io.IoUtils;
 
@@ -118,6 +122,8 @@
     static final String LSKF_CAPTURED_TIMESTAMP_PREF = "lskf_captured_timestamp";
     static final String LSKF_CAPTURED_COUNT_PREF = "lskf_captured_count";
 
+    static final String RECOVERY_WIPE_DATA_COMMAND = "--wipe_data";
+
     private final Injector mInjector;
     private final Context mContext;
 
@@ -521,18 +527,57 @@
     @Override // Binder call
     public void rebootRecoveryWithCommand(String command) {
         if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+
+        boolean isForcedWipe = command != null && command.contains(RECOVERY_WIPE_DATA_COMMAND);
         synchronized (sRequestLock) {
             if (!setupOrClearBcb(true, command)) {
                 Slog.e(TAG, "rebootRecoveryWithCommand failed to setup BCB");
                 return;
             }
 
+            if (isForcedWipe) {
+                deleteSecrets();
+                // TODO: consider adding a dedicated forced-wipe-reboot method to PowerManager and
+                // calling here.
+            }
+
             // Having set up the BCB, go ahead and reboot.
             PowerManager pm = mInjector.getPowerManager();
             pm.reboot(PowerManager.REBOOT_RECOVERY);
         }
     }
 
+    private static void deleteSecrets() {
+        Slogf.w(TAG, "deleteSecrets");
+        try {
+            AndroidKeyStoreMaintenance.deleteAllKeys();
+        } catch (android.security.KeyStoreException e) {
+            Log.wtf(TAG, "Failed to delete all keys from keystore.", e);
+        }
+
+        try {
+            ISecretkeeper secretKeeper = getSecretKeeper();
+            if (secretKeeper != null) {
+                Slogf.i(TAG, "ISecretkeeper.deleteAll();");
+                secretKeeper.deleteAll();
+            }
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Failed to delete all secrets from secretkeeper.", e);
+        }
+    }
+
+    private static @Nullable ISecretkeeper getSecretKeeper() {
+        ISecretkeeper result = null;
+        try {
+            result = ISecretkeeper.Stub.asInterface(
+                ServiceManager.waitForDeclaredService(ISecretkeeper.DESCRIPTOR + "/default"));
+        } catch (SecurityException e) {
+            Slog.w(TAG, "Does not have permissions to get AIDL secretkeeper service");
+        }
+
+        return result;
+    }
+
     private void enforcePermissionForResumeOnReboot() {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
                 != PackageManager.PERMISSION_GRANTED
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 2a93255..c8bcc51 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -54,8 +54,10 @@
 import android.os.UserManager;
 import android.os.ext.SdkExtensions;
 import android.provider.DeviceConfig;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LongArrayQueue;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
@@ -173,6 +175,8 @@
     // Accessed on the handler thread only.
     private long  mRelativeBootTime = calculateRelativeBootTime();
 
+    private final ArrayMap<Integer, Pair<Context, BroadcastReceiver>> mUserBroadcastReceivers;
+
     RollbackManagerServiceImpl(Context context) {
         mContext = context;
         // Note that we're calling onStart here because this object is only constructed on
@@ -210,6 +214,8 @@
             }
         });
 
+        mUserBroadcastReceivers = new ArrayMap<>();
+
         UserManager userManager = mContext.getSystemService(UserManager.class);
         for (UserHandle user : userManager.getUserHandles(true)) {
             registerUserCallbacks(user);
@@ -275,7 +281,9 @@
             }
         }, enableRollbackTimedOutFilter, null, getHandler());
 
-        IntentFilter userAddedIntentFilter = new IntentFilter(Intent.ACTION_USER_ADDED);
+        IntentFilter userIntentFilter = new IntentFilter();
+        userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
+        userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -287,9 +295,15 @@
                         return;
                     }
                     registerUserCallbacks(UserHandle.of(newUserId));
+                } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
+                    final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                    if (newUserId == -1) {
+                        return;
+                    }
+                    unregisterUserCallbacks(UserHandle.of(newUserId));
                 }
             }
-        }, userAddedIntentFilter, null, getHandler());
+        }, userIntentFilter, null, getHandler());
 
         registerTimeChangeReceiver();
     }
@@ -335,7 +349,7 @@
         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
         filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
         filter.addDataScheme("package");
-        context.registerReceiver(new BroadcastReceiver() {
+        BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 assertInWorkerThread();
@@ -354,7 +368,21 @@
                     onPackageFullyRemoved(packageName);
                 }
             }
-        }, filter, null, getHandler());
+        };
+        context.registerReceiver(receiver, filter, null, getHandler());
+        mUserBroadcastReceivers.put(user.getIdentifier(), new Pair(context, receiver));
+    }
+
+    @AnyThread
+    private void unregisterUserCallbacks(UserHandle user) {
+        Pair<Context, BroadcastReceiver> pair = mUserBroadcastReceivers.get(user.getIdentifier());
+        if (pair == null || pair.first == null || pair.second == null) {
+            Slog.e(TAG, "No receiver found for the user" + user);
+            return;
+        }
+
+        pair.first.unregisterReceiver(pair.second);
+        mUserBroadcastReceivers.remove(user.getIdentifier());
     }
 
     @ExtThread
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index e5a8a6d..7794048 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -61,7 +61,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.security.Authorization;
+import android.security.KeyStoreAuthorization;
 import android.service.trust.GrantTrustResult;
 import android.service.trust.TrustAgentService;
 import android.text.TextUtils;
@@ -156,6 +156,7 @@
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
+    private final KeyStoreAuthorization mKeyStoreAuthorization;
     private final UserManager mUserManager;
     private final ActivityManager mActivityManager;
     private FingerprintManager mFingerprintManager;
@@ -249,25 +250,27 @@
      * cases.
      */
     protected static class Injector {
-        private final LockPatternUtils mLockPatternUtils;
-        private final Looper mLooper;
+        private final Context mContext;
 
-        public Injector(LockPatternUtils lockPatternUtils, Looper looper) {
-            mLockPatternUtils = lockPatternUtils;
-            mLooper = looper;
+        public Injector(Context context) {
+            mContext = context;
         }
 
         LockPatternUtils getLockPatternUtils() {
-            return mLockPatternUtils;
+            return new LockPatternUtils(mContext);
+        }
+
+        KeyStoreAuthorization getKeyStoreAuthorization() {
+            return KeyStoreAuthorization.getInstance();
         }
 
         Looper getLooper() {
-            return mLooper;
+            return Looper.myLooper();
         }
     }
 
     public TrustManagerService(Context context) {
-        this(context, new Injector(new LockPatternUtils(context), Looper.myLooper()));
+        this(context, new Injector(context));
     }
 
     protected TrustManagerService(Context context, Injector injector) {
@@ -277,6 +280,7 @@
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         mLockPatternUtils = injector.getLockPatternUtils();
+        mKeyStoreAuthorization = injector.getKeyStoreAuthorization();
         mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper());
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
     }
@@ -908,16 +912,16 @@
                 int authUserId = mLockPatternUtils.isProfileWithUnifiedChallenge(userId)
                         ? resolveProfileParent(userId) : userId;
 
-                Authorization.onDeviceLocked(userId, getBiometricSids(authUserId),
+                mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(authUserId),
                         isWeakUnlockMethodEnabled(authUserId));
             } else {
-                Authorization.onDeviceLocked(userId, getBiometricSids(userId), false);
+                mKeyStoreAuthorization.onDeviceLocked(userId, getBiometricSids(userId), false);
             }
         } else {
             // Notify Keystore that the device is now unlocked for the user.  Note that for unlocks
             // with LSKF, this is redundant with the call from LockSettingsService which provides
             // the password.  However, for unlocks with biometric or trust agent, this is required.
-            Authorization.onDeviceUnlocked(userId, /* password= */ null);
+            mKeyStoreAuthorization.onDeviceUnlocked(userId, /* password= */ null);
         }
     }
 
diff --git a/services/core/java/com/android/server/utils/quota/OWNERS b/services/core/java/com/android/server/utils/quota/OWNERS
index a2943f3..469acb2 100644
--- a/services/core/java/com/android/server/utils/quota/OWNERS
+++ b/services/core/java/com/android/server/utils/quota/OWNERS
@@ -1,4 +1,3 @@
 dplotnikov@google.com
-kwekua@google.com
 omakoto@google.com
 yamasani@google.com
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
index 0d5534b..b8cb4a9 100644
--- a/services/devicepolicy/TEST_MAPPING
+++ b/services/devicepolicy/TEST_MAPPING
@@ -26,5 +26,12 @@
         }
       ]
     }
+  ],
+  "postsubmit": [
+    {
+      // TODO(b/332974906): Promote in presubmit presubmit-devicepolicy.
+      "name": "CtsDevicePolicyManagerTestCases_NoFlakes_NoLarge",
+      "name": "CtsDevicePolicyManagerTestCases_ParentProfileApiDisabled"
+    }
   ]
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/OWNERS b/services/tests/mockingservicestests/src/com/android/server/OWNERS
index f801560..0eb8639 100644
--- a/services/tests/mockingservicestests/src/com/android/server/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/OWNERS
@@ -1,5 +1,5 @@
 per-file *Alarm* = file:/apex/jobscheduler/OWNERS
 per-file *AppStateTracker* = file:/apex/jobscheduler/OWNERS
 per-file *DeviceIdleController* = file:/apex/jobscheduler/OWNERS
-per-file SensitiveContentProtectionManagerServiceTest.java = file:/core/java/android/permission/OWNERS
+per-file SensitiveContentProtectionManagerService* = file:/core/java/android/permission/OWNERS
 per-file RescuePartyTest.java = file:/packages/CrashRecovery/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 682569f..697548c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -1111,16 +1111,9 @@
 
         // mock properties in BootThreshold
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
             mCrashRecoveryPropertiesMap = new HashMap<>();
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
index b415682..0532e04 100644
--- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java
@@ -55,6 +55,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -63,8 +64,7 @@
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.provider.Settings;
-import android.security.Authorization;
-import android.security.authorization.IKeystoreAuthorization;
+import android.security.KeyStoreAuthorization;
 import android.service.trust.TrustAgentService;
 import android.testing.TestableContext;
 import android.view.IWindowManager;
@@ -96,7 +96,6 @@
     @Rule
     public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
             .spyStatic(ActivityManager.class)
-            .spyStatic(Authorization.class)
             .mockStatic(ServiceManager.class)
             .mockStatic(WindowManagerGlobal.class)
             .build();
@@ -126,14 +125,13 @@
     private @Mock DevicePolicyManager mDevicePolicyManager;
     private @Mock FaceManager mFaceManager;
     private @Mock FingerprintManager mFingerprintManager;
-    private @Mock IKeystoreAuthorization mKeystoreAuthorization;
+    private @Mock KeyStoreAuthorization mKeyStoreAuthorization;
     private @Mock LockPatternUtils mLockPatternUtils;
     private @Mock PackageManager mPackageManager;
     private @Mock UserManager mUserManager;
     private @Mock IWindowManager mWindowManager;
 
     private HandlerThread mHandlerThread;
-    private TrustManagerService.Injector mInjector;
     private TrustManagerService mService;
     private ITrustManager mTrustManager;
 
@@ -145,8 +143,6 @@
         when(mFaceManager.getSensorProperties()).thenReturn(List.of());
         when(mFingerprintManager.getSensorProperties()).thenReturn(List.of());
 
-        doReturn(mKeystoreAuthorization).when(() -> Authorization.getService());
-
         when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
         when(mLockPatternUtils.isSecure(TEST_USER_ID)).thenReturn(true);
         when(mLockPatternUtils.getKnownTrustAgents(TEST_USER_ID)).thenReturn(mKnownTrustAgents);
@@ -193,8 +189,7 @@
 
         mHandlerThread = new HandlerThread("handler");
         mHandlerThread.start();
-        mInjector = new TrustManagerService.Injector(mLockPatternUtils, mHandlerThread.getLooper());
-        mService = new TrustManagerService(mMockContext, mInjector);
+        mService = new TrustManagerService(mMockContext, new MockInjector(mMockContext));
 
         // Get the ITrustManager from the new TrustManagerService.
         mService.onStart();
@@ -204,6 +199,27 @@
         mTrustManager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue());
     }
 
+    private class MockInjector extends TrustManagerService.Injector {
+        MockInjector(Context context) {
+            super(context);
+        }
+
+        @Override
+        LockPatternUtils getLockPatternUtils() {
+            return mLockPatternUtils;
+        }
+
+        @Override
+        KeyStoreAuthorization getKeyStoreAuthorization() {
+            return mKeyStoreAuthorization;
+        }
+
+        @Override
+        Looper getLooper() {
+            return mHandlerThread.getLooper();
+        }
+    }
+
     @After
     public void tearDown() {
         LocalServices.removeServiceForTest(SystemServiceManager.class);
@@ -371,14 +387,14 @@
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(false);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null);
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PARENT_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(true);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PARENT_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PROFILE_USER_ID), eq(PARENT_BIOMETRIC_SIDS), eq(false));
     }
 
@@ -392,10 +408,10 @@
         setupMocksForProfile(/* unifiedChallenge= */ false);
 
         mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, false);
-        verify(mKeystoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(PROFILE_USER_ID, null);
 
         mTrustManager.setDeviceLockedForUser(PROFILE_USER_ID, true);
-        verify(mKeystoreAuthorization)
+        verify(mKeyStoreAuthorization)
                 .onDeviceLocked(eq(PROFILE_USER_ID), eq(PROFILE_BIOMETRIC_SIDS), eq(false));
     }
 
@@ -572,11 +588,11 @@
     private void verifyWeakUnlockValue(boolean expectedWeakUnlockEnabled) throws Exception {
         when(mWindowManager.isKeyguardLocked()).thenReturn(false);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceUnlocked(TEST_USER_ID, null);
+        verify(mKeyStoreAuthorization).onDeviceUnlocked(TEST_USER_ID, null);
 
         when(mWindowManager.isKeyguardLocked()).thenReturn(true);
         mTrustManager.reportKeyguardShowingChanged();
-        verify(mKeystoreAuthorization).onDeviceLocked(eq(TEST_USER_ID), any(),
+        verify(mKeyStoreAuthorization).onDeviceLocked(eq(TEST_USER_ID), any(),
                 eq(expectedWeakUnlockEnabled));
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index 74eb79d..34092b6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -68,7 +68,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.security.KeyStore;
+import android.security.KeyStoreAuthorization;
 
 import androidx.test.filters.SmallTest;
 
@@ -105,7 +105,7 @@
     @Mock private IBiometricServiceReceiver mClientReceiver;
     @Mock private IStatusBarService mStatusBarService;
     @Mock private IBiometricSysuiReceiver mSysuiReceiver;
-    @Mock private KeyStore mKeyStore;
+    @Mock private KeyStoreAuthorization mKeyStoreAuthorization;
     @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
     @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
     @Mock private BiometricCameraManager mBiometricCameraManager;
@@ -665,9 +665,10 @@
         final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo,
                 checkDevicePolicyManager);
         return new AuthSession(mContext, mBiometricContext, mStatusBarService, mSysuiReceiver,
-                mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId,
-                operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo,
-                false /* debugEnabled */, mFingerprintSensorProps, mBiometricFrameworkStatsLogger);
+                mKeyStoreAuthorization, mRandom, mClientDeathReceiver, preAuthInfo, mToken,
+                requestId, operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE,
+                promptInfo, false /* debugEnabled */, mFingerprintSensorProps,
+                mBiometricFrameworkStatsLogger);
     }
 
     private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 408442b..3eaf9af 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -80,8 +80,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.authorization.IKeystoreAuthorization;
+import android.security.KeyStoreAuthorization;
 import android.service.gatekeeper.IGateKeeperService;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -173,7 +172,7 @@
     private BiometricCameraManager mBiometricCameraManager;
 
     @Mock
-    private IKeystoreAuthorization mKeystoreAuthService;
+    private KeyStoreAuthorization mKeyStoreAuthorization;
 
     @Mock
     private IGateKeeperService mGateKeeperService;
@@ -195,7 +194,7 @@
         when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class));
         when(mInjector.getSettingObserver(any(), any(), any()))
                 .thenReturn(mock(BiometricService.SettingObserver.class));
-        when(mInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
+        when(mInjector.getKeyStoreAuthorization()).thenReturn(mock(KeyStoreAuthorization.class));
         when(mInjector.isDebugEnabled(any(), anyInt())).thenReturn(false);
         when(mInjector.getBiometricStrengthController(any()))
                 .thenReturn(mock(BiometricStrengthController.class));
@@ -231,7 +230,7 @@
                 mStatusBarService, null /* handler */,
                 mAuthSessionCoordinator);
         when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider);
-        when(mInjector.getKeystoreAuthorizationService()).thenReturn(mKeystoreAuthService);
+        when(mInjector.getKeyStoreAuthorization()).thenReturn(mKeyStoreAuthorization);
         when(mInjector.getGateKeeperService()).thenReturn(mGateKeeperService);
         when(mGateKeeperService.getSecureUserId(anyInt())).thenReturn(42L);
 
@@ -661,9 +660,9 @@
         waitForIdle();
         // HAT sent to keystore
         if (isStrongBiometric) {
-            verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
+            verify(mKeyStoreAuthorization).addAuthToken(AdditionalMatchers.aryEq(HAT));
         } else {
-            verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+            verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         }
         // Send onAuthenticated to client
         verify(mReceiver1).onAuthenticationSucceeded(
@@ -726,7 +725,7 @@
         waitForIdle();
         // Waiting for SystemUI to send confirmation callback
         assertEquals(STATE_AUTH_PENDING_CONFIRM, mBiometricService.mAuthSession.getState());
-        verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+        verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
 
         // SystemUI sends confirm, HAT is sent to keystore and client is notified.
         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
@@ -734,9 +733,9 @@
                 null /* credentialAttestation */);
         waitForIdle();
         if (isStrongBiometric) {
-            verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
+            verify(mKeyStoreAuthorization).addAuthToken(AdditionalMatchers.aryEq(HAT));
         } else {
-            verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+            verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         }
         verify(mReceiver1).onAuthenticationSucceeded(
                 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
@@ -1292,7 +1291,7 @@
                 eq(TYPE_FACE),
                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
                 eq(0 /* vendorCode */));
-        verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
+        verify(mKeyStoreAuthorization, never()).addAuthToken(any(byte[].class));
         assertNull(mBiometricService.mAuthSession);
     }
 
@@ -1796,7 +1795,7 @@
 
         final long expectedResult = 31337L;
 
-        when(mKeystoreAuthService.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)))
+        when(mKeyStoreAuthorization.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)))
                 .thenReturn(expectedResult);
 
         mBiometricService = new BiometricService(mContext, mInjector);
@@ -1805,7 +1804,8 @@
                 Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL);
 
         assertEquals(expectedResult, result);
-        verify(mKeystoreAuthService).getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators));
+        verify(mKeyStoreAuthorization).getLastAuthTime(eq(secureUserId),
+                eq(hardwareAuthenticators));
     }
 
     // Helper methods
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index 3de167e..5fb15e9 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -1001,6 +1001,563 @@
         assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
     }
 
+    private UpdatableFontDir createNewUpdateDir() {
+        UpdatableFontDir dir = new UpdatableFontDir(
+                mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
+                mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+        dir.loadFontFileMap();
+        return dir;
+    }
+
+    private UpdatableFontDir installTestFontFamilies(int version) {
+        UpdatableFontDir dir = createNewUpdateDir();
+        try {
+            dir.update(Arrays.asList(
+                    newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE),
+                    newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE),
+                    newAddFontFamilyRequest("<family name='foobar'>"
+                            + "  <font>foo.ttf</font>"
+                            + "  <font>bar.ttf</font>"
+                            + "</family>")));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return dir;
+    }
+
+    private UpdatableFontDir installTestFontFile(int numFonts, int version) {
+        UpdatableFontDir dir = createNewUpdateDir();
+        List<FontUpdateRequest> requests = new ArrayList<>();
+        if (numFonts <= 0 || numFonts > 3) {
+            throw new IllegalArgumentException("numFont must be 1, 2 or 3");
+        }
+        try {
+            requests.add(newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE));
+            if (numFonts >= 2) {
+                requests.add(newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE));
+            }
+            if (numFonts == 3) {
+                requests.add(newFontUpdateRequest("baz.ttf," + version + ",baz", GOOD_SIGNATURE));
+            }
+            dir.update(requests);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return dir;
+    }
+
+    private List<File> collectSignatureFiles() {
+        return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+                .map((file) -> file.listFiles((unused, s) -> s.endsWith(".fsv_sig")))
+                .flatMap(Arrays::stream)
+                .toList();
+    }
+
+    private List<File> collectFontFiles() {
+        return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+                .map((file) -> file.listFiles((unused, s) -> s.endsWith(".ttf")))
+                .flatMap(Arrays::stream)
+                .toList();
+    }
+
+    private void removeAll(List<File> files) {
+        files.forEach((File file) -> {
+            if (file.isDirectory()) {
+                removeAll(List.of(file.listFiles()));
+            } else {
+                assertThat(file.delete()).isTrue();
+            }
+        });
+    }
+
+    private void assertTestFontFamilyInstalled(UpdatableFontDir dir, int version) {
+        try {
+            assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
+            assertThat(dir.getFontFamilyMap()).containsKey("foobar");
+            assertThat(dir.getFontFamilyMap().get("foobar").getFamilies().size()).isEqualTo(1);
+            FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar").getFamilies()
+                    .get(0);
+            assertThat(foobar.getFontList()).hasSize(2);
+            assertThat(foobar.getFontList().get(0).getFile())
+                    .isEqualTo(dir.getPostScriptMap().get("foo"));
+            assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+            assertThat(foobar.getFontList().get(1).getFile())
+                    .isEqualTo(dir.getPostScriptMap().get("bar"));
+            assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(version);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void assertTestFontInstalled(UpdatableFontDir dir, int version) {
+        try {
+            assertThat(dir.getPostScriptMap().containsKey("foo")).isTrue();
+            assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void signatureMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete one signature file
+        assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1);
+
+        // Delete one signature file
+        assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf and bar.ttf
+        installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+        // Delete one signature file
+        assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf and bar.ttf
+        installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+        // Delete one signature file
+        assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all signature files
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all signature files
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all signature files
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void signatureAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all signature files
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete one font file
+        assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1);
+
+        // Delete one font file
+        assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf and bar.ttf
+        installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+        // Delete one font file
+        assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf and bar.ttf
+        installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+        // Delete one font file
+        assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontDirAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontDirAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontDirAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void fontDirAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void dirContentAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void dirContentAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+        // Install font families, foo.ttf, bar.ttf.
+        installTestFontFamilies(1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void dirContentAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+    }
+
+    @Test
+    public void dirContentAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+        // Install font file, foo.ttf
+        installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+        // Delete all font files
+        removeAll(collectFontFiles());
+        removeAll(collectSignatureFiles());
+
+        // New instance of UpdatableFontDir, this emulate a device reboot.
+        UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+        // Make sure the font installation succeeds.
+        assertTestFontInstalled(dir, 2 /* version */);
+
+        // Make sure after the reboot, the configuration remains.
+        UpdatableFontDir nextDir = createNewUpdateDir();
+        assertTestFontInstalled(nextDir, 2 /* version */);
+    }
+
     private FontUpdateRequest newFontUpdateRequest(String content, String signature)
             throws Exception {
         File file = File.createTempFile("font", "ttf", mCacheDir);
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 081da11..489ef44 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -66,6 +66,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
@@ -220,43 +221,36 @@
         RescuePartyObserver rescuePartyObserver = setUpRescuePartyObserver(watchdog);
 
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
+
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
+
         verify(rescuePartyObserver).executeBootLoopMitigation(1);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(2);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(3);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(4);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(5);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(6);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
     }
@@ -268,11 +262,11 @@
                 setUpRollbackPackageHealthObserver(watchdog);
 
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
+
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
+
         verify(rollbackObserver).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
@@ -280,19 +274,16 @@
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
                 ROLLBACK_INFO_MANUAL));
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rollbackObserver).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
 
         // Update the list of available rollbacks after executing bootloop mitigation once
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
     }
 
@@ -305,27 +296,21 @@
 
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
-        int bootCounter = 0;
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
-            bootCounter += 1;
         }
         verify(rescuePartyObserver).executeBootLoopMitigation(1);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(1);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(2);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-            bootCounter += 1;
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(3);
         verify(rollbackObserver).executeBootLoopMitigation(1);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
@@ -333,43 +318,46 @@
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_HIGH,
                 ROLLBACK_INFO_MANUAL));
 
-        int bootLoopThreshold = PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - bootCounter;
-        for (int i = 0; i < bootLoopThreshold; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(3);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(4);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(4);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(5);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(5);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
         verify(rollbackObserver, never()).executeBootLoopMitigation(2);
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(6);
         verify(rollbackObserver).executeBootLoopMitigation(2);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
         // Update the list of available rollbacks after executing bootloop mitigation
         when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(ROLLBACK_INFO_MANUAL));
 
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; i++) {
-            watchdog.noteBoot();
-        }
+        watchdog.noteBoot();
+
         verify(rescuePartyObserver).executeBootLoopMitigation(6);
         verify(rescuePartyObserver, never()).executeBootLoopMitigation(7);
         verify(rollbackObserver, never()).executeBootLoopMitigation(3);
+
+        moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
+        Mockito.reset(rescuePartyObserver);
+
+        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
+            watchdog.noteBoot();
+        }
+        verify(rescuePartyObserver).executeBootLoopMitigation(1);
+        verify(rescuePartyObserver, never()).executeBootLoopMitigation(2);
     }
 
     RollbackPackageHealthObserver setUpRollbackPackageHealthObserver(PackageWatchdog watchdog) {
@@ -506,16 +494,9 @@
         }
 
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
                 String storedValue = mCrashRecoveryPropertiesMap
@@ -640,5 +621,16 @@
         public long uptimeMillis() {
             return mUpTimeMillis;
         }
+        public void moveTimeForward(long milliSeconds) {
+            mUpTimeMillis += milliSeconds;
+        }
+    }
+
+    private void moveTimeForwardAndDispatch(long milliSeconds) {
+        // Exhaust all due runnables now which shouldn't be executed after time-leap
+        mTestLooper.dispatchAll();
+        mTestClock.moveTimeForward(milliSeconds);
+        mTestLooper.moveTimeForward(milliSeconds);
+        mTestLooper.dispatchAll();
     }
 }
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 4f27e06..1fdf97a 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1224,7 +1224,7 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
         watchdog.registerHealthObserver(bootObserver);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+        for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
         assertThat(bootObserver.mitigatedBootLoop()).isTrue();
@@ -1262,22 +1262,6 @@
     }
 
     /**
-     * Ensure that boot loop mitigation is not done when the number of boots does not meet the
-     * threshold.
-     */
-    @Test
-    public void testBootLoopDetection_doesNotMeetThresholdRecoverabilityHighImpact() {
-        PackageWatchdog watchdog = createWatchdog();
-        TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
-        watchdog.registerHealthObserver(bootObserver);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; i++) {
-            watchdog.noteBoot();
-        }
-        assertThat(bootObserver.mitigatedBootLoop()).isFalse();
-    }
-
-    /**
      * Ensure that boot loop mitigation is done for the observer with the lowest user impact
      */
     @Test
@@ -1306,7 +1290,7 @@
         bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
         watchdog.registerHealthObserver(bootObserver1);
         watchdog.registerHealthObserver(bootObserver2);
-        for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD; i++) {
+        for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
         assertThat(bootObserver1.mitigatedBootLoop()).isTrue();
@@ -1349,9 +1333,7 @@
             watchdog.noteBoot();
         }
         for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
                 watchdog.noteBoot();
-            }
         }
 
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
@@ -1360,38 +1342,7 @@
             watchdog.noteBoot();
         }
         for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
                 watchdog.noteBoot();
-            }
-        }
-
-        assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
-    }
-
-    @Test
-    public void testMultipleBootLoopMitigationRecoverabilityHighImpact() {
-        PackageWatchdog watchdog = createWatchdog();
-        TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_LEVEL_80);
-        watchdog.registerHealthObserver(bootObserver);
-        for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
-            watchdog.noteBoot();
-        }
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
-                watchdog.noteBoot();
-            }
-        }
-
-        moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_DEESCALATION_WINDOW_MS + 1);
-
-        for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_THRESHOLD - 1; j++) {
-            watchdog.noteBoot();
-        }
-        for (int i = 0; i < 4; i++) {
-            for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT; j++) {
-                watchdog.noteBoot();
-            }
         }
 
         assertThat(bootObserver.mBootMitigationCounts).isEqualTo(List.of(1, 2, 3, 4, 1, 2, 3, 4));
@@ -1642,8 +1593,7 @@
 
         mSpyBootThreshold = spy(watchdog.new BootThreshold(
                 PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
+                PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
 
         watchdog.saveAllObserversBootMitigationCountToMetadata(filePath);
 
@@ -1798,16 +1748,9 @@
         mCrashRecoveryPropertiesMap = new HashMap<>();
 
         try {
-            if (Flags.recoverabilityDetection()) {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS,
-                    PackageWatchdog.DEFAULT_BOOT_LOOP_MITIGATION_INCREMENT));
-            } else {
-                mSpyBootThreshold = spy(watchdog.new BootThreshold(
+            mSpyBootThreshold = spy(watchdog.new BootThreshold(
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT,
                     PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS));
-            }
 
             doAnswer((Answer<Integer>) invocationOnMock -> {
                 String storedValue = mCrashRecoveryPropertiesMap
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index c02d8e9..a0bb84d 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -21,6 +21,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_usb",
 }
 
 android_test {
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index 92c2711..c4ebdec 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -21,6 +21,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_android_usb",
 }
 
 android_test {