Merge "Handle the client volume mute events"
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 2da00c7..6d5c160 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -274,24 +274,19 @@
     public void onBootPhase(int phase) {
         mBootPhase = phase;
 
-        if (PHASE_SYSTEM_SERVICES_READY == phase) {
-            mConfigObserver.start();
-            mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
-                    ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
-            setupEverything();
-        } else if (PHASE_BOOT_COMPLETED == phase) {
-            if (!mExemptListLoaded) {
-                synchronized (mLock) {
-                    try {
-                        mExemptedApps =
-                                new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
-                    } catch (RemoteException e) {
-                        // Shouldn't happen.
-                        Slog.wtf(TAG, e);
-                    }
-                    mExemptListLoaded = true;
-                }
-            }
+        switch (phase) {
+            case PHASE_SYSTEM_SERVICES_READY:
+                mConfigObserver.start();
+                mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+                        ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+                onBootPhaseSystemServicesReady();
+                break;
+            case PHASE_THIRD_PARTY_APPS_CAN_START:
+                onBootPhaseThirdPartyAppsCanStart();
+                break;
+            case PHASE_BOOT_COMPLETED:
+                onBootPhaseBootCompleted();
+                break;
         }
     }
 
@@ -403,10 +398,9 @@
             final ArraySet<String> added = new ArraySet<>();
             try {
                 mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
+                mExemptListLoaded = true;
             } catch (RemoteException e) {
                 // Shouldn't happen.
-                Slog.wtf(TAG, e);
-                return;
             }
 
             for (int i = mExemptedApps.size() - 1; i >= 0; --i) {
@@ -695,17 +689,11 @@
 
     /** Perform long-running and/or heavy setup work. This should be called off the main thread. */
     private void setupHeavyWork() {
+        if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || !mIsEnabled) {
+            return;
+        }
         synchronized (mLock) {
             loadInstalledPackageListLocked();
-            if (mBootPhase >= PHASE_BOOT_COMPLETED && !mExemptListLoaded) {
-                try {
-                    mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
-                } catch (RemoteException e) {
-                    // Shouldn't happen.
-                    Slog.wtf(TAG, e);
-                }
-                mExemptListLoaded = true;
-            }
             final boolean isFirstSetup = !mScribe.recordExists();
             if (isFirstSetup) {
                 mAgent.grantBirthrightsLocked();
@@ -726,18 +714,57 @@
         }
     }
 
-    private void setupEverything() {
+    private void onBootPhaseSystemServicesReady() {
         if (mBootPhase < PHASE_SYSTEM_SERVICES_READY || !mIsEnabled) {
             return;
         }
         synchronized (mLock) {
             registerListeners();
             mCurrentBatteryLevel = getCurrentBatteryLevel();
+        }
+    }
+
+    private void onBootPhaseThirdPartyAppsCanStart() {
+        if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || !mIsEnabled) {
+            return;
+        }
+        synchronized (mLock) {
             mHandler.post(this::setupHeavyWork);
             mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
         }
     }
 
+    private void onBootPhaseBootCompleted() {
+        if (mBootPhase < PHASE_BOOT_COMPLETED || !mIsEnabled) {
+            return;
+        }
+        synchronized (mLock) {
+            if (!mExemptListLoaded) {
+                try {
+                    mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
+                    mExemptListLoaded = true;
+                } catch (RemoteException e) {
+                    // Shouldn't happen.
+                }
+            }
+        }
+    }
+
+    private void setupEverything() {
+        if (!mIsEnabled) {
+            return;
+        }
+        if (mBootPhase >= PHASE_SYSTEM_SERVICES_READY) {
+            onBootPhaseSystemServicesReady();
+        }
+        if (mBootPhase >= PHASE_THIRD_PARTY_APPS_CAN_START) {
+            onBootPhaseThirdPartyAppsCanStart();
+        }
+        if (mBootPhase >= PHASE_BOOT_COMPLETED) {
+            onBootPhaseBootCompleted();
+        }
+    }
+
     private void tearDownEverything() {
         if (mIsEnabled) {
             return;
diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java
index 9add310e..4b090f5 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Event.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Event.java
@@ -25,6 +25,7 @@
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.stream.IntStream;
 
 import src.com.android.commands.uinput.InputAbsInfo;
 
@@ -338,7 +339,7 @@
                 mReader.beginArray();
                 while (mReader.hasNext()) {
                     int type = 0;
-                    int[] data = null;
+                    IntStream data = null;
                     mReader.beginObject();
                     while (mReader.hasNext()) {
                         String name = mReader.nextName();
@@ -347,8 +348,7 @@
                                 type = readInt();
                                 break;
                             case "data":
-                                data = readIntList().stream()
-                                            .mapToInt(Integer::intValue).toArray();
+                                data = readIntList().stream().mapToInt(Integer::intValue);
                                 break;
                             default:
                                 consumeRemainingElements();
@@ -359,7 +359,9 @@
                     }
                     mReader.endObject();
                     if (data != null) {
-                        configuration.put(type, data);
+                        final int[] existing = configuration.get(type);
+                        configuration.put(type, existing == null ? data.toArray()
+                                : IntStream.concat(IntStream.of(existing), data).toArray());
                     }
                 }
                 mReader.endArray();
diff --git a/core/api/current.txt b/core/api/current.txt
index 1cd8253..da3746d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11523,6 +11523,7 @@
     field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1
     field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2
     field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+    field public static final int REQUESTED_PERMISSION_IMPLICIT = 4; // 0x4
     field public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 65536; // 0x10000
     field public android.content.pm.ActivityInfo[] activities;
     field public android.content.pm.ApplicationInfo applicationInfo;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 90b7828..e86d2f3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -43,9 +43,9 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Message;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -72,10 +72,7 @@
 import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
 import com.android.internal.inputmethod.RemoteAccessibilityInputConnection;
-import com.android.internal.os.HandlerCaller;
-import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -2634,7 +2631,7 @@
      */
     @Override
     public final IBinder onBind(Intent intent) {
-        return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
+        return new IAccessibilityServiceClientWrapper(this, getMainExecutor(), new Callbacks() {
             @Override
             public void onServiceConnected() {
                 AccessibilityService.this.dispatchServiceConnected();
@@ -2751,30 +2748,12 @@
      *
      * @hide
      */
-    public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
-            implements HandlerCaller.Callback {
-        private static final int DO_INIT = 1;
-        private static final int DO_ON_INTERRUPT = 2;
-        private static final int DO_ON_ACCESSIBILITY_EVENT = 3;
-        private static final int DO_ON_GESTURE = 4;
-        private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
-        private static final int DO_ON_KEY_EVENT = 6;
-        private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
-        private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
-        private static final int DO_GESTURE_COMPLETE = 9;
-        private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
-        private static final int DO_ON_FINGERPRINT_GESTURE = 11;
-        private static final int DO_ACCESSIBILITY_BUTTON_CLICKED = 12;
-        private static final int DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 13;
-        private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14;
-        private static final int DO_CREATE_IME_SESSION = 15;
-        private static final int DO_SET_IME_SESSION_ENABLED = 16;
-        private static final int DO_START_INPUT = 19;
-
-        private final HandlerCaller mCaller;
+    public static class IAccessibilityServiceClientWrapper extends
+            IAccessibilityServiceClient.Stub {
 
         private final Callbacks mCallback;
         private final Context mContext;
+        private final Executor mExecutor;
 
         private int mConnectionId = AccessibilityInteractionClient.NO_ID;
 
@@ -2793,103 +2772,199 @@
         @Nullable
         CancellationGroup mCancellationGroup = null;
 
+        public IAccessibilityServiceClientWrapper(Context context, Executor executor,
+                Callbacks callback) {
+            mCallback = callback;
+            mContext = context;
+            mExecutor = executor;
+        }
+
         public IAccessibilityServiceClientWrapper(Context context, Looper looper,
                 Callbacks callback) {
             mCallback = callback;
             mContext = context;
-            mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
+            mExecutor = new HandlerExecutor(new Handler(looper));
         }
 
         public void init(IAccessibilityServiceConnection connection, int connectionId,
                 IBinder windowToken) {
-            Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId,
-                    connection, windowToken);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                mConnectionId = connectionId;
+                if (connection != null) {
+                    AccessibilityInteractionClient.getInstance(mContext).addConnection(
+                            mConnectionId, connection, /*initializeCache=*/true);
+                    if (mContext != null) {
+                        try {
+                            connection.setAttributionTag(mContext.getAttributionTag());
+                        } catch (RemoteException re) {
+                            Log.w(LOG_TAG, "Error while setting attributionTag", re);
+                            re.rethrowFromSystemServer();
+                        }
+                    }
+                    mCallback.init(mConnectionId, windowToken);
+                    mCallback.onServiceConnected();
+                } else {
+                    AccessibilityInteractionClient.getInstance(mContext)
+                            .clearCache(mConnectionId);
+                    AccessibilityInteractionClient.getInstance(mContext).removeConnection(
+                            mConnectionId);
+                    mConnectionId = AccessibilityInteractionClient.NO_ID;
+                    mCallback.init(AccessibilityInteractionClient.NO_ID, null);
+                }
+                return;
+            });
         }
 
         public void onInterrupt() {
-            Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onInterrupt();
+                }
+            });
         }
 
         public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
-            Message message = mCaller.obtainMessageBO(
-                    DO_ON_ACCESSIBILITY_EVENT, serviceWantsEvent, event);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (event != null) {
+                    // Send the event to AccessibilityCache via AccessibilityInteractionClient
+                    AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
+                            event, mConnectionId);
+                    if (serviceWantsEvent
+                            && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
+                        // Send the event to AccessibilityService
+                        mCallback.onAccessibilityEvent(event);
+                    }
+                }
+                return;
+            });
         }
 
         @Override
         public void onGesture(AccessibilityGestureEvent gestureInfo) {
-            Message message = mCaller.obtainMessageO(DO_ON_GESTURE, gestureInfo);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onGesture(gestureInfo);
+                }
+                return;
+            });
         }
 
         public void clearAccessibilityCache() {
-            Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_CACHE);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
+                return;
+            });
         }
 
         @Override
         public void onKeyEvent(KeyEvent event, int sequence) {
-            Message message = mCaller.obtainMessageIO(DO_ON_KEY_EVENT, sequence, event);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                try {
+                    IAccessibilityServiceConnection connection = AccessibilityInteractionClient
+                            .getInstance(mContext).getConnection(mConnectionId);
+                    if (connection != null) {
+                        final boolean result = mCallback.onKeyEvent(event);
+                        try {
+                            connection.setOnKeyEventResult(result, sequence);
+                        } catch (RemoteException re) {
+                            /* ignore */
+                        }
+                    }
+                } finally {
+                    // Make sure the event is recycled.
+                    try {
+                        event.recycle();
+                    } catch (IllegalStateException ise) {
+                        /* ignore - best effort */
+                    }
+                }
+                return;
+            });
         }
 
         /** Magnification changed callbacks for different displays */
         public void onMagnificationChanged(int displayId, @NonNull Region region,
                 MagnificationConfig config) {
-            final SomeArgs args = SomeArgs.obtain();
-            args.arg1 = region;
-            args.arg2 = config;
-            args.argi1 = displayId;
-
-            final Message message = mCaller.obtainMessageO(DO_ON_MAGNIFICATION_CHANGED, args);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onMagnificationChanged(displayId, region, config);
+                }
+                return;
+            });
         }
 
         public void onSoftKeyboardShowModeChanged(int showMode) {
-          final Message message =
-                  mCaller.obtainMessageI(DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED, showMode);
-          mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onSoftKeyboardShowModeChanged(showMode);
+                }
+                return;
+            });
         }
 
         public void onPerformGestureResult(int sequence, boolean successfully) {
-            Message message = mCaller.obtainMessageII(DO_GESTURE_COMPLETE, sequence,
-                    successfully ? 1 : 0);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onPerformGestureResult(sequence, successfully);
+                }
+                return;
+            });
         }
 
         public void onFingerprintCapturingGesturesChanged(boolean active) {
-            mCaller.sendMessage(mCaller.obtainMessageI(
-                    DO_ON_FINGERPRINT_ACTIVE_CHANGED, active ? 1 : 0));
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onFingerprintCapturingGesturesChanged(active);
+                }
+                return;
+            });
         }
 
         public void onFingerprintGesture(int gesture) {
-            mCaller.sendMessage(mCaller.obtainMessageI(DO_ON_FINGERPRINT_GESTURE, gesture));
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onFingerprintGesture(gesture);
+                }
+                return;
+            });
         }
 
         /** Accessibility button clicked callbacks for different displays */
         public void onAccessibilityButtonClicked(int displayId) {
-            final Message message = mCaller.obtainMessageI(DO_ACCESSIBILITY_BUTTON_CLICKED,
-                    displayId);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onAccessibilityButtonClicked(displayId);
+                }
+                return;
+            });
         }
 
         public void onAccessibilityButtonAvailabilityChanged(boolean available) {
-            final Message message = mCaller.obtainMessageI(
-                    DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, (available ? 1 : 0));
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onAccessibilityButtonAvailabilityChanged(available);
+                }
+                return;
+            });
         }
 
         /** This is called when the system action list is changed. */
         public void onSystemActionsChanged() {
-            mCaller.sendMessage(mCaller.obtainMessage(DO_ON_SYSTEM_ACTIONS_CHANGED));
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.onSystemActionsChanged();
+                }
+                return;
+            });
         }
 
         /** This is called when an app requests ime sessions or when the service is enabled. */
         public void createImeSession(IAccessibilityInputMethodSessionCallback callback) {
-            final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    mCallback.createImeSession(callback);
+                }
+            });
         }
 
         /**
@@ -2905,8 +2980,12 @@
                     Log.w(LOG_TAG, "Session is already finished: " + session);
                     return;
                 }
-                mCaller.sendMessage(mCaller.obtainMessageIO(
-                        DO_SET_IME_SESSION_ENABLED, enabled ? 1 : 0, ls));
+                mExecutor.execute(() -> {
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        ls.setEnabled(enabled);
+                    }
+                    return;
+                });
             } catch (ClassCastException e) {
                 Log.w(LOG_TAG, "Incoming session not of correct type: " + session, e);
             }
@@ -2938,213 +3017,29 @@
                 Log.e(LOG_TAG, "startInput must be called after bindInput.");
                 mCancellationGroup = new CancellationGroup();
             }
-            final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, null /* unused */,
-                    connection, editorInfo, mCancellationGroup, restarting ? 1 : 0,
-                    0 /* unused */);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                    final RemoteAccessibilityInputConnection ic = connection == null ? null
+                            : new RemoteAccessibilityInputConnection(
+                                    connection, mCancellationGroup);
+                    editorInfo.makeCompatible(mContext.getApplicationInfo().targetSdkVersion);
+                    mCallback.startInput(ic, editorInfo, restarting);
+                }
+            });
         }
 
         @Override
         public void onMotionEvent(MotionEvent event) {
-            final Message message = PooledLambda.obtainMessage(
-                            Callbacks::onMotionEvent, mCallback, event);
-            mCaller.sendMessage(message);
+            mExecutor.execute(() -> {
+                mCallback.onMotionEvent(event);
+            });
         }
 
         @Override
         public void onTouchStateChanged(int displayId, int state) {
-            final Message message = PooledLambda.obtainMessage(Callbacks::onTouchStateChanged,
-                    mCallback,
-                    displayId, state);
-            mCaller.sendMessage(message);
-        }
-
-        @Override
-        public void executeMessage(Message message) {
-            switch (message.what) {
-                case DO_ON_ACCESSIBILITY_EVENT: {
-                    AccessibilityEvent event = (AccessibilityEvent) message.obj;
-                    boolean serviceWantsEvent = message.arg1 != 0;
-                    if (event != null) {
-                        // Send the event to AccessibilityCache via AccessibilityInteractionClient
-                        AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
-                                event, mConnectionId);
-                        if (serviceWantsEvent
-                                && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
-                            // Send the event to AccessibilityService
-                            mCallback.onAccessibilityEvent(event);
-                        }
-                        // Make sure the event is recycled.
-                        try {
-                            event.recycle();
-                        } catch (IllegalStateException ise) {
-                            /* ignore - best effort */
-                        }
-                    }
-                    return;
-                }
-                case DO_ON_INTERRUPT: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onInterrupt();
-                    }
-                    return;
-                }
-                case DO_INIT: {
-                    mConnectionId = message.arg1;
-                    SomeArgs args = (SomeArgs) message.obj;
-                    IAccessibilityServiceConnection connection =
-                            (IAccessibilityServiceConnection) args.arg1;
-                    IBinder windowToken = (IBinder) args.arg2;
-                    args.recycle();
-                    if (connection != null) {
-                        AccessibilityInteractionClient.getInstance(mContext).addConnection(
-                                mConnectionId, connection, /*initializeCache=*/true);
-                        if (mContext != null) {
-                            try {
-                                connection.setAttributionTag(mContext.getAttributionTag());
-                            } catch (RemoteException re) {
-                                Log.w(LOG_TAG, "Error while setting attributionTag", re);
-                                re.rethrowFromSystemServer();
-                            }
-                        }
-                        mCallback.init(mConnectionId, windowToken);
-                        mCallback.onServiceConnected();
-                    } else {
-                        AccessibilityInteractionClient.getInstance(mContext)
-                                .clearCache(mConnectionId);
-                        AccessibilityInteractionClient.getInstance(mContext).removeConnection(
-                                mConnectionId);
-                        mConnectionId = AccessibilityInteractionClient.NO_ID;
-                        mCallback.init(AccessibilityInteractionClient.NO_ID, null);
-                    }
-                    return;
-                }
-                case DO_ON_GESTURE: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onGesture((AccessibilityGestureEvent) message.obj);
-                    }
-                    return;
-                }
-                case DO_CLEAR_ACCESSIBILITY_CACHE: {
-                    AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
-                    return;
-                }
-                case DO_ON_KEY_EVENT: {
-                    KeyEvent event = (KeyEvent) message.obj;
-                    try {
-                        IAccessibilityServiceConnection connection = AccessibilityInteractionClient
-                                .getInstance(mContext).getConnection(mConnectionId);
-                        if (connection != null) {
-                            final boolean result = mCallback.onKeyEvent(event);
-                            final int sequence = message.arg1;
-                            try {
-                                connection.setOnKeyEventResult(result, sequence);
-                            } catch (RemoteException re) {
-                                /* ignore */
-                            }
-                        }
-                    } finally {
-                        // Make sure the event is recycled.
-                        try {
-                            event.recycle();
-                        } catch (IllegalStateException ise) {
-                            /* ignore - best effort */
-                        }
-                    }
-                    return;
-                }
-                case DO_ON_MAGNIFICATION_CHANGED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        final SomeArgs args = (SomeArgs) message.obj;
-                        final Region region = (Region) args.arg1;
-                        final MagnificationConfig config = (MagnificationConfig) args.arg2;
-                        final int displayId = args.argi1;
-                        args.recycle();
-                        mCallback.onMagnificationChanged(displayId, region, config);
-                    }
-                    return;
-                }
-                case DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        final int showMode = (int) message.arg1;
-                        mCallback.onSoftKeyboardShowModeChanged(showMode);
-                    }
-                    return;
-                }
-                case DO_GESTURE_COMPLETE: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        final boolean successfully = message.arg2 == 1;
-                        mCallback.onPerformGestureResult(message.arg1, successfully);
-                    }
-                    return;
-                }
-                case DO_ON_FINGERPRINT_ACTIVE_CHANGED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onFingerprintCapturingGesturesChanged(message.arg1 == 1);
-                    }
-                    return;
-                }
-                case DO_ON_FINGERPRINT_GESTURE: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onFingerprintGesture(message.arg1);
-                    }
-                    return;
-                }
-                case DO_ACCESSIBILITY_BUTTON_CLICKED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onAccessibilityButtonClicked(message.arg1);
-                    }
-                    return;
-                }
-                case DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        final boolean available = (message.arg1 != 0);
-                        mCallback.onAccessibilityButtonAvailabilityChanged(available);
-                    }
-                    return;
-                }
-                case DO_ON_SYSTEM_ACTIONS_CHANGED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        mCallback.onSystemActionsChanged();
-                    }
-                    return;
-                }
-                case DO_CREATE_IME_SESSION: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        IAccessibilityInputMethodSessionCallback callback =
-                                (IAccessibilityInputMethodSessionCallback) message.obj;
-                        mCallback.createImeSession(callback);
-                    }
-                    return;
-                }
-                case DO_SET_IME_SESSION_ENABLED: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        AccessibilityInputMethodSession session =
-                                (AccessibilityInputMethodSession) message.obj;
-                        session.setEnabled(message.arg1 != 0);
-                    }
-                    return;
-                }
-                case DO_START_INPUT: {
-                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
-                        final SomeArgs args = (SomeArgs) message.obj;
-                        final IRemoteAccessibilityInputConnection connection =
-                                (IRemoteAccessibilityInputConnection) args.arg2;
-                        final EditorInfo info = (EditorInfo) args.arg3;
-                        final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
-                        final boolean restarting = args.argi5 == 1;
-                        final RemoteAccessibilityInputConnection ic = connection == null ? null
-                                : new RemoteAccessibilityInputConnection(
-                                        connection, cancellationGroup);
-                        info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion);
-                        mCallback.startInput(ic, info, restarting);
-                        args.recycle();
-                    }
-                    return;
-                }
-                default:
-                    Log.w(LOG_TAG, "Unknown message type " + message.what);
-            }
+            mExecutor.execute(() -> {
+                mCallback.onTouchStateChanged(displayId, state);
+            });
         }
     }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e25e374..449729e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -5124,7 +5124,7 @@
         Preconditions.checkNotNull(listener);
         Preconditions.checkNotNull(executor);
         try {
-            listener.init(mContext, executor, this);
+            listener.init(mContext, executor);
             getService().registerProcessObserver(listener.mObserver);
             // Notify upon first registration.
             executor.execute(() ->
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b383d7d..6b3dc82 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -107,6 +107,7 @@
 import android.net.Proxy;
 import android.net.TrafficStats;
 import android.net.Uri;
+import android.net.wifi.WifiFrameworkInitializer;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.BluetoothServiceManager;
@@ -7900,6 +7901,8 @@
         BluetoothFrameworkInitializer.setBluetoothServiceManager(new BluetoothServiceManager());
         BluetoothFrameworkInitializer.setBinderCallsStatsInitializer(context -> {
             BinderCallsStats.startForBluetooth(context); });
+        WifiFrameworkInitializer.setBinderCallsStatsInitializer(context -> {
+            BinderCallsStats.startForWifi(context); });
     }
 
     private void purgePendingResources() {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 57dacd0..877e7d3 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -263,11 +263,6 @@
         // After orientation change, the onResume can come in before the top Activity has
         // left, so if the Activity is not top, wait a second for the top Activity to exit.
         if (mEnterTransitionCoordinator == null || activity.isTopOfTask()) {
-            if (mEnterTransitionCoordinator != null) {
-                mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> {
-                    mEnterTransitionCoordinator = null;
-                });
-            }
             restoreExitedViews();
             restoreReenteringViews();
         } else {
@@ -276,11 +271,6 @@
                 public void run() {
                     if (mEnterTransitionCoordinator == null ||
                             mEnterTransitionCoordinator.isWaitingForRemoteExit()) {
-                        if (mEnterTransitionCoordinator != null) {
-                            mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> {
-                                mEnterTransitionCoordinator = null;
-                            });
-                        }
                         restoreExitedViews();
                         restoreReenteringViews();
                     } else if (mEnterTransitionCoordinator.isReturning()) {
diff --git a/core/java/android/app/GameManagerInternal.java b/core/java/android/app/GameManagerInternal.java
new file mode 100644
index 0000000..c8ff2a8
--- /dev/null
+++ b/core/java/android/app/GameManagerInternal.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 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.app;
+
+/**
+ * Game manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+
+public abstract class GameManagerInternal {
+    /**
+     * Used by the CompatModePackages to read game's compat scaling override.
+     */
+    public abstract float getResolutionScalingFactor(String packageName, int userId);
+}
diff --git a/core/java/android/app/HomeVisibilityListener.java b/core/java/android/app/HomeVisibilityListener.java
index 57d868b..ca20648 100644
--- a/core/java/android/app/HomeVisibilityListener.java
+++ b/core/java/android/app/HomeVisibilityListener.java
@@ -16,16 +16,17 @@
 
 package android.app;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.content.ComponentName;
 import android.content.Context;
 import android.os.Binder;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -39,20 +40,21 @@
 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
 @TestApi
 public abstract class HomeVisibilityListener {
-    private Context mContext;
-    private ActivityManager mActivityManager;
+    private ActivityTaskManager mActivityTaskManager;
     private Executor mExecutor;
+    private int mMaxScanTasksForHomeVisibility;
     /** @hide */
     android.app.IProcessObserver.Stub mObserver;
     /** @hide */
     boolean mIsHomeActivityVisible;
 
     /** @hide */
-    void init(Context context, Executor executor, ActivityManager activityManager) {
-        mContext = context;
-        mActivityManager = activityManager;
-        mIsHomeActivityVisible = isHomeActivityVisible();
+    void init(Context context, Executor executor) {
+        mActivityTaskManager = ActivityTaskManager.getInstance();
         mExecutor = executor;
+        mMaxScanTasksForHomeVisibility = context.getResources().getInteger(
+                com.android.internal.R.integer.config_maxScanTasksForHomeVisibility);
+        mIsHomeActivityVisible = isHomeActivityVisible();
     }
 
     /**
@@ -91,22 +93,21 @@
     }
 
     private boolean isHomeActivityVisible() {
-        List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
-        if (tasks == null || tasks.isEmpty()) {
+        List<ActivityManager.RunningTaskInfo> tasksTopToBottom = mActivityTaskManager.getTasks(
+                mMaxScanTasksForHomeVisibility, /* filterOnlyVisibleRecents= */ true,
+                /* keepIntentExtra= */ false, DEFAULT_DISPLAY);
+        if (tasksTopToBottom == null || tasksTopToBottom.isEmpty()) {
             return false;
         }
 
-        String top = tasks.get(0).topActivity.getPackageName();
-        if (top == null) {
-            return false;
+        for (int i = 0, taskSize = tasksTopToBottom.size(); i < taskSize; ++i) {
+            ActivityManager.RunningTaskInfo task = tasksTopToBottom.get(i);
+            if (!task.isVisible()
+                    || (task.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0) {
+                continue;
+            }
+            return task.getActivityType() == ACTIVITY_TYPE_HOME;
         }
-
-        // We can assume that the screen is idle if the home application is in the foreground.
-        ComponentName defaultHomeComponent = mContext.getPackageManager()
-                .getHomeActivities(new ArrayList<>());
-        if (defaultHomeComponent == null) return false;
-
-        String defaultHomePackage = defaultHomeComponent.getPackageName();
-        return Objects.equals(top, defaultHomePackage);
+        return false;
     }
 }
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index e60a74a..481e7b0 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -31,4 +31,6 @@
     void setGameState(String packageName, in GameState gameState, int userId);
     GameModeInfo getGameModeInfo(String packageName, int userId);
     void setGameServiceProvider(String packageName);
+    void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor, int userId);
+    float getResolutionScalingFactor(String packageName, int gameMode, int userId);
 }
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 58ddd49..13934e5 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -310,6 +310,21 @@
     public static final String MODULE_TELEPHONY = "telephony";
 
     /**
+     * Constants that affect retries when the process is unable to write the property.
+     * The first constant is the number of times the process will attempt to set the
+     * property.  The second constant is the delay between attempts.
+     */
+
+    /**
+     * Wait 200ms between retry attempts and the retry limit is 5.  That gives a total possible
+     * delay of 1s, which should be less than ANR timeouts.  The goal is to have the system crash
+     * because the property could not be set (which is a condition that is easily recognized) and
+     * not crash because of an ANR (which can be confusing to debug).
+     */
+    private static final int PROPERTY_FAILURE_RETRY_DELAY_MILLIS = 200;
+    private static final int PROPERTY_FAILURE_RETRY_LIMIT = 5;
+
+    /**
      * Construct a system property that matches the rules described above.  The module is
      * one of the permitted values above.  The API is a string that is a legal Java simple
      * identifier.  The api is modified to conform to the system property style guide by
@@ -670,7 +685,33 @@
                 }
             }
         }
-        SystemProperties.set(name, Long.toString(val));
+        RuntimeException failure = null;
+        for (int attempt = 0; attempt < PROPERTY_FAILURE_RETRY_LIMIT; attempt++) {
+            try {
+                SystemProperties.set(name, Long.toString(val));
+                if (attempt > 0) {
+                    // This log is not guarded.  Based on known bug reports, it should
+                    // occur once a week or less.  The purpose of the log message is to
+                    // identify the retries as a source of delay that might be otherwise
+                    // be attributed to the cache itself.
+                    Log.w(TAG, "Nonce set after " + attempt + " tries");
+                }
+                return;
+            } catch (RuntimeException e) {
+                if (failure == null) {
+                    failure = e;
+                }
+                try {
+                    Thread.sleep(PROPERTY_FAILURE_RETRY_DELAY_MILLIS);
+                } catch (InterruptedException x) {
+                    // Ignore this exception.  The desired delay is only approximate and
+                    // there is no issue if the sleep sometimes terminates early.
+                }
+            }
+        }
+        // This point is reached only if SystemProperties.set() fails at least once.
+        // Rethrow the first exception that was received.
+        throw failure;
     }
 
     // Set the nonce in a static context.  No handle is available.
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8be2b48..e3bca9c 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -103,7 +103,6 @@
     private boolean mOnLightBackground;
     private SizeF mCurrentSize = null;
     private RemoteViews.ColorResources mColorResources = null;
-    private SparseIntArray mColorMapping = null;
     // Stores the last remote views last inflated.
     private RemoteViews mLastInflatedRemoteViews = null;
     private long mLastInflatedRemoteViewsId = -1;
@@ -900,11 +899,19 @@
      * {@link android.R.color#system_neutral1_500}.
      */
     public void setColorResources(@NonNull SparseIntArray colorMapping) {
-        if (mColorMapping != null && isSameColorMapping(mColorMapping, colorMapping)) {
+        if (mColorResources != null
+                && isSameColorMapping(mColorResources.getColorMapping(), colorMapping)) {
             return;
         }
-        mColorMapping = colorMapping.clone();
-        mColorResources = RemoteViews.ColorResources.create(mContext, mColorMapping);
+        setColorResources(RemoteViews.ColorResources.create(mContext, colorMapping));
+    }
+
+    /** @hide **/
+    public void setColorResources(RemoteViews.ColorResources colorResources) {
+        if (colorResources == mColorResources) {
+            return;
+        }
+        mColorResources = colorResources;
         mColorMappingChanged = true;
         mViewMode = VIEW_MODE_NOINIT;
         reapplyLastRemoteViews();
@@ -934,7 +941,6 @@
     public void resetColorResources() {
         if (mColorResources != null) {
             mColorResources = null;
-            mColorMapping = null;
             mColorMappingChanged = true;
             mViewMode = VIEW_MODE_NOINIT;
             reapplyLastRemoteViews();
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 0c171ad..da486ee 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -19,7 +19,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.os.Process.myUserHandle;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_DATABASE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -278,7 +278,7 @@
                 // Return an empty cursor for all columns.
                 return new MatrixCursor(cursor.getColumnNames(), 0);
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "query: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -289,7 +289,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -298,13 +298,13 @@
             // getCallingPackage() isn't available in getType(), as the javadoc states.
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getType: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
             try {
                 return mInterface.getType(uri);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -336,7 +336,7 @@
                     setCallingAttributionSource(original);
                 }
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "insert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -345,7 +345,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -358,7 +358,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "bulkInsert: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -367,7 +367,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -404,7 +404,7 @@
                     }
                 }
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "applyBatch: ", authority);
+            traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -423,7 +423,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -436,7 +436,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "delete: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -445,7 +445,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -458,7 +458,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return 0;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "update: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -467,7 +467,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -478,7 +478,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -488,7 +488,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -499,7 +499,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, mode);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -509,7 +509,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -518,7 +518,7 @@
                 String method, @Nullable String arg, @Nullable Bundle extras) {
             validateIncomingAuthority(authority);
             Bundle.setDefusable(extras, true);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "call: ", authority);
+            traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -527,7 +527,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -536,13 +536,13 @@
             // getCallingPackage() isn't available in getType(), as the javadoc states.
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getStreamTypes: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
             try {
                 return mInterface.getStreamTypes(uri, mimeTypeFilter);
             } catch (RemoteException e) {
                 throw e.rethrowAsRuntimeException();
             } finally {
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -554,7 +554,7 @@
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             enforceFilePermission(attributionSource, uri, "r");
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openTypedAssetFile: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -564,7 +564,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -582,7 +582,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "canonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -591,7 +591,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -618,7 +618,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return null;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "uncanonicalize: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -627,7 +627,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -654,7 +654,7 @@
                     != PermissionChecker.PERMISSION_GRANTED) {
                 return false;
             }
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "refresh: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -662,7 +662,7 @@
                         CancellationSignal.fromTransport(cancellationSignal));
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
@@ -671,7 +671,7 @@
                 int uid, int modeFlags) {
             uri = validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
-            traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "checkUriPermission: ", uri.getAuthority());
+            traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
             final AttributionSource original = setCallingAttributionSource(
                     attributionSource);
             try {
@@ -680,7 +680,7 @@
                 throw e.rethrowAsRuntimeException();
             } finally {
                 setCallingAttributionSource(original);
-                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+                Trace.traceEnd(TRACE_TAG_DATABASE);
             }
         }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 26b2f07..0e0b2dc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -11051,10 +11051,7 @@
         if (!Objects.equals(this.mData, other.mData)) return false;
         if (!Objects.equals(this.mType, other.mType)) return false;
         if (!Objects.equals(this.mIdentifier, other.mIdentifier)) return false;
-        if (!(this.hasPackageEquivalentComponent() && other.hasPackageEquivalentComponent())
-                && !Objects.equals(this.mPackage, other.mPackage)) {
-            return false;
-        }
+        if (!Objects.equals(this.mPackage, other.mPackage)) return false;
         if (!Objects.equals(this.mComponent, other.mComponent)) return false;
         if (!Objects.equals(this.mCategories, other.mCategories)) return false;
 
@@ -11062,15 +11059,6 @@
     }
 
     /**
-     * Return {@code true} if the component name is not null and is in the same package that this
-     * intent limited to. otherwise return {@code false}.
-     */
-    private boolean hasPackageEquivalentComponent() {
-        return mComponent != null
-            && (mPackage == null || mPackage.equals(mComponent.getPackageName()));
-    }
-
-    /**
      * Generate hash code that matches semantics of filterEquals().
      *
      * @return Returns the hash value of the action, data, type, class, and
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 9708493..4259600 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -252,6 +252,13 @@
     public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 0x00010000;
 
     /**
+     * Flag for {@link #requestedPermissionsFlags}: the requested permission was
+     * not explicitly requested via uses-permission, but was instead implicitly
+     * requested (e.g., for version compatibility reasons).
+     */
+    public static final int REQUESTED_PERMISSION_IMPLICIT = 0x00000004;
+
+    /**
      * Array of all signatures read from the package file. This is only filled
      * in if the flag {@link PackageManager#GET_SIGNATURES} was set. A package
      * must be signed with at least one certificate which is at position zero.
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 0848697..6ed87fff 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -81,7 +81,7 @@
      *
      * @param clientProxy the proxy of the client at the service
      */
-    /* package */ void setClientProxy(IContextHubClient clientProxy) {
+    /* package */ synchronized void setClientProxy(IContextHubClient clientProxy) {
         Objects.requireNonNull(clientProxy, "IContextHubClient cannot be null");
         if (mClientProxy != null) {
             throw new IllegalStateException("Cannot change client proxy multiple times");
@@ -93,6 +93,7 @@
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
+        this.notifyAll();
     }
 
     /**
@@ -221,8 +222,15 @@
     }
 
     /** @hide */
-    public void callbackFinished() {
+    public synchronized void callbackFinished() {
         try {
+            while (mClientProxy == null) {
+                try {
+                    this.wait();
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
             mClientProxy.callbackFinished();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 0418a4b..87579eb 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -29,6 +29,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
 
 import java.io.Serializable;
 import java.lang.ref.WeakReference;
@@ -113,17 +114,21 @@
      */
     private boolean mParcelledByNative;
 
-    /*
+    /**
      * Flag indicating if mParcelledData is only referenced in this bundle.
-     * mParcelledData could be referenced by other bundles if mMap contains lazy values,
+     * mParcelledData could be referenced elsewhere if mMap contains lazy values,
      * and bundle data is copied to another bundle using putAll or the copy constructors.
      */
     boolean mOwnsLazyValues = true;
 
-    /*
+    /** Tracks how many lazy values are referenced in mMap */
+    private int mLazyValues = 0;
+
+    /**
      * As mParcelledData is set to null when it is unparcelled, we keep a weak reference to
      * it to aid in recycling it. Do not use this reference otherwise.
-     */
+     * Is non-null iff mMap contains lazy values.
+    */
     private WeakReference<Parcel> mWeakParcelledData = null;
 
     /**
@@ -310,7 +315,8 @@
         synchronized (this) {
             final Parcel source = mParcelledData;
             if (source != null) {
-                initializeFromParcelLocked(source, /*recycleParcel=*/ true, mParcelledByNative);
+                Preconditions.checkState(mOwnsLazyValues);
+                initializeFromParcelLocked(source, /*ownsParcel*/ true, mParcelledByNative);
             } else {
                 if (DEBUG) {
                     Log.d(TAG, "unparcel "
@@ -401,11 +407,23 @@
                 }
             }
             mMap.setValueAt(i, object);
+            mLazyValues--;
+            if (mOwnsLazyValues) {
+                Preconditions.checkState(mLazyValues >= 0, "Lazy values ref count below 0");
+                // No more lazy values in mMap, so we can recycle the parcel early rather than
+                // waiting for the next GC run
+                if (mLazyValues == 0) {
+                    Preconditions.checkState(mWeakParcelledData.get() != null,
+                            "Parcel recycled earlier than expected");
+                    recycleParcel(mWeakParcelledData.get());
+                    mWeakParcelledData = null;
+                }
+            }
         }
         return (clazz != null) ? clazz.cast(object) : (T) object;
     }
 
-    private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel,
+    private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean ownsParcel,
             boolean parcelledByNative) {
         if (isEmptyParcel(parcelledData)) {
             if (DEBUG) {
@@ -437,9 +455,10 @@
             map.erase();
             map.ensureCapacity(count);
         }
+        int numLazyValues = 0;
         try {
-            recycleParcel &= parcelledData.readArrayMap(map, count, !parcelledByNative,
-                    /* lazy */ true, mClassLoader);
+            numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
+                    /* lazy */ ownsParcel, mClassLoader);
         } catch (BadParcelableException e) {
             if (sShouldDefuse) {
                 Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -448,14 +467,19 @@
                 throw e;
             }
         } finally {
-            mMap = map;
-            if (recycleParcel) {
-                recycleParcel(parcelledData);
-                mWeakParcelledData = null;
-            } else {
-                mWeakParcelledData = new WeakReference<>(parcelledData);
+            mWeakParcelledData = null;
+            if (ownsParcel) {
+                if (numLazyValues == 0) {
+                    recycleParcel(parcelledData);
+                } else {
+                    mWeakParcelledData = new WeakReference<>(parcelledData);
+                }
             }
+
+            mLazyValues = numLazyValues;
             mParcelledByNative = false;
+            mMap = map;
+            // Set field last as it is volatile
             mParcelledData = null;
         }
         if (DEBUG) {
@@ -592,13 +616,17 @@
 
     /**
      * Removes all elements from the mapping of this Bundle.
+     * Recycles the underlying parcel if it is still present.
      */
     public void clear() {
         unparcel();
         if (mOwnsLazyValues && mWeakParcelledData != null) {
             recycleParcel(mWeakParcelledData.get());
-            mWeakParcelledData = null;
         }
+
+        mWeakParcelledData = null;
+        mLazyValues = 0;
+        mOwnsLazyValues = true;
         mMap.clear();
     }
 
@@ -1844,8 +1872,8 @@
             // had been constructed with parcel or to make sure they trigger deserialization of the
             // bundle immediately; neither of which is obvious.
             synchronized (this) {
-                initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle);
-                unparcel(/* itemwise */ true);
+                mOwnsLazyValues = false;
+                initializeFromParcelLocked(parcel, /*ownsParcel*/ false, isNativeBundle);
             }
             return;
         }
@@ -1862,6 +1890,7 @@
                 + ": " + length + " bundle bytes starting at " + offset);
         p.setDataPosition(0);
 
+        mOwnsLazyValues = true;
         mParcelledByNative = isNativeBundle;
         mParcelledData = p;
     }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d553132..80201d3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -71,7 +71,6 @@
 import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.IntFunction;
-import java.util.function.Supplier;
 
 /**
  * Container for a message (data and object references) that can
@@ -5242,20 +5241,20 @@
      * Reads a map into {@code map}.
      *
      * @param sorted Whether the keys are sorted by their hashes, if so we use an optimized path.
-     * @param lazy   Whether to populate the map with lazy {@link Supplier} objects for
+     * @param lazy   Whether to populate the map with lazy {@link Function} objects for
      *               length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
      *               details.
-     * @return whether the parcel can be recycled or not.
+     * @return a count of the lazy values in the map
      * @hide
      */
-    boolean readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+    int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
             boolean lazy, @Nullable ClassLoader loader) {
-        boolean recycle = true;
+        int lazyValues = 0;
         while (size > 0) {
             String key = readString();
             Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
             if (value instanceof LazyValue) {
-                recycle = false;
+                lazyValues++;
             }
             if (sorted) {
                 map.append(key, value);
@@ -5267,7 +5266,7 @@
         if (sorted) {
             map.validate();
         }
-        return recycle;
+        return lazyValues;
     }
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8d3509c..d14d2e4 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2838,6 +2838,26 @@
     }
 
     /**
+     * @hide
+     */
+    public static boolean isUsersOnSecondaryDisplaysEnabled() {
+        return SystemProperties.getBoolean("fw.users_on_secondary_displays",
+                Resources.getSystem()
+                        .getBoolean(R.bool.config_multiuserUsersOnSecondaryDisplays));
+    }
+
+    /**
+     * Returns whether the device allows users to run (and launch activities) on secondary displays.
+     *
+     * @return {@code false} for most devices, except automotive vehicles with passenger displays.
+     *
+     * @hide
+     */
+    public boolean isUsersOnSecondaryDisplaysSupported() {
+        return isUsersOnSecondaryDisplaysEnabled();
+    }
+
+    /**
      * Return whether the context user is running in an "unlocked" state.
      * <p>
      * On devices with direct boot, a user is unlocked only after they've
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9000899..6fc2811 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14257,7 +14257,7 @@
          *
          * @hide
          */
-        public static final int DEFAULT_ENABLE_TARE = 1;
+        public static final int DEFAULT_ENABLE_TARE = 0;
 
         /**
          * Whether to enable the TARE AlarmManager economic policy or not.
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index cce3e8c..a2cb1d5 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -733,7 +733,7 @@
         }
         for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
             // Only update the server side insets here.
-            if (type == ITYPE_CAPTION_BAR) continue;
+            if (!CAPTION_ON_SHELL && type == ITYPE_CAPTION_BAR) continue;
             InsetsSource source = mState.peekSource(type);
             if (source == null) continue;
             if (newState.peekSource(type) == null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e1966a0..84dadca 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -277,7 +277,7 @@
      * @hide
      */
     public static final boolean CAPTION_ON_SHELL =
-            SystemProperties.getBoolean("persist.debug.caption_on_shell", false);
+            SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", false);
 
     /**
      * Whether the client should compute the window frame on its own.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2879cd8..5eec054 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -594,8 +594,8 @@
      *  SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
      */
     private abstract static class Action implements Parcelable {
-        public abstract void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) throws ActionException;
+        public abstract void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+                throws ActionException;
 
         public static final int MERGE_REPLACE = 0;
         public static final int MERGE_APPEND = 1;
@@ -626,7 +626,7 @@
          * Override this if some of the tasks can be performed async.
          */
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             return this;
         }
 
@@ -661,9 +661,7 @@
     // Constant used during async execution. It is not parcelable.
     private static final Action ACTION_NOOP = new RuntimeAction() {
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
-        }
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) { }
     };
 
     /**
@@ -798,8 +796,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View view = root.findViewById(viewId);
             if (!(view instanceof AdapterView<?>)) return;
 
@@ -834,8 +831,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -846,7 +842,7 @@
                 OnItemClickListener listener = (parent, view, position, id) -> {
                     RemoteResponse response = findRemoteResponseTag(view);
                     if (response != null) {
-                        response.handleViewInteraction(view, handler);
+                        response.handleViewInteraction(view, params.handler);
                     }
                 };
                 av.setOnItemClickListener(listener);
@@ -910,8 +906,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -935,7 +930,7 @@
                     ((RemoteViewsListAdapter) a).setViewsList(list);
                 } else {
                     v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
-                            colorResources));
+                            params.colorResources));
                 }
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
@@ -944,7 +939,7 @@
                     ((RemoteViewsListAdapter) a).setViewsList(list);
                 } else {
                     v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
-                            colorResources));
+                            params.colorResources));
                 }
             }
         }
@@ -1025,8 +1020,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) throws ActionException {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+                throws ActionException {
             View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1053,7 +1048,7 @@
                     && adapter.getViewTypeCount() >= mItems.getViewTypeCount()) {
                 try {
                     ((RemoteCollectionItemsAdapter) adapter).setData(
-                            mItems, handler, colorResources);
+                            mItems, params.handler, params.colorResources);
                 } catch (Throwable throwable) {
                     // setData should never failed with the validation in the items builder, but if
                     // it does, catch and rethrow.
@@ -1063,8 +1058,8 @@
             }
 
             try {
-                adapterView.setAdapter(
-                        new RemoteCollectionItemsAdapter(mItems, handler, colorResources));
+                adapterView.setAdapter(new RemoteCollectionItemsAdapter(mItems,
+                        params.handler, params.colorResources));
             } catch (Throwable throwable) {
                 // This could throw if the AdapterView somehow doesn't accept BaseAdapter due to
                 // a type error.
@@ -1095,8 +1090,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1124,17 +1118,17 @@
             if (target instanceof AbsListView) {
                 AbsListView v = (AbsListView) target;
                 v.setRemoteViewsAdapter(intent, isAsync);
-                v.setRemoteViewsInteractionHandler(handler);
+                v.setRemoteViewsInteractionHandler(params.handler);
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
                 v.setRemoteViewsAdapter(intent, isAsync);
-                v.setRemoteViewsOnClickHandler(handler);
+                v.setRemoteViewsOnClickHandler(params.handler);
             }
         }
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             SetRemoteViewsAdapterIntent copy = new SetRemoteViewsAdapterIntent(viewId, intent);
             copy.isAsync = true;
             return copy;
@@ -1173,8 +1167,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1215,7 +1208,7 @@
                 target.setTagInternal(com.android.internal.R.id.fillInIntent, null);
                 return;
             }
-            target.setOnClickListener(v -> mResponse.handleViewInteraction(v, handler));
+            target.setOnClickListener(v -> mResponse.handleViewInteraction(v, params.handler));
         }
 
         @Override
@@ -1253,8 +1246,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
             if (!(target instanceof CompoundButton)) {
@@ -1287,7 +1279,7 @@
             }
 
             OnCheckedChangeListener onCheckedChangeListener =
-                    (v, isChecked) -> mResponse.handleViewInteraction(v, handler);
+                    (v, isChecked) -> mResponse.handleViewInteraction(v, params.handler);
             button.setTagInternal(R.id.remote_checked_change_listener_tag, onCheckedChangeListener);
             button.setOnCheckedChangeListener(onCheckedChangeListener);
         }
@@ -1459,8 +1451,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1517,8 +1508,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -1561,8 +1551,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View view = root.findViewById(viewId);
             if (view == null) return;
 
@@ -1675,12 +1664,12 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) throws ActionException {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+                throws ActionException {
             ReflectionAction ra = new ReflectionAction(viewId, methodName,
                     BaseReflectionAction.BITMAP,
                     bitmap);
-            ra.apply(root, rootParent, handler, colorResources);
+            ra.apply(root, rootParent, params);
         }
 
         @Override
@@ -1756,8 +1745,7 @@
         protected abstract Object getParameterValue(@Nullable View view) throws ActionException;
 
         @Override
-        public final void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public final void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View view = root.findViewById(viewId);
             if (view == null) return;
 
@@ -1775,7 +1763,7 @@
 
         @Override
         public final Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             final View view = root.findViewById(viewId);
             if (view == null) return ACTION_NOOP;
 
@@ -2307,8 +2295,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             mRunnable.run();
         }
     }
@@ -2421,8 +2408,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final Context context = root.getContext();
             final ViewGroup target = root.findViewById(viewId);
 
@@ -2451,8 +2437,7 @@
                             target.removeViews(nextChild, recycledViewIndex - nextChild);
                         }
                         setNextRecyclableChild(target, nextChild + 1, target.getChildCount());
-                        rvToApply.reapplyNestedViews(context, child, rootParent, handler,
-                                null /* size */, colorResources);
+                        rvToApply.reapplyNestedViews(context, child, rootParent, params);
                         return;
                     }
                     // If we cannot recycle the views, we still remove all views in between to
@@ -2463,8 +2448,7 @@
             // If we cannot recycle, insert the new view before the next recyclable child.
 
             // Inflate nested views and add as children
-            View nestedView = rvToApply.applyNestedViews(context, target, rootParent, handler,
-                    null /* size */, colorResources);
+            View nestedView = rvToApply.apply(context, target, rootParent, null /* size */, params);
             if (mStableId != NO_ID) {
                 setStableId(nestedView, mStableId);
             }
@@ -2477,7 +2461,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the current view.
             root.createTree();
@@ -2511,8 +2495,7 @@
                         setNextRecyclableChild(targetVg, nextChild + 1, target.mChildren.size());
                         final AsyncApplyTask reapplyTask = rvToApply.getInternalAsyncApplyTask(
                                 context,
-                                targetVg, null /* listener */, handler, null /* size */,
-                                colorResources,
+                                targetVg, null /* listener */, params, null /* size */,
                                 recycled.mRoot);
                         final ViewTree tree = reapplyTask.doInBackground();
                         if (tree == null) {
@@ -2521,8 +2504,7 @@
                         return new RuntimeAction() {
                             @Override
                             public void apply(View root, ViewGroup rootParent,
-                                    InteractionHandler handler, ColorResources colorResources)
-                                    throws ActionException {
+                                    ActionApplyParams params) throws ActionException {
                                 reapplyTask.onPostExecute(tree);
                                 if (recycledViewIndex > nextChild) {
                                     targetVg.removeViews(nextChild, recycledViewIndex - nextChild);
@@ -2533,23 +2515,22 @@
                     // If the layout id is different, still remove the children as if we recycled
                     // the view, to insert at the same place.
                     target.removeChildren(nextChild, recycledViewIndex - nextChild + 1);
-                    return insertNewView(context, target, handler, colorResources,
+                    return insertNewView(context, target, params,
                             () -> targetVg.removeViews(nextChild,
                                     recycledViewIndex - nextChild + 1));
 
                 }
             }
             // If we cannot recycle, simply add the view at the same available slot.
-            return insertNewView(context, target, handler, colorResources, () -> {});
+            return insertNewView(context, target, params, () -> {});
         }
 
-        private Action insertNewView(Context context, ViewTree target, InteractionHandler handler,
-                ColorResources colorResources, Runnable finalizeAction) {
+        private Action insertNewView(Context context, ViewTree target,
+                ActionApplyParams params, Runnable finalizeAction) {
             ViewGroup targetVg = (ViewGroup) target.mRoot;
             int nextChild = getNextRecyclableChild(targetVg);
             final AsyncApplyTask task = mNestedViews.getInternalAsyncApplyTask(context, targetVg,
-                    null /* listener */, handler, null /* size */, colorResources,
-                    null /* result */);
+                    null /* listener */, params, null /* size */,  null /* result */);
             final ViewTree tree = task.doInBackground();
 
             if (tree == null) {
@@ -2569,8 +2550,7 @@
 
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                        ColorResources colorResources) throws ActionException {
+                public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
                     task.onPostExecute(tree);
                     finalizeAction.run();
                     targetVg.addView(task.mResult, insertIndex);
@@ -2627,8 +2607,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final ViewGroup target = root.findViewById(viewId);
 
             if (target == null) {
@@ -2652,7 +2631,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the current view.
             root.createTree();
@@ -2676,8 +2655,7 @@
             }
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                        ColorResources colorResources) throws ActionException {
+                public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
                     if (mViewIdToKeep == REMOVE_ALL_VIEWS_ID) {
                         for (int i = targetVg.getChildCount() - 1; i >= 0; i--) {
                             if (!hasStableId(targetVg.getChildAt(i))) {
@@ -2736,8 +2714,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
 
             if (target == null || target == root) {
@@ -2752,7 +2729,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             // In the async implementation, update the view tree so that subsequent calls to
             // findViewById return the correct view.
             root.createTree();
@@ -2771,8 +2748,7 @@
             parent.mChildren.remove(target);
             return new RuntimeAction() {
                 @Override
-                public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                        ColorResources colorResources) throws ActionException {
+                public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
                     parentVg.removeView(target.mRoot);
                 }
             };
@@ -2851,8 +2827,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return;
             if (drawablesLoaded) {
@@ -2883,7 +2858,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent,
-                InteractionHandler handler, ColorResources colorResources) {
+                ActionApplyParams params) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return ACTION_NOOP;
 
@@ -2961,8 +2936,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final TextView target = root.findViewById(viewId);
             if (target == null) return;
             target.setTextSize(units, size);
@@ -3007,8 +2981,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
             target.setPadding(left, top, right, bottom);
@@ -3084,8 +3057,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) {
                 return;
@@ -3230,8 +3202,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -3266,8 +3237,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             // Let's traverse the viewtree and override all textColors!
             Stack<View> viewsToProcess = new Stack<>();
             viewsToProcess.add(root);
@@ -3317,8 +3287,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
             final View target = root.findViewById(mViewId);
             if (target == null) return;
 
@@ -3352,8 +3321,7 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources)
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
                 throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
@@ -3404,8 +3372,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) throws ActionException {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+                throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -3483,8 +3451,8 @@
         }
 
         @Override
-        public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
-                ColorResources colorResources) throws ActionException {
+        public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+                throws ActionException {
             final View target = root.findViewById(viewId);
             if (target == null) return;
 
@@ -5578,52 +5546,39 @@
     /** @hide */
     public View apply(@NonNull Context context, @NonNull ViewGroup parent,
             @Nullable InteractionHandler handler, @Nullable SizeF size) {
-        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
-        View result = inflateView(context, rvToApply, parent);
-        rvToApply.performApply(result, parent, handler, null);
-        return result;
+        return apply(context, parent, size, new ActionApplyParams()
+                .withInteractionHandler(handler));
     }
 
     /** @hide */
     public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
             @Nullable InteractionHandler handler, @StyleRes int applyThemeResId) {
-        return applyWithTheme(context, parent, handler, applyThemeResId, null);
-    }
-
-    /** @hide */
-    public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
-            @Nullable InteractionHandler handler, @StyleRes int applyThemeResId,
-            @Nullable SizeF size) {
-        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
-        View result = inflateView(context, rvToApply, parent, applyThemeResId, null);
-        rvToApply.performApply(result, parent, handler, null);
-        return result;
+        return apply(context, parent, null, new ActionApplyParams()
+                .withInteractionHandler(handler)
+                .withThemeResId(applyThemeResId));
     }
 
     /** @hide */
     public View apply(Context context, ViewGroup parent, InteractionHandler handler,
             @Nullable SizeF size, @Nullable ColorResources colorResources) {
-        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
-        View result = inflateView(context, rvToApply, parent, 0, colorResources);
-        rvToApply.performApply(result, parent, handler, colorResources);
-        return result;
+        return apply(context, parent, size, new ActionApplyParams()
+                .withInteractionHandler(handler)
+                .withColorResources(colorResources));
     }
 
-    private View applyNestedViews(Context context, ViewGroup directParent,
-            ViewGroup rootParent, InteractionHandler handler, SizeF size,
-            ColorResources colorResources) {
-        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
-        View result = inflateView(context, rvToApply, directParent, 0, colorResources);
-        rvToApply.performApply(result, rootParent, handler, colorResources);
-        return result;
+    /** @hide **/
+    public View apply(Context context, ViewGroup parent, @Nullable SizeF size,
+            ActionApplyParams params) {
+        return apply(context, parent, parent, size, params);
     }
 
-    private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
-        return inflateView(context, rv, parent, 0, null);
+    private View apply(Context context, ViewGroup directParent, ViewGroup rootParent,
+            @Nullable SizeF size, ActionApplyParams params) {
+        RemoteViews rvToApply = getRemoteViewsToApply(context, size);
+        View result = inflateView(context, rvToApply, directParent,
+                params.applyThemeResId, params.colorResources);
+        rvToApply.performApply(result, rootParent, params);
+        return result;
     }
 
     private View inflateView(Context context, RemoteViews rv, @Nullable ViewGroup parent,
@@ -5704,7 +5659,6 @@
         return applyAsync(context, parent, executor, listener, null /* handler */);
     }
 
-
     /** @hide */
     public CancellationSignal applyAsync(Context context, ViewGroup parent,
             Executor executor, OnViewAppliedListener listener, InteractionHandler handler) {
@@ -5723,16 +5677,19 @@
     public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
             OnViewAppliedListener listener, InteractionHandler handler, SizeF size,
             ColorResources colorResources) {
+
+        ActionApplyParams params = new ActionApplyParams()
+                .withInteractionHandler(handler)
+                .withColorResources(colorResources)
+                .withExecutor(executor);
         return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
-                handler, colorResources, null /* result */,
-                true /* topLevel */).startTaskOnExecutor(executor);
+                params, null /* result */, true /* topLevel */).startTaskOnExecutor(executor);
     }
 
     private AsyncApplyTask getInternalAsyncApplyTask(Context context, ViewGroup parent,
-            OnViewAppliedListener listener, InteractionHandler handler, SizeF size,
-            ColorResources colorResources, View result) {
+            OnViewAppliedListener listener, ActionApplyParams params, SizeF size, View result) {
         return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
-                handler, colorResources, result, false /* topLevel */);
+                params, result, false /* topLevel */);
     }
 
     private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
@@ -5742,8 +5699,8 @@
         final ViewGroup mParent;
         final Context mContext;
         final OnViewAppliedListener mListener;
-        final InteractionHandler mHandler;
-        final ColorResources mColorResources;
+        final ActionApplyParams mApplyParams;
+
         /**
          * Whether the remote view is the top-level one (i.e. not within an action).
          *
@@ -5758,16 +5715,13 @@
 
         private AsyncApplyTask(
                 RemoteViews rv, ViewGroup parent, Context context, OnViewAppliedListener listener,
-                InteractionHandler handler, ColorResources colorResources,
-                View result, boolean topLevel) {
+                ActionApplyParams applyParams, View result, boolean topLevel) {
             mRV = rv;
             mParent = parent;
             mContext = context;
             mListener = listener;
-            mColorResources = colorResources;
-            mHandler = handler;
             mTopLevel = topLevel;
-
+            mApplyParams = applyParams;
             mResult = result;
         }
 
@@ -5776,17 +5730,18 @@
         protected ViewTree doInBackground(Void... params) {
             try {
                 if (mResult == null) {
-                    mResult = inflateView(mContext, mRV, mParent, 0, mColorResources);
+                    mResult = inflateView(mContext, mRV, mParent, 0, mApplyParams.colorResources);
                 }
 
                 mTree = new ViewTree(mResult);
+
                 if (mRV.mActions != null) {
                     int count = mRV.mActions.size();
                     mActions = new Action[count];
                     for (int i = 0; i < count && !isCancelled(); i++) {
                         // TODO: check if isCancelled in nested views.
-                        mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler,
-                                mColorResources);
+                        mActions[i] = mRV.mActions.get(i)
+                                .initActionAsync(mTree, mParent, mApplyParams);
                     }
                 } else {
                     mActions = null;
@@ -5808,10 +5763,13 @@
 
                 try {
                     if (mActions != null) {
-                        InteractionHandler handler = mHandler == null
-                                ? DEFAULT_INTERACTION_HANDLER : mHandler;
+
+                        ActionApplyParams applyParams = mApplyParams.clone();
+                        if (applyParams.handler == null) {
+                            applyParams.handler = DEFAULT_INTERACTION_HANDLER;
+                        }
                         for (Action a : mActions) {
-                            a.apply(viewTree.mRoot, mParent, handler, mColorResources);
+                            a.apply(viewTree.mRoot, mParent, applyParams);
                         }
                     }
                     // If the parent of the view is has is a root, resolve the recycling.
@@ -5859,18 +5817,43 @@
      * the {@link #apply(Context,ViewGroup)} call.
      */
     public void reapply(Context context, View v) {
-        reapply(context, v, null /* handler */);
+        reapply(context, v, null /* size */, new ActionApplyParams());
     }
 
     /** @hide */
     public void reapply(Context context, View v, InteractionHandler handler) {
-        reapply(context, v, handler, null /* size */, null /* colorResources */);
+        reapply(context, v, null /* size */,
+                new ActionApplyParams().withInteractionHandler(handler));
     }
 
     /** @hide */
     public void reapply(Context context, View v, InteractionHandler handler, SizeF size,
             ColorResources colorResources) {
-        reapply(context, v, handler, size, colorResources, true);
+        reapply(context, v, size, new ActionApplyParams()
+                .withInteractionHandler(handler).withColorResources(colorResources));
+    }
+
+    /** @hide */
+    public void reapply(Context context, View v, @Nullable SizeF size, ActionApplyParams params) {
+        reapply(context, v, (ViewGroup) v.getParent(), size, params, true);
+    }
+
+    private void reapplyNestedViews(Context context, View v, ViewGroup rootParent,
+            ActionApplyParams params) {
+        reapply(context, v, rootParent, null, params, false);
+    }
+
+    // Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
+    // should set it to false.
+    private void reapply(Context context, View v, ViewGroup rootParent,
+            @Nullable SizeF size, ActionApplyParams params, boolean topLevel) {
+        RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
+        rvToApply.performApply(v, rootParent, params);
+
+        // If the parent of the view is has is a root, resolve the recycling.
+        if (topLevel && v instanceof ViewGroup) {
+            finalizeViewRecycling((ViewGroup) v);
+        }
     }
 
     /** @hide */
@@ -5922,27 +5905,6 @@
         return rvToApply;
     }
 
-    // Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
-    // should set it to false.
-    private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
-            ColorResources colorResources, boolean topLevel) {
-
-        RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
-
-        rvToApply.performApply(v, (ViewGroup) v.getParent(), handler, colorResources);
-
-        // If the parent of the view is has is a root, resolve the recycling.
-        if (topLevel && v instanceof ViewGroup) {
-            finalizeViewRecycling((ViewGroup) v);
-        }
-    }
-
-    private void reapplyNestedViews(Context context, View v, ViewGroup rootParent,
-            InteractionHandler handler, SizeF size, ColorResources colorResources) {
-        RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
-        rvToApply.performApply(v, rootParent, handler, colorResources);
-    }
-
     /**
      * Applies all the actions to the provided view, moving as much of the task on the background
      * thread as possible.
@@ -5973,19 +5935,25 @@
             ColorResources colorResources) {
         RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
 
+        ActionApplyParams params = new ActionApplyParams()
+                .withColorResources(colorResources)
+                .withInteractionHandler(handler)
+                .withExecutor(executor);
+
         return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
-                context, listener, handler, colorResources, v, true /* topLevel */)
+                context, listener, params, v, true /* topLevel */)
                 .startTaskOnExecutor(executor);
     }
 
-    private void performApply(View v, ViewGroup parent, InteractionHandler handler,
-            ColorResources colorResources) {
+    private void performApply(View v, ViewGroup parent, ActionApplyParams params) {
+        params = params.clone();
+        if (params.handler == null) {
+            params.handler = DEFAULT_INTERACTION_HANDLER;
+        }
         if (mActions != null) {
-            handler = handler == null ? DEFAULT_INTERACTION_HANDLER : handler;
             final int count = mActions.size();
             for (int i = 0; i < count; i++) {
-                Action a = mActions.get(i);
-                a.apply(v, parent, handler, colorResources);
+                mActions.get(i).apply(v, parent, params);
             }
         }
     }
@@ -6043,6 +6011,47 @@
     }
 
     /**
+     * Utility class to hold all the options when applying the remote views
+     * @hide
+     */
+    public class ActionApplyParams {
+
+        public InteractionHandler handler;
+        public ColorResources colorResources;
+        public Executor executor;
+        @StyleRes public int applyThemeResId;
+
+        @Override
+        public ActionApplyParams clone() {
+            return new ActionApplyParams()
+                    .withInteractionHandler(handler)
+                    .withColorResources(colorResources)
+                    .withExecutor(executor)
+                    .withThemeResId(applyThemeResId);
+        }
+
+        public ActionApplyParams withInteractionHandler(InteractionHandler handler) {
+            this.handler = handler;
+            return this;
+        }
+
+        public ActionApplyParams withColorResources(ColorResources colorResources) {
+            this.colorResources = colorResources;
+            return this;
+        }
+
+        public ActionApplyParams withThemeResId(@StyleRes int themeResId) {
+            this.applyThemeResId = themeResId;
+            return this;
+        }
+
+        public ActionApplyParams withExecutor(Executor executor) {
+            this.executor = executor;
+            return this;
+        }
+    }
+
+    /**
      * Object allowing the modification of a context to overload the system's dynamic colors.
      *
      * Only colors from {@link android.R.color#system_accent1_0} to
@@ -6056,10 +6065,12 @@
         // Size, in bytes, of an entry in the array of colors in an ARSC file.
         private static final int ARSC_ENTRY_SIZE = 16;
 
-        private ResourcesLoader mLoader;
+        private final ResourcesLoader mLoader;
+        private final SparseIntArray mColorMapping;
 
-        private ColorResources(ResourcesLoader loader) {
+        private ColorResources(ResourcesLoader loader, SparseIntArray colorMapping) {
             mLoader = loader;
+            mColorMapping = colorMapping;
         }
 
         /**
@@ -6071,6 +6082,10 @@
             context.getResources().addLoaders(mLoader);
         }
 
+        public SparseIntArray getColorMapping() {
+            return mColorMapping;
+        }
+
         private static ByteArrayOutputStream readFileContent(InputStream input) throws IOException {
             ByteArrayOutputStream content = new ByteArrayOutputStream(2048);
             byte[] buffer = new byte[4096];
@@ -6145,7 +6160,7 @@
                             ResourcesLoader colorsLoader = new ResourcesLoader();
                             colorsLoader.addProvider(ResourcesProvider
                                     .loadFromTable(pfd, null /* assetsProvider */));
-                            return new ColorResources(colorsLoader);
+                            return new ColorResources(colorsLoader, colorMapping.clone());
                         }
                     }
                 } finally {
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index cc90aaf..e567ced 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -32,8 +32,10 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.SparseArray;
 import android.view.RemoteAnimationDefinition;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -72,6 +74,12 @@
      */
     private final Executor mExecutor;
 
+    // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release.
+    /** Map from Task id to client tokens of TaskFragments in the Task. */
+    private final SparseArray<List<IBinder>> mTaskIdToFragmentTokens = new SparseArray<>();
+    /** Map from Task id to Task configuration. */
+    private final SparseArray<Configuration> mTaskIdToConfigurations = new SparseArray<>();
+
     public TaskFragmentOrganizer(@NonNull Executor executor) {
         mExecutor = executor;
     }
@@ -161,6 +169,27 @@
             @NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {}
 
     /**
+     * Called when the parent leaf Task of organized TaskFragments is changed.
+     * When the leaf Task is changed, the organizer may want to update the TaskFragments in one
+     * transaction.
+     *
+     * For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new
+     * Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override
+     * bounds.
+     * @hide
+     */
+    public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
+        // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release.
+        final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId);
+        if (tokens == null || tokens.isEmpty()) {
+            return;
+        }
+        for (int i = tokens.size() - 1; i >= 0; i--) {
+            onTaskFragmentParentInfoChanged(tokens.get(i), parentConfig);
+        }
+    }
+
+    /**
      * Called when the {@link WindowContainerTransaction} created with
      * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} failed on the server side.
      *
@@ -203,34 +232,43 @@
         final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
         for (TaskFragmentTransaction.Change change : changes) {
             // TODO(b/240519866): apply all changes in one WCT.
+            final int taskId = change.getTaskId();
             switch (change.getType()) {
                 case TYPE_TASK_FRAGMENT_APPEARED:
-                    onTaskFragmentAppeared(change.getTaskFragmentInfo());
-                    if (change.getTaskConfiguration() != null) {
-                        // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the
-                        // same Task
-                        onTaskFragmentParentInfoChanged(
-                                change.getTaskFragmentToken(),
-                                change.getTaskConfiguration());
+                    // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+                    // release.
+                    if (!mTaskIdToFragmentTokens.contains(taskId)) {
+                        mTaskIdToFragmentTokens.put(taskId, new ArrayList<>());
                     }
+                    mTaskIdToFragmentTokens.get(taskId).add(change.getTaskFragmentToken());
+                    onTaskFragmentParentInfoChanged(change.getTaskFragmentToken(),
+                            mTaskIdToConfigurations.get(taskId));
+
+                    onTaskFragmentAppeared(change.getTaskFragmentInfo());
                     break;
                 case TYPE_TASK_FRAGMENT_INFO_CHANGED:
-                    if (change.getTaskConfiguration() != null) {
-                        // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the
-                        // same Task
-                        onTaskFragmentParentInfoChanged(
-                                change.getTaskFragmentToken(),
-                                change.getTaskConfiguration());
-                    }
                     onTaskFragmentInfoChanged(change.getTaskFragmentInfo());
                     break;
                 case TYPE_TASK_FRAGMENT_VANISHED:
+                    // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+                    // release.
+                    if (mTaskIdToFragmentTokens.contains(taskId)) {
+                        final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId);
+                        tokens.remove(change.getTaskFragmentToken());
+                        if (tokens.isEmpty()) {
+                            mTaskIdToFragmentTokens.remove(taskId);
+                            mTaskIdToConfigurations.remove(taskId);
+                        }
+                    }
+
                     onTaskFragmentVanished(change.getTaskFragmentInfo());
                     break;
                 case TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED:
-                    onTaskFragmentParentInfoChanged(
-                            change.getTaskFragmentToken(),
-                            change.getTaskConfiguration());
+                    // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+                    // release.
+                    mTaskIdToConfigurations.put(taskId, change.getTaskConfiguration());
+
+                    onTaskFragmentParentInfoChanged(taskId, change.getTaskConfiguration());
                     break;
                 case TYPE_TASK_FRAGMENT_ERROR:
                     final Bundle errorBundle = change.getErrorBundle();
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index dbfa4d3..48343803 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -66,6 +66,8 @@
     private static final long INVALID_ID = -1;
     public static final int NANOS_IN_MILLISECOND = 1_000_000;
 
+    private static final int MAX_LENGTH_EVENT_DESC = 20;
+
     static final int REASON_END_UNKNOWN = -1;
     static final int REASON_END_NORMAL = 0;
     static final int REASON_END_SURFACE_DESTROYED = 1;
@@ -394,7 +396,18 @@
         return true;
     }
 
-    private void markEvent(String desc) {
+    /**
+     * Mark the FrameTracker events in the trace.
+     *
+     * @param desc The description of the trace event,
+     *            shouldn't exceed {@link #MAX_LENGTH_EVENT_DESC}.
+     */
+    private void markEvent(@NonNull String desc) {
+        if (desc.length() > MAX_LENGTH_EVENT_DESC) {
+            throw new IllegalArgumentException(TextUtils.formatSimple(
+                    "The length of the trace event description <%s> exceeds %d",
+                    desc, MAX_LENGTH_EVENT_DESC));
+        }
         Trace.beginSection(TextUtils.formatSimple("%s#%s", mSession.getName(), desc));
         Trace.endSection();
     }
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e625b31..72de78c 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -149,6 +149,10 @@
     private static final int DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES = 3;
     private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
 
+    @VisibleForTesting
+    public static final int MAX_LENGTH_OF_CUJ_NAME = 80;
+    private static final int MAX_LENGTH_SESSION_NAME = 100;
+
     public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
     public static final String ACTION_SESSION_CANCEL = ACTION_PREFIX + ".ACTION_SESSION_CANCEL";
 
@@ -732,6 +736,9 @@
      * @return the name of the cuj type
      */
     public static String getNameOfCuj(int cujType) {
+        // Please note:
+        // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
+        // 2. The returned string should be the same with the name defined in atoms.proto.
         switch (cujType) {
             case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE:
                 return "SHADE_EXPAND_COLLAPSE";
@@ -1106,9 +1113,27 @@
         public Session(@CujType int cujType, @NonNull String postfix) {
             mCujType = cujType;
             mTimeStamp = System.nanoTime();
-            mName = TextUtils.isEmpty(postfix)
-                    ? String.format("J<%s>", getNameOfCuj(mCujType))
-                    : String.format("J<%s::%s>", getNameOfCuj(mCujType), postfix);
+            mName = generateSessionName(getNameOfCuj(cujType), postfix);
+        }
+
+        private String generateSessionName(@NonNull String cujName, @NonNull String cujPostfix) {
+            final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix);
+            // We assert that the cujName shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
+            if (cujName.length() > MAX_LENGTH_OF_CUJ_NAME) {
+                throw new IllegalArgumentException(TextUtils.formatSimple(
+                        "The length of cuj name <%s> exceeds %d", cujName, MAX_LENGTH_OF_CUJ_NAME));
+            }
+            if (hasPostfix) {
+                final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length();
+                if (cujPostfix.length() > remaining) {
+                    cujPostfix = cujPostfix.substring(0, remaining - 3).concat("...");
+                }
+            }
+            // The max length of the whole string should be:
+            // 105 with postfix, 83 without postfix
+            return hasPostfix
+                    ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix)
+                    : TextUtils.formatSimple("J<%s>", cujName);
         }
 
         @CujType
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 0a29fc52..fa6fa55 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -1169,7 +1169,15 @@
 
     }
 
+    /** @hide */
+    public static void startForWifi(Context context) {
+        new BinderCallsStats.SettingsObserver(
+            context,
+            new BinderCallsStats(
+                new BinderCallsStats.Injector(),
+                com.android.internal.os.BinderLatencyProto.Dims.WIFI));
 
+    }
 
     /**
      * Settings observer for other processes (not system_server).
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 578b588..2c9ef4f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -339,6 +339,8 @@
     // A map from package name of vendor APEXes that can be updated to an installer package name
     // allowed to install updates for it.
     private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>();
+    // A set of package names that are allowed to use <install-constraints> manifest tag.
+    private final Set<String> mInstallConstraintsAllowlist = new ArraySet<>();
 
     private String mModulesInstallerPackageName;
 
@@ -535,6 +537,10 @@
         return mAllowedVendorApexes;
     }
 
+    public Set<String> getInstallConstraintsAllowlist() {
+        return mInstallConstraintsAllowlist;
+    }
+
     public String getModulesInstallerPackageName() {
         return mModulesInstallerPackageName;
     }
@@ -1455,6 +1461,20 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "install-constraints-allowed": {
+                        if (allowAppConfigs) {
+                            String packageName = parser.getAttributeValue(null, "package");
+                            if (packageName == null) {
+                                Slog.w(TAG, "<" + name + "> without package in " + permFile
+                                        + " at " + parser.getPositionDescription());
+                            } else {
+                                mInstallConstraintsAllowlist.add(packageName);
+                            }
+                        } else {
+                            logNotAllowedInPartition(name, permFile, parser);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     default: {
                         Slog.w(TAG, "Tag " + name + " is unknown in "
                                 + permFile + " at " + parser.getPositionDescription());
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0acf703..062523e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -3607,4 +3607,19 @@
              false, the application cannot be profiled at all. Defaults to true. -->
         <attr name="enabled" format="boolean" />
     </declare-styleable>
+
+    <!-- <code>install-constraints</code> tag rejects installs unless one the constraints defined by
+         its child elements is true.
+         It is possible to have multiple <code>install-constraints</code> tags in a single manifest,
+         where each tag is evaluated independently.
+         @hide -->
+    <declare-styleable name="AndroidManifestInstallConstraints" parent="AndroidManifest" />
+
+    <!-- A constraint for <code>install-constraints</code>. Checks that the device fingerprint
+         starts with the given prefix.
+         @hide -->
+    <declare-styleable name="AndroidManifestInstallConstraintsFingerprintPrefix"
+                       parent="AndroidManifestInstallConstraints">
+        <attr name="value" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9d2c3d7..d176a1d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2629,6 +2629,10 @@
          will be locked. -->
     <bool name="config_multiuserDelayUserDataLocking">false</bool>
 
+    <!-- Whether the device allows users to start in background on secondary displays.
+         Should be false for most devices, except automotive vehicle with passenger displays. -->
+    <bool name="config_multiuserUsersOnSecondaryDisplays">false</bool>
+
     <!-- Whether to automatically switch a non-primary user back to the primary user after a
          timeout when the device is docked.  -->
     <bool name="config_enableTimeoutToUserZeroWhenDocked">false</bool>
@@ -5850,4 +5854,7 @@
 
     <!-- Whether the wake screen on notifications feature is available. -->
     <bool name="config_pulseOnNotificationsAvailable">true</bool>
+
+    <!-- The number of tasks to scan to get the visibility of Home -->
+    <integer name="config_maxScanTasksForHomeVisibility">10</integer>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cb0393f..e6ae7b1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -453,6 +453,7 @@
   <java-symbol type="integer" name="config_multiuserMaximumUsers" />
   <java-symbol type="integer" name="config_multiuserMaxRunningUsers" />
   <java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
+  <java-symbol type="bool" name="config_multiuserUsersOnSecondaryDisplays" />
   <java-symbol type="bool" name="config_enableTimeoutToUserZeroWhenDocked" />
   <java-symbol type="integer" name="config_userTypePackageWhitelistMode"/>
   <java-symbol type="xml" name="config_user_types" />
@@ -3977,6 +3978,8 @@
 
   <java-symbol type="string" name="config_customCountryDetector" />
 
+  <java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
+
   <!-- For Foldables -->
   <java-symbol type="array" name="config_foldedDeviceStates" />
   <java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
diff --git a/core/tests/coretests/src/android/graphics/PathOffsetTest.java b/core/tests/coretests/src/android/graphics/PathOffsetTest.java
deleted file mode 100644
index 6cc42f6..0000000
--- a/core/tests/coretests/src/android/graphics/PathOffsetTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2008 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.graphics;
-
-import static org.junit.Assert.assertTrue;
-
-import android.graphics.Bitmap.Config;
-import android.graphics.Path.Direction;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class PathOffsetTest {
-
-    private static final int SQUARE = 10;
-    private static final int WIDTH = 100;
-    private static final int HEIGHT = 100;
-    private static final int START_X = 10;
-    private static final int START_Y = 20;
-    private static final int OFFSET_X = 30;
-    private static final int OFFSET_Y = 40;
-
-    @Test
-    @SmallTest
-    public void testPathOffset() {
-        Path actualPath = new Path();
-        actualPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW);
-        assertTrue(actualPath.isSimplePath);
-        actualPath.offset(OFFSET_X, OFFSET_Y);
-        assertTrue(actualPath.isSimplePath);
-
-        Path expectedPath = new Path();
-        expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE,
-                START_Y + OFFSET_Y + SQUARE, Direction.CW);
-
-        assertPaths(actualPath, expectedPath);
-    }
-
-    @Test
-    @SmallTest
-    public void testPathOffsetWithDestination() {
-        Path initialPath = new Path();
-        initialPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW);
-        Path actualPath = new Path();
-        assertTrue(initialPath.isSimplePath);
-        assertTrue(actualPath.isSimplePath);
-        initialPath.offset(OFFSET_X, OFFSET_Y, actualPath);
-        assertTrue(actualPath.isSimplePath);
-
-        Path expectedPath = new Path();
-        expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE,
-                START_Y + OFFSET_Y + SQUARE, Direction.CW);
-
-        assertPaths(actualPath, expectedPath);
-    }
-
-    private static void assertPaths(Path actual, Path expected) {
-        Bitmap actualBitmap = drawAndGetBitmap(actual);
-        Bitmap expectedBitmap = drawAndGetBitmap(expected);
-        assertTrue(actualBitmap.sameAs(expectedBitmap));
-    }
-
-    private static Bitmap drawAndGetBitmap(Path path) {
-        Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Config.ARGB_8888);
-        bitmap.eraseColor(Color.BLACK);
-        Paint paint = new Paint();
-        paint.setColor(Color.RED);
-        Canvas canvas = new Canvas(bitmap);
-        canvas.drawPath(path, paint);
-        return bitmap;
-    }
-
-}
diff --git a/core/tests/coretests/src/android/graphics/PathTest.java b/core/tests/coretests/src/android/graphics/PathTest.java
deleted file mode 100644
index b50792c..0000000
--- a/core/tests/coretests/src/android/graphics/PathTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 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.graphics;
-
-import androidx.test.filters.SmallTest;
-
-import junit.framework.TestCase;
-
-public class PathTest extends TestCase {
-
-    @SmallTest
-    public void testResetPreservesFillType() throws Exception {
-        Path path = new Path();
-
-        final Path.FillType defaultFillType = path.getFillType();
-        final Path.FillType fillType = Path.FillType.INVERSE_EVEN_ODD;
-
-        // This test is only meaningful if it changes from the default.
-        assertFalse(fillType.equals(defaultFillType));
-
-        path.setFillType(fillType);
-        path.reset();
-        assertEquals(path.getFillType(), fillType);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index d96f041..1519e48 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -16,10 +16,26 @@
 
 package com.android.internal.jank;
 
+import static android.text.TextUtils.formatSimple;
+
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
 import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_LAUNCH_CAMERA;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_ADD;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_APP_START;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_APPEAR;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_REMOVE;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_EXPAND;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE;
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
+import static com.android.internal.jank.InteractionJankMonitor.MAX_LENGTH_OF_CUJ_NAME;
+import static com.android.internal.jank.InteractionJankMonitor.getNameOfCuj;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -38,6 +54,7 @@
 import android.os.HandlerThread;
 import android.os.SystemClock;
 import android.provider.DeviceConfig;
+import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewAttachTestActivity;
 
@@ -52,8 +69,12 @@
 import com.android.internal.jank.FrameTracker.ViewRootWrapper;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
 import com.android.internal.jank.InteractionJankMonitor.Session;
+import com.android.internal.util.FrameworkStatsLog;
+
+import com.google.common.truth.Expect;
 
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -64,11 +85,17 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @SmallTest
 public class InteractionJankMonitorTest {
     private static final String CUJ_POSTFIX = "";
+    private static final SparseArray<String> ENUM_NAME_EXCEPTION_MAP = new SparseArray<>();
+    private static final SparseArray<String> CUJ_NAME_EXCEPTION_MAP = new SparseArray<>();
+    private static final String ENUM_NAME_PREFIX =
+            "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__";
+
     private ViewAttachTestActivity mActivity;
     private View mView;
     private HandlerThread mWorker;
@@ -77,6 +104,53 @@
     public ActivityTestRule<ViewAttachTestActivity> mRule =
             new ActivityTestRule<>(ViewAttachTestActivity.class);
 
+    @Rule
+    public final Expect mExpect = Expect.create();
+
+    @BeforeClass
+    public static void initialize() {
+        ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD"));
+        ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE"));
+        ENUM_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"));
+
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, "CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE");
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
+                "CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE");
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, "CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE");
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_ROW_EXPAND, "CUJ_NOTIFICATION_SHADE_ROW_EXPAND");
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_ROW_SWIPE, "CUJ_NOTIFICATION_SHADE_ROW_SWIPE");
+        CUJ_NAME_EXCEPTION_MAP.put(
+                CUJ_NOTIFICATION_SHADE_SCROLL_FLING, "CUJ_NOTIFICATION_SHADE_SCROLL_FLING");
+        CUJ_NAME_EXCEPTION_MAP.put(CUJ_LOCKSCREEN_LAUNCH_CAMERA, "CUJ_LOCKSCREEN_LAUNCH_CAMERA");
+        CUJ_NAME_EXCEPTION_MAP.put(CUJ_SPLIT_SCREEN_RESIZE, "CUJ_SPLIT_SCREEN_RESIZE");
+    }
+
+    private static String getEnumName(String name) {
+        return formatSimple("%s%s", ENUM_NAME_PREFIX, name);
+    }
+
     @Before
     public void setup() {
         // Prepare an activity for getting ThreadedRenderer later.
@@ -174,6 +248,82 @@
         }
     }
 
+    @Test
+    public void testCujsMapToEnumsCorrectly() {
+        List<Field> cujs = Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
+                .filter(f -> f.getName().startsWith("CUJ_")
+                        && Modifier.isStatic(f.getModifiers())
+                        && f.getType() == int.class)
+                .collect(Collectors.toList());
+
+        Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields())
+                .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX)
+                        && Modifier.isStatic(f.getModifiers())
+                        && f.getType() == int.class)
+                .collect(Collectors.toMap(this::getIntFieldChecked, Field::getName));
+
+        cujs.forEach(f -> {
+            final int cuj = getIntFieldChecked(f);
+            final String cujName = f.getName();
+            final String expectedEnumName = ENUM_NAME_EXCEPTION_MAP.contains(cuj)
+                    ? ENUM_NAME_EXCEPTION_MAP.get(cuj)
+                    : formatSimple("%s%s", ENUM_NAME_PREFIX, cujName.substring(4));
+            final int enumKey = CUJ_TO_STATSD_INTERACTION_TYPE[cuj];
+            final String enumName = enumsMap.get(enumKey);
+            final String expectedNameOfCuj = CUJ_NAME_EXCEPTION_MAP.contains(cuj)
+                    ? CUJ_NAME_EXCEPTION_MAP.get(cuj)
+                    : formatSimple("CUJ_%s", getNameOfCuj(cuj));
+            mExpect
+                    .withMessage(formatSimple(
+                            "%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey))
+                    .that(expectedEnumName.equals(enumName))
+                    .isTrue();
+            mExpect
+                    .withMessage(formatSimple("getNameOfCuj(%d) not matches %s", cuj, cujName))
+                    .that(cujName.equals(expectedNameOfCuj))
+                    .isTrue();
+        });
+    }
+
+    @Test
+    public void testCujNameLimit() {
+        Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
+                .filter(f -> f.getName().startsWith("CUJ_")
+                        && Modifier.isStatic(f.getModifiers())
+                        && f.getType() == int.class)
+                .forEach(f -> {
+                    final int cuj = getIntFieldChecked(f);
+                    mExpect
+                            .withMessage(formatSimple(
+                                    "Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj)))
+                            .that(getNameOfCuj(cuj).length())
+                            .isAtMost(MAX_LENGTH_OF_CUJ_NAME);
+                });
+    }
+
+    @Test
+    public void testSessionNameLengthLimit() {
+        final int cujType = CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+        final String cujName = getNameOfCuj(cujType);
+        final String cujTag = "ThisIsTheCujTag";
+        final String tooLongTag = cujTag.repeat(10);
+
+        // Normal case, no postfix.
+        Session noPostfix = new Session(cujType, "");
+        assertThat(noPostfix.getName()).isEqualTo(formatSimple("J<%s>", cujName));
+
+        // Normal case, with postfix.
+        Session withPostfix = new Session(cujType, cujTag);
+        assertThat(withPostfix.getName()).isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag));
+
+        // Since the length of the cuj name is tested in another test, no need to test it here.
+        // Too long postfix case, should trim the postfix and keep the cuj name completed.
+        final String expectedTrimmedName = formatSimple("J<%s::%s>", cujName,
+                "ThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagT...");
+        Session longPostfix = new Session(cujType, tooLongTag);
+        assertThat(longPostfix.getName()).isEqualTo(expectedTrimmedName);
+    }
+
     private InteractionJankMonitor createMockedInteractionJankMonitor() {
         InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker));
         doReturn(true).when(monitor).shouldMonitor(anyInt());
@@ -217,4 +367,12 @@
 
         return tracker;
     }
+
+    private int getIntFieldChecked(Field field) {
+        try {
+            return field.getInt(null);
+        } catch (IllegalAccessException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
 }
diff --git a/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java b/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
index 7c76498..c88ab90 100644
--- a/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
+++ b/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
@@ -23,6 +23,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -34,7 +35,6 @@
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.quality.Strictness;
@@ -56,16 +56,11 @@
     private Parcel mParcelSpy;
     private Bundle mBundle;
 
-    @Before
-    public void setUp() throws Exception {
-        setUpBundle(/* hasLazy */ true);
-    }
-
     @Test
     public void bundleClear_whenUnparcelledWithoutLazy_recyclesParcelOnce() {
-        setUpBundle(/* hasLazy */ false);
+        setUpBundle(/* lazy */ 0, /* nonLazy */ 1);
         // Will unparcel and immediately recycle parcel
-        assertNotNull(mBundle.getString("key"));
+        assertNotNull(mBundle.getString("nonLazy0"));
         verify(mParcelSpy, times(1)).recycle();
         assertFalse(mBundle.isDefinitelyEmpty());
 
@@ -77,6 +72,7 @@
 
     @Test
     public void bundleClear_whenParcelled_recyclesParcel() {
+        setUpBundle(/* lazy */ 1);
         assertTrue(mBundle.isParcelled());
         verify(mParcelSpy, times(0)).recycle();
 
@@ -90,23 +86,9 @@
     }
 
     @Test
-    public void bundleClear_whenUnparcelledWithLazyValueUnwrapped_recyclesParcel() {
-        // Will unparcel with a lazy value, and immediately unwrap the lazy value,
-        // with no lazy values left at the end of getParcelable
-        assertNotNull(mBundle.getParcelable("key", CustomParcelable.class));
-        verify(mParcelSpy, times(0)).recycle();
-
-        mBundle.clear();
-        verify(mParcelSpy, times(1)).recycle();
-        assertTrue(mBundle.isDefinitelyEmpty());
-
-        // Should not recycle again
-        mBundle.clear();
-        verify(mParcelSpy, times(1)).recycle();
-    }
-
-    @Test
     public void bundleClear_whenUnparcelledWithLazy_recyclesParcel() {
+        setUpBundle(/* lazy */ 1);
+
         // Will unparcel but keep the CustomParcelable lazy
         assertFalse(mBundle.isEmpty());
         verify(mParcelSpy, times(0)).recycle();
@@ -122,6 +104,8 @@
 
     @Test
     public void bundleClear_whenClearedWithSharedParcel_doesNotRecycleParcel() {
+        setUpBundle(/* lazy */ 1);
+
         Bundle copy = new Bundle();
         copy.putAll(mBundle);
 
@@ -136,6 +120,8 @@
 
     @Test
     public void bundleClear_whenClearedWithCopiedParcel_doesNotRecycleParcel() {
+        setUpBundle(/* lazy */ 1);
+
         // Will unparcel but keep the CustomParcelable lazy
         assertFalse(mBundle.isEmpty());
 
@@ -151,7 +137,101 @@
         verify(mParcelSpy, never()).recycle();
     }
 
-    private void setUpBundle(boolean hasLazy) {
+    @Test
+    public void bundleGet_whenUnparcelledWithLazyValueUnwrapped_recyclesParcel() {
+        setUpBundle(/* lazy */ 1);
+
+        // Will unparcel with a lazy value, and immediately unwrap the lazy value,
+        // with no lazy values left at the end of getParcelable
+        // Ref counting should immediately recycle
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(1)).recycle();
+
+        // Should not recycle again
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        mBundle.clear();
+        verify(mParcelSpy, times(1)).recycle();
+    }
+
+    @Test
+    public void bundleGet_whenMultipleLazy_recyclesParcelWhenAllUnwrapped() {
+        setUpBundle(/* lazy */ 2);
+
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(0)).recycle();
+
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(0)).recycle();
+
+        assertNotNull(mBundle.getParcelable("lazy1", CustomParcelable.class));
+        verify(mParcelSpy, times(1)).recycle();
+
+        // Should not recycle again
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        mBundle.clear();
+        verify(mParcelSpy, times(1)).recycle();
+        assertTrue(mBundle.isDefinitelyEmpty());
+    }
+
+    @Test
+    public void bundleGet_whenLazyAndNonLazy_recyclesParcelWhenAllUnwrapped() {
+        setUpBundle(/* lazy */ 1, /* nonLazy */ 1);
+
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(1)).recycle();
+
+        // Should not recycle again
+        assertNotNull(mBundle.getString("nonLazy0"));
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        mBundle.clear();
+        verify(mParcelSpy, times(1)).recycle();
+    }
+
+    @Test
+    public void bundleGet_whenLazyAndNonLazy_doesNotRecycleWhenOnlyNonLazyRetrieved() {
+        setUpBundle(/* lazy */ 1, /* nonLazy */ 1);
+
+        assertNotNull(mBundle.getString("nonLazy0"));
+        verify(mParcelSpy, times(0)).recycle();
+
+        assertNotNull(mBundle.getString("nonLazy0"));
+        verify(mParcelSpy, times(0)).recycle();
+
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(1)).recycle();
+    }
+
+    @Test
+    public void bundleGet_withWithSharedParcel_doesNotRecycleParcel() {
+        setUpBundle(/* lazy */ 1);
+
+        Bundle copy = new Bundle();
+        copy.putAll(mBundle);
+
+        assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        mBundle.clear();
+
+        assertNotNull(copy.getParcelable("lazy0", CustomParcelable.class));
+        copy.clear();
+
+        verify(mParcelSpy, never()).recycle();
+    }
+
+    @Test
+    public void bundleGet_getAfterLazyCleared_doesNotRecycleAgain() {
+        setUpBundle(/* lazy */ 1);
+        mBundle.clear();
+        verify(mParcelSpy, times(1)).recycle();
+
+        assertNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+        verify(mParcelSpy, times(1)).recycle();
+    }
+
+    private void setUpBundle(int lazy) {
+        setUpBundle(lazy, /* nonLazy */ 0);
+    }
+
+    private void setUpBundle(int lazy, int nonLazy) {
         AtomicReference<Parcel> parcel = new AtomicReference<>();
         StaticMockitoSession session = mockitoSession()
                 .strictness(Strictness.STRICT_STUBS)
@@ -166,7 +246,7 @@
 
         Bundle bundle = new Bundle();
         bundle.setClassLoader(getClass().getClassLoader());
-        Parcel p = createBundle(hasLazy);
+        Parcel p = createBundle(lazy, nonLazy);
         bundle.readFromParcel(p);
         p.recycle();
 
@@ -179,13 +259,17 @@
     /**
      * Create a test bundle, parcel it and return the parcel.
      */
-    private Parcel createBundle(boolean hasLazy) {
+    private Parcel createBundle(int lazy, int nonLazy) {
         final Bundle source = new Bundle();
-        if (hasLazy) {
-            source.putParcelable("key", new CustomParcelable(13, "Tiramisu"));
-        } else {
-            source.putString("key", "tiramisu");
+
+        for (int i = 0; i < nonLazy; i++) {
+            source.putString("nonLazy" + i, "Tiramisu");
         }
+
+        for (int i = 0; i < lazy; i++) {
+            source.putParcelable("lazy" + i, new CustomParcelable(13, "Tiramisu"));
+        }
+
         return getParcelledBundle(source);
     }
 
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 425a378..a8ab6d9 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -330,11 +330,7 @@
 
     public void drawPath(@NonNull Path path, @NonNull Paint paint) {
         throwIfHasHwFeaturesInSwMode(paint);
-        if (path.isSimplePath && path.rects != null) {
-            nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
-        } else {
-            nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
-        }
+        nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
     }
 
     public void drawPoint(float x, float y, @NonNull Paint paint) {
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index a998ba8..d06f665 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -286,11 +286,7 @@
 
     @Override
     public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
-        if (path.isSimplePath && path.rects != null) {
-            nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
-        } else {
-            nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
-        }
+        nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
     }
 
     @Override
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index e5ef10d..afcaabe 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -20,8 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -47,18 +45,6 @@
     public final long mNativePath;
 
     /**
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean isSimplePath = true;
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public Region rects;
-    private Direction mLastDirection = null;
-
-    /**
      * Create an empty path
      */
     public Path() {
@@ -72,15 +58,7 @@
      * @param src The path to copy from when initializing the new path
      */
     public Path(@Nullable Path src) {
-        long valNative = 0;
-        if (src != null) {
-            valNative = src.mNativePath;
-            isSimplePath = src.isSimplePath;
-            if (src.rects != null) {
-                rects = new Region(src.rects);
-            }
-        }
-        mNativePath = nInit(valNative);
+        mNativePath = nInit(src != null ? src.mNativePath : 0);
         sRegistry.registerNativeAllocation(this, mNativePath);
     }
 
@@ -89,9 +67,6 @@
      * This does NOT change the fill-type setting.
      */
     public void reset() {
-        isSimplePath = true;
-        mLastDirection = null;
-        if (rects != null) rects.setEmpty();
         // We promised not to change this, so preserve it around the native
         // call, which does now reset fill type.
         final FillType fillType = getFillType();
@@ -104,9 +79,6 @@
      * keeps the internal data structure for faster reuse.
      */
     public void rewind() {
-        isSimplePath = true;
-        mLastDirection = null;
-        if (rects != null) rects.setEmpty();
         nRewind(mNativePath);
     }
 
@@ -116,19 +88,7 @@
         if (this == src) {
             return;
         }
-        isSimplePath = src.isSimplePath;
         nSet(mNativePath, src.mNativePath);
-        if (!isSimplePath) {
-            return;
-        }
-
-        if (rects != null && src.rects != null) {
-            rects.set(src.rects);
-        } else if (rects != null && src.rects == null) {
-            rects.setEmpty();
-        } else if (src.rects != null) {
-            rects = new Region(src.rects);
-        }
     }
 
     /**
@@ -192,12 +152,7 @@
      * @see #op(Path, android.graphics.Path.Op)
      */
     public boolean op(@NonNull Path path1, @NonNull Path path2, @NonNull Op op) {
-        if (nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
-            isSimplePath = false;
-            rects = null;
-            return true;
-        }
-        return false;
+        return nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath);
     }
 
     /**
@@ -378,7 +333,6 @@
      * @param y The y-coordinate of the end of a line
      */
     public void lineTo(float x, float y) {
-        isSimplePath = false;
         nLineTo(mNativePath, x, y);
     }
 
@@ -393,7 +347,6 @@
      *           this contour, to specify a line
      */
     public void rLineTo(float dx, float dy) {
-        isSimplePath = false;
         nRLineTo(mNativePath, dx, dy);
     }
 
@@ -408,7 +361,6 @@
      * @param y2 The y-coordinate of the end point on a quadratic curve
      */
     public void quadTo(float x1, float y1, float x2, float y2) {
-        isSimplePath = false;
         nQuadTo(mNativePath, x1, y1, x2, y2);
     }
 
@@ -427,7 +379,6 @@
      *            this contour, for the end point of a quadratic curve
      */
     public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
-        isSimplePath = false;
         nRQuadTo(mNativePath, dx1, dy1, dx2, dy2);
     }
 
@@ -445,7 +396,6 @@
      */
     public void cubicTo(float x1, float y1, float x2, float y2,
                         float x3, float y3) {
-        isSimplePath = false;
         nCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
     }
 
@@ -456,7 +406,6 @@
      */
     public void rCubicTo(float x1, float y1, float x2, float y2,
                          float x3, float y3) {
-        isSimplePath = false;
         nRCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
     }
 
@@ -507,7 +456,6 @@
      */
     public void arcTo(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle, boolean forceMoveTo) {
-        isSimplePath = false;
         nArcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
     }
 
@@ -516,7 +464,6 @@
      * first point of the contour, a line segment is automatically added.
      */
     public void close() {
-        isSimplePath = false;
         nClose(mNativePath);
     }
 
@@ -536,18 +483,6 @@
         final int nativeInt;
     }
 
-    private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
-        if (mLastDirection == null) {
-            mLastDirection = dir;
-        }
-        if (mLastDirection != dir) {
-            isSimplePath = false;
-        } else {
-            if (rects == null) rects = new Region();
-            rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
-        }
-    }
-
     /**
      * Add a closed rectangle contour to the path
      *
@@ -568,7 +503,6 @@
      * @param dir    The direction to wind the rectangle's contour
      */
     public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) {
-        detectSimplePath(left, top, right, bottom, dir);
         nAddRect(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
@@ -588,7 +522,6 @@
      * @param dir The direction to wind the oval's contour
      */
     public void addOval(float left, float top, float right, float bottom, @NonNull Direction dir) {
-        isSimplePath = false;
         nAddOval(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
@@ -601,7 +534,6 @@
      * @param dir    The direction to wind the circle's contour
      */
     public void addCircle(float x, float y, float radius, @NonNull Direction dir) {
-        isSimplePath = false;
         nAddCircle(mNativePath, x, y, radius, dir.nativeInt);
     }
 
@@ -624,7 +556,6 @@
      */
     public void addArc(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle) {
-        isSimplePath = false;
         nAddArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
     }
 
@@ -649,7 +580,6 @@
      */
     public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry,
             @NonNull Direction dir) {
-        isSimplePath = false;
         nAddRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
     }
 
@@ -682,7 +612,6 @@
         if (radii.length < 8) {
             throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
         }
-        isSimplePath = false;
         nAddRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
     }
 
@@ -693,7 +622,6 @@
      * @param dx  The amount to translate the path in X as it is added
      */
     public void addPath(@NonNull Path src, float dx, float dy) {
-        isSimplePath = false;
         nAddPath(mNativePath, src.mNativePath, dx, dy);
     }
 
@@ -703,7 +631,6 @@
      * @param src The path that is appended to the current path
      */
     public void addPath(@NonNull Path src) {
-        isSimplePath = false;
         nAddPath(mNativePath, src.mNativePath);
     }
 
@@ -713,7 +640,6 @@
      * @param src The path to add as a new contour
      */
     public void addPath(@NonNull Path src, @NonNull Matrix matrix) {
-        if (!src.isSimplePath) isSimplePath = false;
         nAddPath(mNativePath, src.mNativePath, matrix.ni());
     }
 
@@ -741,15 +667,6 @@
      * @param dy The amount in the Y direction to offset the entire path
      */
     public void offset(float dx, float dy) {
-        if (isSimplePath && rects == null) {
-            // nothing to offset
-            return;
-        }
-        if (isSimplePath && dx == Math.rint(dx) && dy == Math.rint(dy)) {
-            rects.translate((int) dx, (int) dy);
-        } else {
-            isSimplePath = false;
-        }
         nOffset(mNativePath, dx, dy);
     }
 
@@ -760,7 +677,6 @@
      * @param dy The new Y coordinate for the last point
      */
     public void setLastPoint(float dx, float dy) {
-        isSimplePath = false;
         nSetLastPoint(mNativePath, dx, dy);
     }
 
@@ -773,12 +689,7 @@
      *               then the the original path is modified
      */
     public void transform(@NonNull Matrix matrix, @Nullable Path dst) {
-        long dstNative = 0;
-        if (dst != null) {
-            dst.isSimplePath = false;
-            dstNative = dst.mNativePath;
-        }
-        nTransform(mNativePath, matrix.ni(), dstNative);
+        nTransform(mNativePath, matrix.ni(), dst != null ? dst.mNativePath : 0);
     }
 
     /**
@@ -787,7 +698,6 @@
      * @param matrix The matrix to apply to the path
      */
     public void transform(@NonNull Matrix matrix) {
-        isSimplePath = false;
         nTransform(mNativePath, matrix.ni());
     }
 
@@ -797,7 +707,6 @@
     }
 
     final long mutateNI() {
-        isSimplePath = false;
         return mNativePath;
     }
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 8ae0d3d..25e1922 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1557,16 +1557,6 @@
         return Arrays.binarySearch(mSupportedAxes, axis) >= 0;
     }
 
-    /** @hide */
-    public List<FontFamily> getFallback() {
-        ArrayList<FontFamily> families = new ArrayList<>();
-        int familySize = nativeGetFamilySize(native_instance);
-        for (int i = 0; i < familySize; ++i) {
-            families.add(new FontFamily(nativeGetFamily(native_instance, i)));
-        }
-        return families;
-    }
-
     private static native long nativeCreateFromTypeface(long native_instance, int style);
     private static native long nativeCreateFromTypefaceWithExactStyle(
             long native_instance, int weight, boolean italic);
@@ -1592,13 +1582,6 @@
     @CriticalNative
     private static native long nativeGetReleaseFunc();
 
-    @CriticalNative
-    private static native int nativeGetFamilySize(long naitvePtr);
-
-    @CriticalNative
-    private static native long nativeGetFamily(long nativePtr, int index);
-
-
     private static native void nativeRegisterGenericFamily(String str, long nativePtr);
 
     private static native int nativeWriteTypefaces(
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 0dba6b0..d42fca2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -51,12 +51,6 @@
     @VisibleForTesting
     final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
 
-    /**
-     * Mapping from the client assigned unique token to the TaskFragment parent
-     * {@link Configuration}.
-     */
-    final Map<IBinder, Configuration> mFragmentParentConfigs = new ArrayMap<>();
-
     private final TaskFragmentCallback mCallback;
     @VisibleForTesting
     TaskFragmentAnimationController mAnimationController;
@@ -68,8 +62,7 @@
         void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo);
         void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo);
         void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo);
-        void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
-                @NonNull Configuration parentConfig);
+        void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig);
         void onActivityReparentToTask(int taskId, @NonNull Intent activityIntent,
                 @NonNull IBinder activityToken);
         void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType);
@@ -300,7 +293,6 @@
     @Override
     public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
         mFragmentInfos.remove(taskFragmentInfo.getFragmentToken());
-        mFragmentParentConfigs.remove(taskFragmentInfo.getFragmentToken());
 
         if (mCallback != null) {
             mCallback.onTaskFragmentVanished(taskFragmentInfo);
@@ -308,12 +300,9 @@
     }
 
     @Override
-    public void onTaskFragmentParentInfoChanged(
-            @NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {
-        mFragmentParentConfigs.put(fragmentToken, parentConfig);
-
+    public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
         if (mCallback != null) {
-            mCallback.onTaskFragmentParentInfoChanged(fragmentToken, parentConfig);
+            mCallback.onTaskFragmentParentInfoChanged(taskId, parentConfig);
         }
     }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index c688080..dad0739 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -155,6 +155,9 @@
             container.setInfo(taskFragmentInfo);
             if (container.isFinished()) {
                 mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
+            } else {
+                // Update with the latest Task configuration.
+                mPresenter.updateContainer(container);
             }
             updateCallbackIfNecessary();
         }
@@ -233,19 +236,30 @@
     }
 
     @Override
-    public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
-            @NonNull Configuration parentConfig) {
+    public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
         synchronized (mLock) {
-            final TaskFragmentContainer container = getContainer(fragmentToken);
-            if (container != null) {
-                onTaskConfigurationChanged(container.getTaskId(), parentConfig);
-                if (isInPictureInPicture(parentConfig)) {
-                    // No need to update presentation in PIP until the Task exit PIP.
-                    return;
-                }
-                mPresenter.updateContainer(container);
-                updateCallbackIfNecessary();
+            onTaskConfigurationChanged(taskId, parentConfig);
+            if (isInPictureInPicture(parentConfig)) {
+                // No need to update presentation in PIP until the Task exit PIP.
+                return;
             }
+            final TaskContainer taskContainer = getTaskContainer(taskId);
+            if (taskContainer == null || taskContainer.isEmpty()) {
+                Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
+                return;
+            }
+            // Update all TaskFragments in the Task. Make a copy of the list since some may be
+            // removed on updating.
+            final List<TaskFragmentContainer> containers =
+                    new ArrayList<>(taskContainer.mContainers);
+            for (int i = containers.size() - 1; i >= 0; i--) {
+                final TaskFragmentContainer container = containers.get(i);
+                // Wait until onTaskFragmentAppeared to update new container.
+                if (!container.isFinished() && !container.isWaitingActivityAppear()) {
+                    mPresenter.updateContainer(container);
+                }
+            }
+            updateCallbackIfNecessary();
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 31fc6a5..2c02006 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -452,6 +452,7 @@
      */
     void setEntry(@NonNull final BubbleEntry entry) {
         Objects.requireNonNull(entry);
+        boolean showingDotPreviously = showDot();
         mLastUpdated = entry.getStatusBarNotification().getPostTime();
         mIsBubble = entry.getStatusBarNotification().getNotification().isBubbleNotification();
         mPackageName = entry.getStatusBarNotification().getPackageName();
@@ -498,6 +499,10 @@
         mShouldSuppressNotificationDot = entry.shouldSuppressNotificationDot();
         mShouldSuppressNotificationList = entry.shouldSuppressNotificationList();
         mShouldSuppressPeek = entry.shouldSuppressPeek();
+        if (showingDotPreviously != showDot()) {
+            // This will update the UI if needed
+            setShowDot(showDot());
+        }
     }
 
     @Nullable
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
index 4eeb207..d6803e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
@@ -19,14 +19,14 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Paint;
+import android.graphics.Color;
 import android.graphics.Path;
+import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.Drawable;
 
 import com.android.launcher3.icons.BaseIconFactory;
 import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.ShadowGenerator;
 import com.android.wm.shell.R;
 
 /**
@@ -44,78 +44,77 @@
      * will include the workprofile indicator on the badge if appropriate.
      */
     BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
-        ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize);
-        Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize);
-
         if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
-            userBadgedBitmap = Bitmap.createScaledBitmap(
-                    getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */
-                            userBadgedAppIcon.getIntrinsicWidth()),
-                    mIconBitmapSize, mIconBitmapSize, /* filter */ true);
+            AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon;
+            userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground());
+        }
+        if (isImportantConversation) {
+            userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon);
+        }
+        Bitmap userBadgedBitmap = createIconBitmap(
+                userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW);
+        return createIconBitmap(userBadgedBitmap);
+    }
+
+    private class CircularRingDrawable extends CircularAdaptiveIcon {
+
+        final int mImportantConversationColor;
+        final Rect mTempBounds = new Rect();
+
+        final Drawable mDr;
+
+        CircularRingDrawable(Drawable dr) {
+            super(null, null);
+            mDr = dr;
+            mImportantConversationColor = mContext.getResources().getColor(
+                    R.color.important_conversation, null);
         }
 
-        if (isImportantConversation) {
-            final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
+        @Override
+        public void draw(Canvas canvas) {
+            int save = canvas.save();
+            canvas.clipPath(getIconMask());
+            canvas.drawColor(mImportantConversationColor);
+            int ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
                     com.android.internal.R.dimen.importance_ring_stroke_width);
-            final int importantConversationColor = mContext.getResources().getColor(
-                    R.color.important_conversation, null);
-            Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
-                    userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
-            Canvas c = new Canvas(badgeAndRing);
-
-            Paint ringPaint = new Paint();
-            ringPaint.setStyle(Paint.Style.FILL);
-            ringPaint.setColor(importantConversationColor);
-            ringPaint.setAntiAlias(true);
-            c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint);
-
-            final int bitmapTop = (int) ringStrokeWidth;
-            final int bitmapLeft = (int) ringStrokeWidth;
-            final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth;
-            final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth;
-
-            Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth,
-                    bitmapHeight, /* filter */ true);
-            c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null);
-
-            shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
-            return createIconBitmap(badgeAndRing);
-        } else {
-            Canvas c = new Canvas();
-            c.setBitmap(userBadgedBitmap);
-            shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
-            return createIconBitmap(userBadgedBitmap);
+            mTempBounds.set(getBounds());
+            mTempBounds.inset(ringStrokeWidth, ringStrokeWidth);
+            mDr.setBounds(mTempBounds);
+            mDr.draw(canvas);
+            canvas.restoreToCount(save);
         }
     }
 
-    private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) {
-        Drawable foreground = icon.getForeground();
-        Drawable background = icon.getBackground();
-        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas();
-        canvas.setBitmap(bitmap);
+    private static class CircularAdaptiveIcon extends AdaptiveIconDrawable {
 
-        // Clip canvas to circle.
-        Path circlePath = new Path();
-        circlePath.addCircle(/* x */ size / 2f,
-                /* y */ size / 2f,
-                /* radius */ size / 2f,
-                Path.Direction.CW);
-        canvas.clipPath(circlePath);
+        final Path mPath = new Path();
 
-        // Draw background.
-        background.setBounds(0, 0, size, size);
-        background.draw(canvas);
+        CircularAdaptiveIcon(Drawable bg, Drawable fg) {
+            super(bg, fg);
+        }
 
-        // Draw foreground. The foreground and background drawables are derived from adaptive icons
-        // Some icon shapes fill more space than others, so adaptive icons are normalized to about
-        // the same size. This size is smaller than the original bounds, so we estimate
-        // the difference in this offset.
-        int offset = size / 5;
-        foreground.setBounds(-offset, -offset, size + offset, size + offset);
-        foreground.draw(canvas);
+        @Override
+        public Path getIconMask() {
+            mPath.reset();
+            Rect bounds = getBounds();
+            mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW);
+            return mPath;
+        }
 
-        canvas.setBitmap(null);
-        return bitmap;
+        @Override
+        public void draw(Canvas canvas) {
+            int save = canvas.save();
+            canvas.clipPath(getIconMask());
+
+            canvas.drawColor(Color.BLACK);
+            Drawable d;
+            if ((d = getBackground()) != null) {
+                d.draw(canvas);
+            }
+            if ((d = getForeground()) != null) {
+                d.draw(canvas);
+            }
+            canvas.restoreToCount(save);
+        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 3982616..8771ceb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1055,18 +1055,28 @@
     public void updateBubble(BubbleEntry notif, boolean suppressFlyout, boolean showInShade) {
         // If this is an interruptive notif, mark that it's interrupted
         mSysuiProxy.setNotificationInterruption(notif.getKey());
-        if (!notif.getRanking().isTextChanged()
+        boolean isNonInterruptiveNotExpanding = !notif.getRanking().isTextChanged()
                 && (notif.getBubbleMetadata() != null
-                && !notif.getBubbleMetadata().getAutoExpandBubble())
+                && !notif.getBubbleMetadata().getAutoExpandBubble());
+        if (isNonInterruptiveNotExpanding
                 && mBubbleData.hasOverflowBubbleWithKey(notif.getKey())) {
             // Update the bubble but don't promote it out of overflow
             Bubble b = mBubbleData.getOverflowBubbleWithKey(notif.getKey());
-            b.setEntry(notif);
+            if (notif.isBubble()) {
+                notif.setFlagBubble(false);
+            }
+            updateNotNotifyingEntry(b, notif, showInShade);
+        } else if (mBubbleData.hasAnyBubbleWithKey(notif.getKey())
+                && isNonInterruptiveNotExpanding) {
+            Bubble b = mBubbleData.getAnyBubbleWithkey(notif.getKey());
+            if (b != null) {
+                updateNotNotifyingEntry(b, notif, showInShade);
+            }
         } else if (mBubbleData.isSuppressedWithLocusId(notif.getLocusId())) {
             // Update the bubble but don't promote it out of overflow
             Bubble b = mBubbleData.getSuppressedBubbleWithKey(notif.getKey());
             if (b != null) {
-                b.setEntry(notif);
+                updateNotNotifyingEntry(b, notif, showInShade);
             }
         } else {
             Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */);
@@ -1076,13 +1086,25 @@
                 if (bubble.shouldAutoExpand()) {
                     bubble.setShouldAutoExpand(false);
                 }
+                mImpl.mCachedState.updateBubbleSuppressedState(bubble);
             } else {
                 inflateAndAdd(bubble, suppressFlyout, showInShade);
             }
         }
     }
 
-    void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
+    void updateNotNotifyingEntry(Bubble b, BubbleEntry entry, boolean showInShade) {
+        boolean isBubbleSelected = Objects.equals(b, mBubbleData.getSelectedBubble());
+        boolean isBubbleExpandedAndSelected = isStackExpanded() && isBubbleSelected;
+        b.setEntry(entry);
+        boolean suppress = isBubbleExpandedAndSelected || !showInShade || !b.showInShade();
+        b.setSuppressNotification(suppress);
+        b.setShowDot(!isBubbleExpandedAndSelected);
+        mImpl.mCachedState.updateBubbleSuppressedState(b);
+    }
+
+    @VisibleForTesting
+    public void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
         // Lazy init stack view when a bubble is created
         ensureStackViewCreated();
         bubble.setInflateSynchronously(mInflateSynchronously);
@@ -1111,7 +1133,10 @@
     }
 
     @VisibleForTesting
-    public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) {
+    public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem) {
+        if (!fromSystem) {
+            return;
+        }
         // shouldBubbleUp checks canBubble & for bubble metadata
         boolean shouldBubble = shouldBubbleUp && canLaunchInTaskView(mContext, entry);
         if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
@@ -1172,9 +1197,9 @@
                 // notification, so that the bubble will be re-created if shouldBubbleUp returns
                 // true.
                 mBubbleData.dismissBubbleWithKey(key, DISMISS_NO_BUBBLE_UP);
-            } else if (entry != null && mTmpRanking.isBubble() && !isActive) {
+            } else if (entry != null && mTmpRanking.isBubble() && !isActiveOrInOverflow) {
                 entry.setFlagBubble(true);
-                onEntryUpdated(entry, shouldBubbleUp);
+                onEntryUpdated(entry, shouldBubbleUp, /* fromSystem= */ true);
             }
         }
     }
@@ -1773,9 +1798,9 @@
         }
 
         @Override
-        public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) {
+        public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem) {
             mMainExecutor.execute(() -> {
-                BubbleController.this.onEntryUpdated(entry, shouldBubbleUp);
+                BubbleController.this.onEntryUpdated(entry, shouldBubbleUp, fromSystem);
             });
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
index 9d3bf34..5dab8a0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 
@@ -65,4 +66,19 @@
             return null;
         }
     }
+
+    /**
+     * Creates the bitmap for the provided drawable and returns the scale used for
+     * drawing the actual drawable.
+     */
+    public Bitmap createIconBitmap(@NonNull Drawable icon, float[] outScale) {
+        if (outScale == null) {
+            outScale = new float[1];
+        }
+        icon = normalizeAndWrapToAdaptiveIcon(icon,
+                true /* shrinkNonAdaptiveIcons */,
+                null /* outscale */,
+                outScale);
+        return createIconBitmap(icon, outScale[0], BITMAP_GENERATION_MODE_WITH_SHADOW);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 69762c9..f437553 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -195,15 +195,18 @@
                     b.isImportantConversation());
             info.badgeBitmap = badgeBitmapInfo.icon;
             // Raw badge bitmap never includes the important conversation ring
-            info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon;
-            info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon;
+            info.mRawBadgeBitmap = b.isImportantConversation()
+                    ? badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon
+                    : badgeBitmapInfo.icon;
+
+            float[] bubbleBitmapScale = new float[1];
+            info.bubbleBitmap = iconFactory.createIconBitmap(bubbleDrawable, bubbleBitmapScale);
 
             // Dot color & placement
             Path iconPath = PathParser.createPathFromPathData(
                     c.getResources().getString(com.android.internal.R.string.config_icon_mask));
             Matrix matrix = new Matrix();
-            float scale = iconFactory.getNormalizer().getScale(bubbleDrawable,
-                    null /* outBounds */, null /* path */, null /* outMaskShape */);
+            float scale = bubbleBitmapScale[0];
             float radius = DEFAULT_PATH_SIZE / 2f;
             matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
                     radius /* pivot y */);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index cf792cd..37b96ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -171,8 +171,9 @@
      *
      * @param entry the {@link BubbleEntry} by the notification.
      * @param shouldBubbleUp {@code true} if this notification should bubble up.
+     * @param fromSystem {@code true} if this update is from NotificationManagerService.
      */
-    void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp);
+    void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem);
 
     /**
      * Called when new notification entry removed.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 40cf9a3..85c8ebf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -1130,16 +1130,16 @@
             boolean adjusted = false;
             if (mYOffsetForIme != 0) {
                 if (dividerLeash != null) {
-                    mTempRect.set(mDividerBounds);
+                    getRefDividerBounds(mTempRect);
                     mTempRect.offset(0, mYOffsetForIme);
                     t.setPosition(dividerLeash, mTempRect.left, mTempRect.top);
                 }
 
-                mTempRect.set(mBounds1);
+                getRefBounds1(mTempRect);
                 mTempRect.offset(0, mYOffsetForIme);
                 t.setPosition(leash1, mTempRect.left, mTempRect.top);
 
-                mTempRect.set(mBounds2);
+                getRefBounds2(mTempRect);
                 mTempRect.offset(0, mYOffsetForIme);
                 t.setPosition(leash2, mTempRect.left, mTempRect.top);
                 adjusted = true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
index 81904e2..e22c951 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
@@ -49,6 +49,7 @@
 import com.android.wm.shell.pip.tv.TvPipTransition;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.sysui.ShellController;
+import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 
 import java.util.Optional;
@@ -138,12 +139,14 @@
     @WMSingleton
     @Provides
     static PipTransitionController provideTvPipTransition(
-            Transitions transitions, ShellTaskOrganizer shellTaskOrganizer,
+            ShellInit shellInit,
+            ShellTaskOrganizer shellTaskOrganizer,
+            Transitions transitions,
             PipAnimationController pipAnimationController,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
             TvPipBoundsState tvPipBoundsState, TvPipMenuController pipMenuController) {
-        return new TvPipTransition(tvPipBoundsState, pipMenuController,
-                tvPipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer);
+        return new TvPipTransition(shellInit, shellTaskOrganizer, transitions, tvPipBoundsState,
+                pipMenuController, tvPipBoundsAlgorithm, pipAnimationController);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index e2bf767..d53451a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -409,15 +409,15 @@
     @WMSingleton
     @Provides
     static PipTransitionController providePipTransitionController(Context context,
-            Transitions transitions, ShellTaskOrganizer shellTaskOrganizer,
+            ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Transitions transitions,
             PipAnimationController pipAnimationController, PipBoundsAlgorithm pipBoundsAlgorithm,
             PipBoundsState pipBoundsState, PipTransitionState pipTransitionState,
             PhonePipMenuController pipMenuController,
             PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
             Optional<SplitScreenController> splitScreenOptional) {
-        return new PipTransition(context, pipBoundsState, pipTransitionState, pipMenuController,
-                pipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer,
-                pipSurfaceTransactionHelper, splitScreenOptional);
+        return new PipTransition(context, shellInit, shellTaskOrganizer, transitions,
+                pipBoundsState, pipTransitionState, pipMenuController, pipBoundsAlgorithm,
+                pipAnimationController, pipSurfaceTransactionHelper, splitScreenOptional);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index 20d7725..af205ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -122,7 +122,6 @@
                     break;
                 case WindowManager.TRANSIT_TO_BACK:
                 case WindowManager.TRANSIT_TO_FRONT:
-                    transitionHandled = true;
                     break;
             }
         }
@@ -147,7 +146,9 @@
             return false;
         }
         mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
-        return true;
+
+        // Intercepted transition to manage the window decorations. Let other handlers animate.
+        return false;
     }
 
     private boolean startCloseTransition(
@@ -164,7 +165,8 @@
             windowDecors.add(windowDecor);
         }
 
-        return true;
+        // Intercepted transition to manage the window decorations. Let other handlers animate.
+        return false;
     }
 
     private boolean startChangeTransition(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index cf2734c..81e49f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -183,7 +183,7 @@
         return mCurrentAnimator;
     }
 
-    PipTransitionAnimator getCurrentAnimator() {
+    public PipTransitionAnimator getCurrentAnimator() {
         return mCurrentAnimator;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 1155ea1..f747b5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -127,7 +127,7 @@
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final @NonNull PipMenuController mPipMenuController;
     private final PipAnimationController mPipAnimationController;
-    private final PipTransitionController mPipTransitionController;
+    protected final PipTransitionController mPipTransitionController;
     protected final PipParamsChangedForwarder mPipParamsChangedForwarder;
     private final PipUiEventLogger mPipUiEventLoggerLogger;
     private final int mEnterAnimationDuration;
@@ -196,6 +196,26 @@
         }
     };
 
+    @VisibleForTesting
+    final PipTransitionController.PipTransitionCallback mPipTransitionCallback =
+            new PipTransitionController.PipTransitionCallback() {
+                @Override
+                public void onPipTransitionStarted(int direction, Rect pipBounds) {}
+
+                @Override
+                public void onPipTransitionFinished(int direction) {
+                    // Apply the deferred RunningTaskInfo if applicable after all proper callbacks
+                    // are sent.
+                    if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) {
+                        onTaskInfoChanged(mDeferredTaskInfo);
+                        mDeferredTaskInfo = null;
+                    }
+                }
+
+                @Override
+                public void onPipTransitionCanceled(int direction) {}
+            };
+
     private final PipAnimationController.PipTransactionHandler mPipTransactionHandler =
             new PipAnimationController.PipTransactionHandler() {
                 @Override
@@ -216,7 +236,7 @@
     private ActivityManager.RunningTaskInfo mDeferredTaskInfo;
     private WindowContainerToken mToken;
     private SurfaceControl mLeash;
-    private PipTransitionState mPipTransitionState;
+    protected PipTransitionState mPipTransitionState;
     private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
     private long mLastOneShotAlphaAnimationTime;
     private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
@@ -296,6 +316,7 @@
         mTaskOrganizer.addFocusListener(this);
         mPipTransitionController.setPipOrganizer(this);
         displayController.addDisplayWindowListener(this);
+        pipTransitionController.registerPipTransitionCallback(mPipTransitionCallback);
     }
 
     public PipTransitionController getTransitionController() {
@@ -773,11 +794,6 @@
             mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
         }
         mPipTransitionController.sendOnPipTransitionFinished(direction);
-        // Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent.
-        if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) {
-            onTaskInfoChanged(mDeferredTaskInfo);
-            mDeferredTaskInfo = null;
-        }
     }
 
     private void sendOnPipTransitionCancelled(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 51be2a5..33761d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -66,6 +66,7 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.CounterRotatorHelper;
 import com.android.wm.shell.transition.Transitions;
 
@@ -107,17 +108,18 @@
     private boolean mHasFadeOut;
 
     public PipTransition(Context context,
+            @NonNull ShellInit shellInit,
+            @NonNull ShellTaskOrganizer shellTaskOrganizer,
+            @NonNull Transitions transitions,
             PipBoundsState pipBoundsState,
             PipTransitionState pipTransitionState,
             PipMenuController pipMenuController,
             PipBoundsAlgorithm pipBoundsAlgorithm,
             PipAnimationController pipAnimationController,
-            Transitions transitions,
-            @NonNull ShellTaskOrganizer shellTaskOrganizer,
             PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
             Optional<SplitScreenController> splitScreenOptional) {
-        super(pipBoundsState, pipMenuController, pipBoundsAlgorithm,
-                pipAnimationController, transitions, shellTaskOrganizer);
+        super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
+                pipBoundsAlgorithm, pipAnimationController);
         mContext = context;
         mPipTransitionState = pipTransitionState;
         mEnterExitAnimationDuration = context.getResources()
@@ -315,7 +317,8 @@
     }
 
     @Override
-    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {
         if (transition != mExitTransition) {
             return;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 90a2695..f51e247 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -38,6 +38,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 
 import java.util.ArrayList;
@@ -131,10 +132,13 @@
     public void onFixedRotationStarted() {
     }
 
-    public PipTransitionController(PipBoundsState pipBoundsState,
+    public PipTransitionController(
+            @NonNull ShellInit shellInit,
+            @NonNull ShellTaskOrganizer shellTaskOrganizer,
+            @NonNull Transitions transitions,
+            PipBoundsState pipBoundsState,
             PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm,
-            PipAnimationController pipAnimationController, Transitions transitions,
-            @android.annotation.NonNull ShellTaskOrganizer shellTaskOrganizer) {
+            PipAnimationController pipAnimationController) {
         mPipBoundsState = pipBoundsState;
         mPipMenuController = pipMenuController;
         mShellTaskOrganizer = shellTaskOrganizer;
@@ -142,10 +146,14 @@
         mPipAnimationController = pipAnimationController;
         mTransitions = transitions;
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
-            transitions.addHandler(this);
+            shellInit.addInitCallback(this::onInit, this);
         }
     }
 
+    private void onInit() {
+        mTransitions.addHandler(this);
+    }
+
     void setPipOrganizer(PipTaskOrganizer pto) {
         mPipOrganizer = pto;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
index 5062cc4..8ebcf63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
@@ -32,6 +32,7 @@
 import com.android.wm.shell.pip.PipBoundsState;
 import com.android.wm.shell.pip.PipMenuController;
 import com.android.wm.shell.pip.PipTransitionController;
+import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 
 /**
@@ -39,14 +40,16 @@
  * TODO: Implement animation once TV is using Transitions.
  */
 public class TvPipTransition extends PipTransitionController {
-    public TvPipTransition(PipBoundsState pipBoundsState,
+    public TvPipTransition(
+            @NonNull ShellInit shellInit,
+            @NonNull ShellTaskOrganizer shellTaskOrganizer,
+            @NonNull Transitions transitions,
+            PipBoundsState pipBoundsState,
             PipMenuController pipMenuController,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
-            PipAnimationController pipAnimationController,
-            Transitions transitions,
-            @NonNull ShellTaskOrganizer shellTaskOrganizer) {
-        super(pipBoundsState, pipMenuController, tvPipBoundsAlgorithm, pipAnimationController,
-                transitions, shellTaskOrganizer);
+            PipAnimationController pipAnimationController) {
+        super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
+                tvPipBoundsAlgorithm, pipAnimationController);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index de7e7bd..8de649e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -21,6 +21,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
 
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -90,7 +91,6 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -337,17 +337,39 @@
     }
 
     public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) {
+        final int[] result = new int[1];
+        IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
+            @Override
+            public void onAnimationStart(@WindowManager.TransitionOldType int transit,
+                    RemoteAnimationTarget[] apps,
+                    RemoteAnimationTarget[] wallpapers,
+                    RemoteAnimationTarget[] nonApps,
+                    final IRemoteAnimationFinishedCallback finishedCallback) {
+                try {
+                    finishedCallback.onAnimationFinished();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to invoke onAnimationFinished", e);
+                }
+                if (result[0] == START_SUCCESS || result[0] == START_TASK_TO_FRONT) {
+                    final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+                    mStageCoordinator.prepareEvictNonOpeningChildTasks(position, apps, evictWct);
+                    mSyncQueue.queue(evictWct);
+                }
+            }
+            @Override
+            public void onAnimationCancelled(boolean isKeyguardOccluded) {
+            }
+        };
         options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
                 null /* wct */);
+        RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
+                0 /* duration */, 0 /* statusBarTransitionDelay */);
+        ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+        activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
 
         try {
-            final WindowContainerTransaction evictWct = new WindowContainerTransaction();
-            mStageCoordinator.prepareEvictChildTasks(position, evictWct);
-            final int result =
-                    ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
-            if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
-                mSyncQueue.queue(evictWct);
-            }
+            result[0] = ActivityTaskManager.getService().startActivityFromRecents(taskId,
+                    activityOptions.toBundle());
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to launch task", e);
         }
@@ -453,12 +475,12 @@
             mStageCoordinator.prepareEvictInvisibleChildTasks(wct);
             mSyncQueue.queue(wct);
         }
-        return reparentSplitTasksForAnimation(apps, true /*splitExpectedToBeVisible*/);
+        return reparentSplitTasksForAnimation(apps, false /* enterSplitScreen */);
     }
 
     RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
         try {
-            return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/);
+            return reparentSplitTasksForAnimation(apps, true /* enterSplitScreen */);
         } finally {
             for (RemoteAnimationTarget appTarget : apps) {
                 if (appTarget.leash != null) {
@@ -469,14 +491,23 @@
     }
 
     private RemoteAnimationTarget[] reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,
-            boolean splitExpectedToBeVisible) {
+            boolean enterSplitScreen) {
         if (ENABLE_SHELL_TRANSITIONS) return null;
-        // TODO(b/206487881): Integrate this with shell transition.
-        if (splitExpectedToBeVisible && !isSplitScreenVisible()) return null;
-        // Split not visible, but not enough apps to have split, also return null
-        if (!splitExpectedToBeVisible && apps.length < 2) return null;
 
-        SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+        if (enterSplitScreen) {
+            int openingApps = 0;
+            for (int i = 0; i < apps.length; ++i) {
+                if (apps[i].mode == MODE_OPENING) openingApps++;
+            }
+            if (openingApps < 2) {
+                // Not having enough apps to enter split screen
+                return null;
+            }
+        } else if (!isSplitScreenVisible()) {
+            return null;
+        }
+
+        final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
         if (mSplitTasksContainerLayer != null) {
             // Remove the previous layer before recreating
             transaction.remove(mSplitTasksContainerLayer);
@@ -489,17 +520,14 @@
         mRootTDAOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, builder);
         mSplitTasksContainerLayer = builder.build();
 
-        // Ensure that we order these in the parent in the right z-order as their previous order
-        Arrays.sort(apps, (a1, a2) -> a1.prefixOrderIndex - a2.prefixOrderIndex);
-        int layer = 1;
-        for (RemoteAnimationTarget appTarget : apps) {
+        for (int i = 0; i < apps.length; ++i) {
+            final RemoteAnimationTarget appTarget = apps[i];
             transaction.reparent(appTarget.leash, mSplitTasksContainerLayer);
             transaction.setPosition(appTarget.leash, appTarget.screenSpaceBounds.left,
                     appTarget.screenSpaceBounds.top);
-            transaction.setLayer(appTarget.leash, layer++);
         }
         transaction.apply();
-        transaction.close();
+        mTransactionPool.release(transaction);
         return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
     }
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 83bdf8b..d7ca791 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -94,6 +94,7 @@
             @NonNull WindowContainerToken topRoot) {
         mFinishCallback = finishCallback;
         mAnimatingTransition = transition;
+        mFinishTransaction = finishTransaction;
         if (mPendingRemoteHandler != null) {
             mPendingRemoteHandler.startAnimation(transition, info, startTransaction,
                     finishTransaction, mRemoteFinishCB);
@@ -107,8 +108,6 @@
     private void playInternalAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull WindowContainerToken mainRoot,
             @NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) {
-        mFinishTransaction = mTransactionPool.acquire();
-
         // Play some place-holder fade animations
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
@@ -287,16 +286,14 @@
         return true;
     }
 
-    void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+    void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {
         if (isPendingEnter(transition)) {
             if (!aborted) {
                 // An enter transition got merged, appends the rest operations to finish entering
                 // split screen.
-                // TODO (b/238856352): Passed-in the proper finish transition to merge instead.
-                if (mFinishTransaction == null) {
-                    mFinishTransaction = mTransactionPool.acquire();
-                }
-                mStageCoordinator.finishEnterSplitScreen(mFinishTransaction);
+                mStageCoordinator.finishEnterSplitScreen(finishT);
+                mPendingRemoteHandler = null;
             }
 
             mPendingEnter.mCallback.onTransitionConsumed(aborted);
@@ -339,11 +336,6 @@
         mAnimatingTransition = null;
 
         mOnFinish.run();
-        if (mFinishTransaction != null) {
-            mFinishTransaction.apply();
-            mTransactionPool.release(mFinishTransaction);
-            mFinishTransaction = null;
-        }
         if (mFinishCallback != null) {
             mFinishCallback.onTransitionFinished(wct /* wct */, wctCB /* wctCB */);
             mFinishCallback = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index f2340d5..8e1ae39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -233,6 +233,7 @@
                 if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
                         && (mMainStage.containsContainer(container)
                         || mSideStage.containsContainer(container))) {
+                    updateSurfaceBounds(mSplitLayout, finishT, false /* applyResizingOffset */);
                     setDividerVisibility(true, finishT);
                     return;
                 }
@@ -451,10 +452,16 @@
                     IRemoteAnimationFinishedCallback finishedCallback,
                     SurfaceControl.Transaction t) {
                 if (apps == null || apps.length == 0) {
-                    // Switch the split position if launching as MULTIPLE_TASK failed.
-                    if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
-                        setSideStagePosition(SplitLayout.reversePosition(
-                                getSideStagePosition()), null);
+                    if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+                        mMainExecutor.execute(() ->
+                                exitSplitScreen(mMainStage.getChildCount() == 0
+                                        ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+                    } else {
+                        // Switch the split position if launching as MULTIPLE_TASK failed.
+                        if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
+                            setSideStagePosition(SplitLayout.reversePosition(
+                                    getSideStagePosition()), null);
+                        }
                     }
 
                     // Do nothing when the animation was cancelled.
@@ -650,7 +657,7 @@
         mShouldUpdateRecents = true;
         // If any stage has no child after animation finished, it means that split will display
         // nothing, such status will happen if task and intent is same app but not support
-        // multi-instagce, we should exit split and expand that app as full screen.
+        // multi-instance, we should exit split and expand that app as full screen.
         if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
             mMainExecutor.execute(() ->
                     exitSplitScreen(mMainStage.getChildCount() == 0
@@ -1742,8 +1749,9 @@
     }
 
     @Override
-    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
-        mSplitTransitions.onTransitionConsumed(transition, aborted);
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {
+        mSplitTransitions.onTransitionConsumed(transition, aborted, finishT);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index f414d69..1af9415 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -33,6 +33,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
@@ -376,7 +377,13 @@
             SurfaceControl leash, boolean firstAppeared) {
         final Point taskPositionInParent = taskInfo.positionInParent;
         mSyncQueue.runInSync(t -> {
-            t.setWindowCrop(leash, null);
+            // The task surface might be released before running in the sync queue for the case like
+            // trampoline launch, so check if the surface is valid before processing it.
+            if (!leash.isValid()) {
+                Slog.w(TAG, "Skip updating invalid child task surface of task#" + taskInfo.taskId);
+                return;
+            }
+            t.setCrop(leash, null);
             t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
             if (firstAppeared && !ENABLE_SHELL_TRANSITIONS) {
                 t.setAlpha(leash, 1f);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 11b453c..5cce6b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -274,7 +274,8 @@
     }
 
     @Override
-    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {
         MixedTransition mixed = null;
         for (int i = mActiveTransitions.size() - 1; i >= 0; --i) {
             if (mActiveTransitions.get(i).mTransition != transition) continue;
@@ -283,7 +284,7 @@
         }
         if (mixed == null) return;
         if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
-            mPipHandler.onTransitionConsumed(transition, aborted);
+            mPipHandler.onTransitionConsumed(transition, aborted, finishT);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index cedb340..9469529 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -82,7 +82,8 @@
     }
 
     @Override
-    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {
         mRequestedRemotes.remove(transition);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index cd29741..279d57a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -159,8 +159,10 @@
     private void onInit() {
         // The very last handler (0 in the list) should be the default one.
         mHandlers.add(mDefaultTransitionHandler);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Default");
         // Next lowest priority is remote transitions.
         mHandlers.add(mRemoteTransitionHandler);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote");
 
         ContentResolver resolver = mContext.getContentResolver();
         mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
@@ -206,7 +208,13 @@
      * @see TransitionHandler
      */
     public void addHandler(@NonNull TransitionHandler handler) {
+        if (mHandlers.isEmpty()) {
+            throw new RuntimeException("Unexpected handler added prior to initialization, please "
+                    + "use ShellInit callbacks to ensure proper ordering");
+        }
         mHandlers.add(handler);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: %s",
+                handler.getClass().getSimpleName());
     }
 
     public ShellExecutor getMainExecutor() {
@@ -535,7 +543,8 @@
             active.mMerged = true;
             active.mAborted = abort;
             if (active.mHandler != null) {
-                active.mHandler.onTransitionConsumed(active.mToken, abort);
+                active.mHandler.onTransitionConsumed(
+                        active.mToken, abort, abort ? null : active.mFinishT);
             }
             return;
         }
@@ -543,7 +552,8 @@
         active.mAborted = abort;
         if (active.mAborted && active.mHandler != null) {
             // Notifies to clean-up the aborted transition.
-            active.mHandler.onTransitionConsumed(transition, true /* aborted */);
+            active.mHandler.onTransitionConsumed(
+                    transition, true /* aborted */, null /* finishTransaction */);
         }
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                 "Transition animation finished (abort=%b), notifying core %s", abort, transition);
@@ -579,7 +589,8 @@
             ActiveTransition aborted = mActiveTransitions.remove(activeIdx);
             // Notifies to clean-up the aborted transition.
             if (aborted.mHandler != null) {
-                aborted.mHandler.onTransitionConsumed(transition, true /* aborted */);
+                aborted.mHandler.onTransitionConsumed(
+                        transition, true /* aborted */, null /* finishTransaction */);
             }
             mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */);
         }
@@ -765,8 +776,13 @@
          * Called when a transition which was already "claimed" by this handler has been merged
          * into another animation or has been aborted. Gives this handler a chance to clean-up any
          * expectations.
+         *
+         * @param transition The transition been consumed.
+         * @param aborted Whether the transition is aborted or not.
+         * @param finishTransaction The transaction to be applied after the transition animated.
          */
-        default void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) { }
+        default void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+                @Nullable SurfaceControl.Transaction finishTransaction) { }
 
         /**
          * Sets transition animation scale settings value to handler.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 4380bdc..506a4c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -66,6 +66,7 @@
     final DisplayController mDisplayController;
     final ShellTaskOrganizer mTaskOrganizer;
     final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
+    final Supplier<WindowContainerTransaction> mWindowContainerTransactionSupplier;
     final SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
     private final DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
             new DisplayController.OnDisplaysChangedListener() {
@@ -102,7 +103,8 @@
             RunningTaskInfo taskInfo,
             SurfaceControl taskSurface) {
         this(context, displayController, taskOrganizer, taskInfo, taskSurface,
-                SurfaceControl.Builder::new, new SurfaceControlViewHostFactory() {});
+                SurfaceControl.Builder::new, WindowContainerTransaction::new,
+                new SurfaceControlViewHostFactory() {});
     }
 
     WindowDecoration(
@@ -112,6 +114,7 @@
             RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+            Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
             SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
         mContext = context;
         mDisplayController = displayController;
@@ -119,6 +122,7 @@
         mTaskInfo = taskInfo;
         mTaskSurface = taskSurface;
         mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
+        mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
         mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
 
         mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
@@ -229,7 +233,9 @@
         mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
         startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
                 .setShadowRadius(mTaskBackgroundSurface, shadowRadius)
-                .setColor(mTaskBackgroundSurface, mTmpColor);
+                .setColor(mTaskBackgroundSurface, mTmpColor)
+                .setLayer(mTaskBackgroundSurface, -1)
+                .show(mTaskBackgroundSurface);
 
         // Caption view
         mCaptionWindowManager.setConfiguration(taskConfig);
@@ -301,6 +307,10 @@
             mTaskBackgroundSurface.release();
             mTaskBackgroundSurface = null;
         }
+
+        final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
+        wct.removeInsetsProvider(mTaskInfo.token, CAPTION_INSETS_TYPES);
+        mTaskOrganizer.applyTransaction(wct);
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 857f578..579638d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -21,13 +21,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityManager;
@@ -70,7 +70,7 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class PipTaskOrganizerTest extends ShellTestCase {
-    private PipTaskOrganizer mSpiedPipTaskOrganizer;
+    private PipTaskOrganizer mPipTaskOrganizer;
 
     @Mock private DisplayController mMockDisplayController;
     @Mock private SyncTransactionQueue mMockSyncTransactionQueue;
@@ -100,14 +100,15 @@
         mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
                 new PipSnapAlgorithm());
         mMainExecutor = new TestShellExecutor();
-        mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext,
+        mPipTaskOrganizer = new PipTaskOrganizer(mContext,
                 mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
                 mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController,
                 mMockPipSurfaceTransactionHelper, mMockPipTransitionController,
                 mMockPipParamsChangedForwarder, mMockOptionalSplitScreen, mMockDisplayController,
-                mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor));
+                mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor);
         mMainExecutor.flushAll();
         preparePipTaskOrg();
+        preparePipSurfaceTransactionHelper();
     }
 
     @Test
@@ -124,14 +125,14 @@
     public void startSwipePipToHome_updatesAspectRatio() {
         final Rational aspectRatio = new Rational(2, 1);
 
-        mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio));
+        mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio));
 
         assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
     }
 
     @Test
     public void startSwipePipToHome_updatesLastPipComponentName() {
-        mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null));
+        mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null));
 
         assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
     }
@@ -140,7 +141,7 @@
     public void startSwipePipToHome_updatesOverrideMinSize() {
         final Size minSize = new Size(400, 320);
 
-        mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize),
+        mPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize),
                 createPipParams(null));
 
         assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
@@ -150,7 +151,7 @@
     public void onTaskAppeared_updatesAspectRatio() {
         final Rational aspectRatio = new Rational(2, 1);
 
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(aspectRatio)), mock(SurfaceControl.class));
 
         assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
@@ -158,7 +159,7 @@
 
     @Test
     public void onTaskAppeared_updatesLastPipComponentName() {
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
                 mock(SurfaceControl.class));
 
         assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
@@ -168,7 +169,7 @@
     public void onTaskAppeared_updatesOverrideMinSize() {
         final Size minSize = new Size(400, 320);
 
-        mSpiedPipTaskOrganizer.onTaskAppeared(
+        mPipTaskOrganizer.onTaskAppeared(
                 createTaskInfo(mComponent1, createPipParams(null), minSize),
                 mock(SurfaceControl.class));
 
@@ -179,16 +180,16 @@
     public void onTaskInfoChanged_notInPip_deferUpdatesAspectRatio() {
         final Rational startAspectRatio = new Rational(2, 1);
         final Rational newAspectRatio = new Rational(1, 2);
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(startAspectRatio)), mock(SurfaceControl.class));
 
         // It is in entering transition, should defer onTaskInfoChanged callback in this case.
-        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
                 createPipParams(newAspectRatio)));
         verify(mMockPipParamsChangedForwarder, never()).notifyAspectRatioChanged(anyFloat());
 
         // Once the entering transition finishes, the new aspect ratio applies in a deferred manner
-        mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+        sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
         verify(mMockPipParamsChangedForwarder)
                 .notifyAspectRatioChanged(newAspectRatio.floatValue());
     }
@@ -197,11 +198,11 @@
     public void onTaskInfoChanged_inPip_updatesAspectRatioIfChanged() {
         final Rational startAspectRatio = new Rational(2, 1);
         final Rational newAspectRatio = new Rational(1, 2);
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(startAspectRatio)), mock(SurfaceControl.class));
-        mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+        sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
-        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
                 createPipParams(newAspectRatio)));
 
         verify(mMockPipParamsChangedForwarder)
@@ -210,11 +211,11 @@
 
     @Test
     public void onTaskInfoChanged_inPip_updatesLastPipComponentName() {
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(null)), mock(SurfaceControl.class));
-        mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+        sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
-        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
+        mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
                 createPipParams(null)));
 
         assertEquals(mComponent2, mPipBoundsState.getLastPipComponentName());
@@ -222,12 +223,12 @@
 
     @Test
     public void onTaskInfoChanged_inPip_updatesOverrideMinSize() {
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(null)), mock(SurfaceControl.class));
-        mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+        sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
 
         final Size minSize = new Size(400, 320);
-        mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
+        mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
                 createPipParams(null), minSize));
 
         assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
@@ -235,23 +236,42 @@
 
     @Test
     public void onTaskVanished_clearsPipBounds() {
-        mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+        mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
                 createPipParams(null)), mock(SurfaceControl.class));
         mPipBoundsState.setBounds(new Rect(100, 100, 200, 150));
 
-        mSpiedPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null)));
+        mPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null)));
         assertTrue(mPipBoundsState.getBounds().isEmpty());
     }
 
+    private void sendOnPipTransitionFinished(
+            @PipAnimationController.TransitionDirection int direction) {
+        mPipTaskOrganizer.sendOnPipTransitionFinished(direction);
+        // PipTransitionController will call back into PipTaskOrganizer.
+        mPipTaskOrganizer.mPipTransitionCallback.onPipTransitionFinished(direction);
+    }
+
     private void preparePipTaskOrg() {
         final DisplayInfo info = new DisplayInfo();
         mPipBoundsState.setDisplayLayout(new DisplayLayout(info,
                 mContext.getResources(), true, true));
-        mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
-        mSpiedPipTaskOrganizer.setSurfaceControlTransactionFactory(
+        mPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
+        mPipTaskOrganizer.setSurfaceControlTransactionFactory(
                 MockSurfaceControlHelper::createMockSurfaceControlTransaction);
-        doNothing().when(mSpiedPipTaskOrganizer).enterPipWithAlphaAnimation(any(), anyLong());
-        doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any());
+    }
+
+    private void preparePipSurfaceTransactionHelper() {
+        doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+                .crop(any(), any(), any());
+        doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+                .resetScale(any(), any(), any());
+        doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+                .round(any(), any(), anyBoolean());
+        doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+                .scale(any(), any(), any(), any(), anyFloat());
+        doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+                .alpha(any(), any(), anyFloat());
+        doNothing().when(mMockPipSurfaceTransactionHelper).onDensityOrFontScaleChanged(any());
     }
 
     private static ActivityManager.RunningTaskInfo createTaskInfo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b318bb2..226843e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -204,6 +204,8 @@
         verify(mMockSurfaceControlStartT)
                 .setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f});
         verify(mMockSurfaceControlStartT).setShadowRadius(taskBackgroundSurface, 10);
+        verify(mMockSurfaceControlStartT).setLayer(taskBackgroundSurface, -1);
+        verify(mMockSurfaceControlStartT).show(taskBackgroundSurface);
 
         verify(mMockSurfaceControlViewHostFactory)
                 .create(any(), eq(defaultDisplay), any(), anyBoolean());
@@ -233,6 +235,57 @@
     }
 
     @Test
+    public void testLayoutResultCalculation_visibleFocusedTaskToInvisible() {
+        final Display defaultDisplay = mock(Display.class);
+        doReturn(defaultDisplay).when(mMockDisplayController)
+                .getDisplay(Display.DEFAULT_DISPLAY);
+
+        final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+        final SurfaceControl.Builder decorContainerSurfaceBuilder =
+                createMockSurfaceControlBuilder(decorContainerSurface);
+        mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+        final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class);
+        final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
+                createMockSurfaceControlBuilder(taskBackgroundSurface);
+        mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+
+        final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+                new ActivityManager.TaskDescription.Builder()
+                        .setBackgroundColor(Color.YELLOW);
+        final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+                .setDisplayId(Display.DEFAULT_DISPLAY)
+                .setTaskDescriptionBuilder(taskDescriptionBuilder)
+                .setBounds(TASK_BOUNDS)
+                .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+                .setVisible(true)
+                .build();
+        taskInfo.isFocused = true;
+        // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is
+        // 64px.
+        taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+        mOutsetsDp.set(10, 20, 30, 40);
+
+        final SurfaceControl taskSurface = mock(SurfaceControl.class);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+        windowDecor.relayout(taskInfo);
+
+        verify(mMockSurfaceControlViewHost, never()).release();
+        verify(decorContainerSurface, never()).release();
+        verify(taskBackgroundSurface, never()).release();
+        verify(mMockWindowContainerTransaction, never())
+                .removeInsetsProvider(eq(taskInfo.token), any());
+
+        taskInfo.isVisible = false;
+        windowDecor.relayout(taskInfo);
+
+        verify(mMockSurfaceControlViewHost).release();
+        verify(decorContainerSurface).release();
+        verify(taskBackgroundSurface).release();
+        verify(mMockWindowContainerTransaction).removeInsetsProvider(eq(taskInfo.token), any());
+    }
+
+    @Test
     public void testNotCrashWhenDisplayAppearsAfterTask() {
         doReturn(mock(Display.class)).when(mMockDisplayController)
                 .getDisplay(Display.DEFAULT_DISPLAY);
@@ -282,7 +335,7 @@
             ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
         return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
                 taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(),
-                mMockSurfaceControlViewHostFactory);
+                () -> mMockWindowContainerTransaction, mMockSurfaceControlViewHostFactory);
     }
 
     private class MockSurfaceControlBuilderSupplier implements Supplier<SurfaceControl.Builder> {
@@ -313,9 +366,11 @@
                 ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
                 SurfaceControl taskSurface,
                 Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+                Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
                 SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
             super(context, displayController, taskOrganizer, taskInfo, taskSurface,
-                    surfaceControlBuilderSupplier, surfaceControlViewHostFactory);
+                    surfaceControlBuilderSupplier, windowContainerTransactionSupplier,
+                    surfaceControlViewHostFactory);
         }
 
         @Override
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index 6a7119b..f5ed568 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -380,18 +380,6 @@
     env->SetStaticObjectField(cls, fid, typeface);
 }
 
-// Critical Native
-static jint Typeface_getFamilySize(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
-    return toTypeface(faceHandle)->fFontCollection->getFamilyCount();
-}
-
-// Critical Native
-static jlong Typeface_getFamily(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle, jint index) {
-    std::shared_ptr<minikin::FontFamily> family =
-            toTypeface(faceHandle)->fFontCollection->getFamilyAt(index);
-    return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
-}
-
 // Regular JNI
 static void Typeface_warmUpCache(JNIEnv* env, jobject, jstring jFilePath) {
     ScopedUtfChars filePath(env, jFilePath);
@@ -431,8 +419,6 @@
         {"nativeReadTypefaces", "(Ljava/nio/ByteBuffer;I)[J", (void*)Typeface_readTypefaces},
         {"nativeForceSetStaticFinalField", "(Ljava/lang/String;Landroid/graphics/Typeface;)V",
          (void*)Typeface_forceSetStaticFinalField},
-        {"nativeGetFamilySize", "(J)I", (void*)Typeface_getFamilySize},
-        {"nativeGetFamily", "(JI)J", (void*)Typeface_getFamily},
         {"nativeWarmUpCache", "(Ljava/lang/String;)V", (void*)Typeface_warmUpCache},
         {"nativeAddFontCollections", "(J)V", (void*)Typeface_addFontCollection},
         {"nativeRegisterLocaleList", "(Ljava/lang/String;)V", (void*)Typeface_registerLocaleList},
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7b27358..53d4efa 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -45,6 +45,7 @@
 import java.nio.ReadOnlyBufferException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1811,7 +1812,7 @@
                     synchronized(mBufferLock) {
                         switch (mBufferMode) {
                             case BUFFER_MODE_LEGACY:
-                                validateInputByteBuffer(mCachedInputBuffers, index);
+                                validateInputByteBufferLocked(mCachedInputBuffers, index);
                                 break;
                             case BUFFER_MODE_BLOCK:
                                 while (mQueueRequests.size() <= index) {
@@ -1840,7 +1841,7 @@
                     synchronized(mBufferLock) {
                         switch (mBufferMode) {
                             case BUFFER_MODE_LEGACY:
-                                validateOutputByteBuffer(mCachedOutputBuffers, index, info);
+                                validateOutputByteBufferLocked(mCachedOutputBuffers, index, info);
                                 break;
                             case BUFFER_MODE_BLOCK:
                                 while (mOutputFrames.size() <= index) {
@@ -2328,10 +2329,6 @@
      */
     public final void start() {
         native_start();
-        synchronized(mBufferLock) {
-            cacheBuffers(true /* input */);
-            cacheBuffers(false /* input */);
-        }
     }
     private native final void native_start();
 
@@ -2388,8 +2385,10 @@
      */
     public final void flush() {
         synchronized(mBufferLock) {
-            invalidateByteBuffers(mCachedInputBuffers);
-            invalidateByteBuffers(mCachedOutputBuffers);
+            invalidateByteBuffersLocked(mCachedInputBuffers);
+            invalidateByteBuffersLocked(mCachedOutputBuffers);
+            mValidInputIndices.clear();
+            mValidOutputIndices.clear();
             mDequeuedInputBuffers.clear();
             mDequeuedOutputBuffers.clear();
         }
@@ -2673,14 +2672,14 @@
                         + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
                         + "Please use getQueueRequest() to queue buffers");
             }
-            invalidateByteBuffer(mCachedInputBuffers, index);
+            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
             mDequeuedInputBuffers.remove(index);
         }
         try {
             native_queueInputBuffer(
                     index, offset, size, presentationTimeUs, flags);
         } catch (CryptoException | IllegalStateException e) {
-            revalidateByteBuffer(mCachedInputBuffers, index);
+            revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
             throw e;
         }
     }
@@ -2943,14 +2942,14 @@
                         + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
                         + "Please use getQueueRequest() to queue buffers");
             }
-            invalidateByteBuffer(mCachedInputBuffers, index);
+            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
             mDequeuedInputBuffers.remove(index);
         }
         try {
             native_queueSecureInputBuffer(
                     index, offset, info, presentationTimeUs, flags);
         } catch (CryptoException | IllegalStateException e) {
-            revalidateByteBuffer(mCachedInputBuffers, index);
+            revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
             throw e;
         }
     }
@@ -2984,7 +2983,7 @@
         int res = native_dequeueInputBuffer(timeoutUs);
         if (res >= 0) {
             synchronized(mBufferLock) {
-                validateInputByteBuffer(mCachedInputBuffers, res);
+                validateInputByteBufferLocked(mCachedInputBuffers, res);
             }
         }
         return res;
@@ -3581,10 +3580,10 @@
         int res = native_dequeueOutputBuffer(info, timeoutUs);
         synchronized (mBufferLock) {
             if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
-                cacheBuffers(false /* input */);
+                cacheBuffersLocked(false /* input */);
             } else if (res >= 0) {
-                validateOutputByteBuffer(mCachedOutputBuffers, res, info);
-                if (mHasSurface) {
+                validateOutputByteBufferLocked(mCachedOutputBuffers, res, info);
+                if (mHasSurface || mCachedOutputBuffers == null) {
                     mDequeuedOutputInfos.put(res, info.dup());
                 }
             }
@@ -3678,9 +3677,9 @@
         synchronized(mBufferLock) {
             switch (mBufferMode) {
                 case BUFFER_MODE_LEGACY:
-                    invalidateByteBuffer(mCachedOutputBuffers, index);
+                    invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
                     mDequeuedOutputBuffers.remove(index);
-                    if (mHasSurface) {
+                    if (mHasSurface || mCachedOutputBuffers == null) {
                         info = mDequeuedOutputInfos.remove(index);
                     }
                     break;
@@ -3832,15 +3831,24 @@
 
     private ByteBuffer[] mCachedInputBuffers;
     private ByteBuffer[] mCachedOutputBuffers;
+    private BitSet mValidInputIndices = new BitSet();
+    private BitSet mValidOutputIndices = new BitSet();
+
     private final BufferMap mDequeuedInputBuffers = new BufferMap();
     private final BufferMap mDequeuedOutputBuffers = new BufferMap();
     private final Map<Integer, BufferInfo> mDequeuedOutputInfos =
         new HashMap<Integer, BufferInfo>();
     final private Object mBufferLock;
 
-    private final void invalidateByteBuffer(
-            @Nullable ByteBuffer[] buffers, int index) {
-        if (buffers != null && index >= 0 && index < buffers.length) {
+    private void invalidateByteBufferLocked(
+            @Nullable ByteBuffer[] buffers, int index, boolean input) {
+        if (buffers == null) {
+            if (index < 0) {
+                throw new IllegalStateException("index is negative (" + index + ")");
+            }
+            BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+            indices.clear(index);
+        } else if (index >= 0 && index < buffers.length) {
             ByteBuffer buffer = buffers[index];
             if (buffer != null) {
                 buffer.setAccessible(false);
@@ -3848,9 +3856,14 @@
         }
     }
 
-    private final void validateInputByteBuffer(
+    private void validateInputByteBufferLocked(
             @Nullable ByteBuffer[] buffers, int index) {
-        if (buffers != null && index >= 0 && index < buffers.length) {
+        if (buffers == null) {
+            if (index < 0) {
+                throw new IllegalStateException("index is negative (" + index + ")");
+            }
+            mValidInputIndices.set(index);
+        } else if (index >= 0 && index < buffers.length) {
             ByteBuffer buffer = buffers[index];
             if (buffer != null) {
                 buffer.setAccessible(true);
@@ -3859,10 +3872,16 @@
         }
     }
 
-    private final void revalidateByteBuffer(
-            @Nullable ByteBuffer[] buffers, int index) {
+    private void revalidateByteBuffer(
+            @Nullable ByteBuffer[] buffers, int index, boolean input) {
         synchronized(mBufferLock) {
-            if (buffers != null && index >= 0 && index < buffers.length) {
+            if (buffers == null) {
+                if (index < 0) {
+                    throw new IllegalStateException("index is negative (" + index + ")");
+                }
+                BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+                indices.set(index);
+            } else if (index >= 0 && index < buffers.length) {
                 ByteBuffer buffer = buffers[index];
                 if (buffer != null) {
                     buffer.setAccessible(true);
@@ -3871,9 +3890,14 @@
         }
     }
 
-    private final void validateOutputByteBuffer(
+    private void validateOutputByteBufferLocked(
             @Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
-        if (buffers != null && index >= 0 && index < buffers.length) {
+        if (buffers == null) {
+            if (index < 0) {
+                throw new IllegalStateException("index is negative (" + index + ")");
+            }
+            mValidOutputIndices.set(index);
+        } else if (index >= 0 && index < buffers.length) {
             ByteBuffer buffer = buffers[index];
             if (buffer != null) {
                 buffer.setAccessible(true);
@@ -3882,7 +3906,7 @@
         }
     }
 
-    private final void invalidateByteBuffers(@Nullable ByteBuffer[] buffers) {
+    private void invalidateByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
         if (buffers != null) {
             for (ByteBuffer buffer: buffers) {
                 if (buffer != null) {
@@ -3892,27 +3916,29 @@
         }
     }
 
-    private final void freeByteBuffer(@Nullable ByteBuffer buffer) {
+    private void freeByteBufferLocked(@Nullable ByteBuffer buffer) {
         if (buffer != null /* && buffer.isDirect() */) {
             // all of our ByteBuffers are direct
             java.nio.NioUtils.freeDirectBuffer(buffer);
         }
     }
 
-    private final void freeByteBuffers(@Nullable ByteBuffer[] buffers) {
+    private void freeByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
         if (buffers != null) {
             for (ByteBuffer buffer: buffers) {
-                freeByteBuffer(buffer);
+                freeByteBufferLocked(buffer);
             }
         }
     }
 
-    private final void freeAllTrackedBuffers() {
+    private void freeAllTrackedBuffers() {
         synchronized(mBufferLock) {
-            freeByteBuffers(mCachedInputBuffers);
-            freeByteBuffers(mCachedOutputBuffers);
+            freeByteBuffersLocked(mCachedInputBuffers);
+            freeByteBuffersLocked(mCachedOutputBuffers);
             mCachedInputBuffers = null;
             mCachedOutputBuffers = null;
+            mValidInputIndices.clear();
+            mValidOutputIndices.clear();
             mDequeuedInputBuffers.clear();
             mDequeuedOutputBuffers.clear();
             mQueueRequests.clear();
@@ -3920,14 +3946,31 @@
         }
     }
 
-    private final void cacheBuffers(boolean input) {
+    private void cacheBuffersLocked(boolean input) {
         ByteBuffer[] buffers = null;
         try {
             buffers = getBuffers(input);
-            invalidateByteBuffers(buffers);
+            invalidateByteBuffersLocked(buffers);
         } catch (IllegalStateException e) {
             // we don't get buffers in async mode
         }
+        if (buffers != null) {
+            BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+            for (int i = 0; i < buffers.length; ++i) {
+                ByteBuffer buffer = buffers[i];
+                if (buffer == null || !indices.get(i)) {
+                    continue;
+                }
+                buffer.setAccessible(true);
+                if (!input) {
+                    BufferInfo info = mDequeuedOutputInfos.get(i);
+                    if (info != null) {
+                        buffer.limit(info.offset + info.size).position(info.offset);
+                    }
+                }
+            }
+            indices.clear();
+        }
         if (input) {
             mCachedInputBuffers = buffers;
         } else {
@@ -3963,6 +4006,9 @@
                         + "objects and attach to QueueRequest objects.");
             }
             if (mCachedInputBuffers == null) {
+                cacheBuffersLocked(true /* input */);
+            }
+            if (mCachedInputBuffers == null) {
                 throw new IllegalStateException();
             }
             // FIXME: check codec status
@@ -4001,6 +4047,9 @@
                         + "Please use getOutputFrame to get output frames.");
             }
             if (mCachedOutputBuffers == null) {
+                cacheBuffersLocked(false /* input */);
+            }
+            if (mCachedOutputBuffers == null) {
                 throw new IllegalStateException();
             }
             // FIXME: check codec status
@@ -4038,7 +4087,7 @@
         }
         ByteBuffer newBuffer = getBuffer(true /* input */, index);
         synchronized (mBufferLock) {
-            invalidateByteBuffer(mCachedInputBuffers, index);
+            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
             mDequeuedInputBuffers.put(index, newBuffer);
         }
         return newBuffer;
@@ -4075,7 +4124,7 @@
         }
         Image newImage = getImage(true /* input */, index);
         synchronized (mBufferLock) {
-            invalidateByteBuffer(mCachedInputBuffers, index);
+            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
             mDequeuedInputBuffers.put(index, newImage);
         }
         return newImage;
@@ -4111,7 +4160,7 @@
         }
         ByteBuffer newBuffer = getBuffer(false /* input */, index);
         synchronized (mBufferLock) {
-            invalidateByteBuffer(mCachedOutputBuffers, index);
+            invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
             mDequeuedOutputBuffers.put(index, newBuffer);
         }
         return newBuffer;
@@ -4146,7 +4195,7 @@
         }
         Image newImage = getImage(false /* input */, index);
         synchronized (mBufferLock) {
-            invalidateByteBuffer(mCachedOutputBuffers, index);
+            invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
             mDequeuedOutputBuffers.put(index, newImage);
         }
         return newImage;
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
new file mode 100644
index 0000000..9f92887
--- /dev/null
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2021 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.media.tv.interactive;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Rect;
+import android.media.tv.AdResponse;
+import android.media.tv.BroadcastInfoResponse;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvTrackInfo;
+import android.media.tv.interactive.TvInteractiveAppService.Session;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.Surface;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+import java.util.List;
+
+/**
+ * Implements the internal ITvInteractiveAppSession interface.
+ * @hide
+ */
+public class ITvInteractiveAppSessionWrapper
+        extends ITvInteractiveAppSession.Stub implements HandlerCaller.Callback {
+    private static final String TAG = "ITvInteractiveAppSessionWrapper";
+
+    private static final int EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS = 1000;
+    private static final int EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS = 5 * 1000;
+
+    private static final int DO_RELEASE = 1;
+    private static final int DO_START_INTERACTIVE_APP = 2;
+    private static final int DO_STOP_INTERACTIVE_APP = 3;
+    private static final int DO_RESET_INTERACTIVE_APP = 4;
+    private static final int DO_CREATE_BI_INTERACTIVE_APP = 5;
+    private static final int DO_DESTROY_BI_INTERACTIVE_APP = 6;
+    private static final int DO_SET_TELETEXT_APP_ENABLED = 7;
+    private static final int DO_SEND_CURRENT_CHANNEL_URI = 8;
+    private static final int DO_SEND_CURRENT_CHANNEL_LCN = 9;
+    private static final int DO_SEND_STREAM_VOLUME = 10;
+    private static final int DO_SEND_TRACK_INFO_LIST = 11;
+    private static final int DO_SEND_CURRENT_TV_INPUT_ID = 12;
+    private static final int DO_SEND_SIGNING_RESULT = 13;
+    private static final int DO_NOTIFY_ERROR = 14;
+    private static final int DO_NOTIFY_TUNED = 15;
+    private static final int DO_NOTIFY_TRACK_SELECTED = 16;
+    private static final int DO_NOTIFY_TRACKS_CHANGED = 17;
+    private static final int DO_NOTIFY_VIDEO_AVAILABLE = 18;
+    private static final int DO_NOTIFY_VIDEO_UNAVAILABLE = 19;
+    private static final int DO_NOTIFY_CONTENT_ALLOWED = 20;
+    private static final int DO_NOTIFY_CONTENT_BLOCKED = 21;
+    private static final int DO_NOTIFY_SIGNAL_STRENGTH = 22;
+    private static final int DO_SET_SURFACE = 23;
+    private static final int DO_DISPATCH_SURFACE_CHANGED = 24;
+    private static final int DO_NOTIFY_BROADCAST_INFO_RESPONSE = 25;
+    private static final int DO_NOTIFY_AD_RESPONSE = 26;
+    private static final int DO_CREATE_MEDIA_VIEW = 27;
+    private static final int DO_RELAYOUT_MEDIA_VIEW = 28;
+    private static final int DO_REMOVE_MEDIA_VIEW = 29;
+
+    private final HandlerCaller mCaller;
+    private Session mSessionImpl;
+    private InputChannel mChannel;
+    private TvInteractiveAppEventReceiver mReceiver;
+
+    public ITvInteractiveAppSessionWrapper(
+            Context context, Session mSessionImpl, InputChannel channel) {
+        this.mSessionImpl = mSessionImpl;
+        mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
+        mChannel = channel;
+        if (channel != null) {
+            mReceiver = new TvInteractiveAppEventReceiver(channel, context.getMainLooper());
+        }
+    }
+
+    @Override
+    public void executeMessage(Message msg) {
+        if (mSessionImpl == null) {
+            return;
+        }
+
+        long startTime = System.nanoTime();
+        switch (msg.what) {
+            case DO_RELEASE: {
+                mSessionImpl.release();
+                mSessionImpl = null;
+                if (mReceiver != null) {
+                    mReceiver.dispose();
+                    mReceiver = null;
+                }
+                if (mChannel != null) {
+                    mChannel.dispose();
+                    mChannel = null;
+                }
+                break;
+            }
+            case DO_START_INTERACTIVE_APP: {
+                mSessionImpl.startInteractiveApp();
+                break;
+            }
+            case DO_STOP_INTERACTIVE_APP: {
+                mSessionImpl.stopInteractiveApp();
+                break;
+            }
+            case DO_RESET_INTERACTIVE_APP: {
+                mSessionImpl.resetInteractiveApp();
+                break;
+            }
+            case DO_CREATE_BI_INTERACTIVE_APP: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.createBiInteractiveApp((Uri) args.arg1, (Bundle) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_DESTROY_BI_INTERACTIVE_APP: {
+                mSessionImpl.destroyBiInteractiveApp((String) msg.obj);
+                break;
+            }
+            case DO_SET_TELETEXT_APP_ENABLED: {
+                mSessionImpl.setTeletextAppEnabled((Boolean) msg.obj);
+                break;
+            }
+            case DO_SEND_CURRENT_CHANNEL_URI: {
+                mSessionImpl.sendCurrentChannelUri((Uri) msg.obj);
+                break;
+            }
+            case DO_SEND_CURRENT_CHANNEL_LCN: {
+                mSessionImpl.sendCurrentChannelLcn((Integer) msg.obj);
+                break;
+            }
+            case DO_SEND_STREAM_VOLUME: {
+                mSessionImpl.sendStreamVolume((Float) msg.obj);
+                break;
+            }
+            case DO_SEND_TRACK_INFO_LIST: {
+                mSessionImpl.sendTrackInfoList((List<TvTrackInfo>) msg.obj);
+                break;
+            }
+            case DO_SEND_CURRENT_TV_INPUT_ID: {
+                mSessionImpl.sendCurrentTvInputId((String) msg.obj);
+                break;
+            }
+            case DO_SEND_SIGNING_RESULT: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.sendSigningResult((String) args.arg1, (byte[]) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_ERROR: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyError((String) args.arg1, (Bundle) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_TUNED: {
+                mSessionImpl.notifyTuned((Uri) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_TRACK_SELECTED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.notifyTrackSelected((Integer) args.arg1, (String) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_TRACKS_CHANGED: {
+                mSessionImpl.notifyTracksChanged((List<TvTrackInfo>) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_VIDEO_AVAILABLE: {
+                mSessionImpl.notifyVideoAvailable();
+                break;
+            }
+            case DO_NOTIFY_VIDEO_UNAVAILABLE: {
+                mSessionImpl.notifyVideoUnavailable((Integer) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_CONTENT_ALLOWED: {
+                mSessionImpl.notifyContentAllowed();
+                break;
+            }
+            case DO_NOTIFY_CONTENT_BLOCKED: {
+                mSessionImpl.notifyContentBlocked((TvContentRating) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_SIGNAL_STRENGTH: {
+                mSessionImpl.notifySignalStrength((Integer) msg.obj);
+                break;
+            }
+            case DO_SET_SURFACE: {
+                mSessionImpl.setSurface((Surface) msg.obj);
+                break;
+            }
+            case DO_DISPATCH_SURFACE_CHANGED: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.dispatchSurfaceChanged(
+                        (Integer) args.arg1, (Integer) args.arg2, (Integer) args.arg3);
+                args.recycle();
+                break;
+            }
+            case DO_NOTIFY_BROADCAST_INFO_RESPONSE: {
+                mSessionImpl.notifyBroadcastInfoResponse((BroadcastInfoResponse) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_AD_RESPONSE: {
+                mSessionImpl.notifyAdResponse((AdResponse) msg.obj);
+                break;
+            }
+            case DO_CREATE_MEDIA_VIEW: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mSessionImpl.createMediaView((IBinder) args.arg1, (Rect) args.arg2);
+                args.recycle();
+                break;
+            }
+            case DO_RELAYOUT_MEDIA_VIEW: {
+                mSessionImpl.relayoutMediaView((Rect) msg.obj);
+                break;
+            }
+            case DO_REMOVE_MEDIA_VIEW: {
+                mSessionImpl.removeMediaView(true);
+                break;
+            }
+            default: {
+                Log.w(TAG, "Unhandled message code: " + msg.what);
+                break;
+            }
+        }
+        long durationMs = (System.nanoTime() - startTime) / (1000 * 1000);
+        if (durationMs > EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS) {
+            Log.w(TAG, "Handling message (" + msg.what + ") took too long time (duration="
+                    + durationMs + "ms)");
+            if (durationMs > EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS) {
+                // TODO: handle timeout
+            }
+        }
+    }
+
+    @Override
+    public void startInteractiveApp() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_START_INTERACTIVE_APP));
+    }
+
+    @Override
+    public void stopInteractiveApp() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_INTERACTIVE_APP));
+    }
+
+    @Override
+    public void resetInteractiveApp() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RESET_INTERACTIVE_APP));
+    }
+
+    @Override
+    public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_CREATE_BI_INTERACTIVE_APP, biIAppUri, params));
+    }
+
+    @Override
+    public void destroyBiInteractiveApp(@NonNull String biIAppId) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_DESTROY_BI_INTERACTIVE_APP, biIAppId));
+    }
+
+    @Override
+    public void setTeletextAppEnabled(boolean enable) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SET_TELETEXT_APP_ENABLED, enable));
+    }
+
+    @Override
+    public void sendCurrentChannelUri(@Nullable Uri channelUri) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_URI, channelUri));
+    }
+
+    @Override
+    public void sendCurrentChannelLcn(int lcn) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_LCN, lcn));
+    }
+
+    @Override
+    public void sendStreamVolume(float volume) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_STREAM_VOLUME, volume));
+    }
+
+    @Override
+    public void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_TRACK_INFO_LIST, tracks));
+    }
+
+    @Override
+    public void sendCurrentTvInputId(@Nullable String inputId) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_SEND_CURRENT_TV_INPUT_ID, inputId));
+    }
+
+    @Override
+    public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_SEND_SIGNING_RESULT, signingId, result));
+    }
+
+    @Override
+    public void notifyError(@NonNull String errMsg, @NonNull Bundle params) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_NOTIFY_ERROR, errMsg, params));
+    }
+
+    @Override
+    public void release() {
+        mSessionImpl.scheduleMediaViewCleanup();
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
+    }
+
+    @Override
+    public void notifyTuned(Uri channelUri) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_TUNED, channelUri));
+    }
+
+    @Override
+    public void notifyTrackSelected(int type, final String trackId) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_NOTIFY_TRACK_SELECTED, type, trackId));
+    }
+
+    @Override
+    public void notifyTracksChanged(List<TvTrackInfo> tracks) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_TRACKS_CHANGED, tracks));
+    }
+
+    @Override
+    public void notifyVideoAvailable() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_VIDEO_AVAILABLE));
+    }
+
+    @Override
+    public void notifyVideoUnavailable(int reason) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_VIDEO_UNAVAILABLE, reason));
+    }
+
+    @Override
+    public void notifyContentAllowed() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_CONTENT_ALLOWED));
+    }
+
+    @Override
+    public void notifyContentBlocked(String rating) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_CONTENT_BLOCKED, rating));
+    }
+
+    @Override
+    public void notifySignalStrength(int strength) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_SIGNAL_STRENGTH, strength));
+    }
+
+    @Override
+    public void setSurface(Surface surface) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface));
+    }
+
+    @Override
+    public void dispatchSurfaceChanged(int format, int width, int height) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageIIII(DO_DISPATCH_SURFACE_CHANGED, format, width, height, 0));
+    }
+
+    @Override
+    public void notifyBroadcastInfoResponse(BroadcastInfoResponse response) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_NOTIFY_BROADCAST_INFO_RESPONSE, response));
+    }
+
+    @Override
+    public void notifyAdResponse(AdResponse response) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_AD_RESPONSE, response));
+    }
+
+    @Override
+    public void createMediaView(IBinder windowToken, Rect frame) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageOO(DO_CREATE_MEDIA_VIEW, windowToken, frame));
+    }
+
+    @Override
+    public void relayoutMediaView(Rect frame) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RELAYOUT_MEDIA_VIEW, frame));
+    }
+
+    @Override
+    public void removeMediaView() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_MEDIA_VIEW));
+    }
+
+    private final class TvInteractiveAppEventReceiver extends InputEventReceiver {
+        TvInteractiveAppEventReceiver(InputChannel inputChannel, Looper looper) {
+            super(inputChannel, looper);
+        }
+
+        @Override
+        public void onInputEvent(InputEvent event) {
+            if (mSessionImpl == null) {
+                // The session has been finished.
+                finishInputEvent(event, false);
+                return;
+            }
+
+            int handled = mSessionImpl.dispatchInputEvent(event, this);
+            if (handled != TvInteractiveAppManager.Session.DISPATCH_IN_PROGRESS) {
+                finishInputEvent(
+                        event, handled == TvInteractiveAppManager.Session.DISPATCH_HANDLED);
+            }
+        }
+    }
+}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 54700b6..f5b4322 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -45,7 +45,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteCallbackList;
@@ -1416,193 +1415,6 @@
         }
     }
 
-    /**
-     * Implements the internal ITvInteractiveAppSession interface.
-     * @hide
-     */
-    public static class ITvInteractiveAppSessionWrapper extends ITvInteractiveAppSession.Stub {
-        // TODO: put ITvInteractiveAppSessionWrapper in a separate Java file
-        private final Session mSessionImpl;
-        private InputChannel mChannel;
-        private TvInteractiveAppEventReceiver mReceiver;
-
-        public ITvInteractiveAppSessionWrapper(
-                Context context, Session mSessionImpl, InputChannel channel) {
-            this.mSessionImpl = mSessionImpl;
-            mChannel = channel;
-            if (channel != null) {
-                mReceiver = new TvInteractiveAppEventReceiver(channel, context.getMainLooper());
-            }
-        }
-
-        @Override
-        public void startInteractiveApp() {
-            mSessionImpl.startInteractiveApp();
-        }
-
-        @Override
-        public void stopInteractiveApp() {
-            mSessionImpl.stopInteractiveApp();
-        }
-
-        @Override
-        public void resetInteractiveApp() {
-            mSessionImpl.resetInteractiveApp();
-        }
-
-        @Override
-        public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
-            mSessionImpl.createBiInteractiveApp(biIAppUri, params);
-        }
-
-        @Override
-        public void setTeletextAppEnabled(boolean enable) {
-            mSessionImpl.setTeletextAppEnabled(enable);
-        }
-
-        @Override
-        public void destroyBiInteractiveApp(@NonNull String biIAppId) {
-            mSessionImpl.destroyBiInteractiveApp(biIAppId);
-        }
-
-        @Override
-        public void sendCurrentChannelUri(@Nullable Uri channelUri) {
-            mSessionImpl.sendCurrentChannelUri(channelUri);
-        }
-
-        @Override
-        public void sendCurrentChannelLcn(int lcn) {
-            mSessionImpl.sendCurrentChannelLcn(lcn);
-        }
-
-        @Override
-        public void sendStreamVolume(float volume) {
-            mSessionImpl.sendStreamVolume(volume);
-        }
-
-        @Override
-        public void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
-            mSessionImpl.sendTrackInfoList(tracks);
-        }
-
-        @Override
-        public void sendCurrentTvInputId(@Nullable String inputId) {
-            mSessionImpl.sendCurrentTvInputId(inputId);
-        }
-
-        @Override
-        public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
-            mSessionImpl.sendSigningResult(signingId, result);
-        }
-
-        @Override
-        public void notifyError(@NonNull String errMsg, @NonNull Bundle params) {
-            mSessionImpl.notifyError(errMsg, params);
-        }
-
-        @Override
-        public void release() {
-            mSessionImpl.scheduleMediaViewCleanup();
-            mSessionImpl.release();
-        }
-
-        @Override
-        public void notifyTuned(Uri channelUri) {
-            mSessionImpl.notifyTuned(channelUri);
-        }
-
-        @Override
-        public void notifyTrackSelected(int type, final String trackId) {
-            mSessionImpl.notifyTrackSelected(type, trackId);
-        }
-
-        @Override
-        public void notifyTracksChanged(List<TvTrackInfo> tracks) {
-            mSessionImpl.notifyTracksChanged(tracks);
-        }
-
-        @Override
-        public void notifyVideoAvailable() {
-            mSessionImpl.notifyVideoAvailable();
-        }
-
-        @Override
-        public void notifyVideoUnavailable(int reason) {
-            mSessionImpl.notifyVideoUnavailable(reason);
-        }
-
-        @Override
-        public void notifyContentAllowed() {
-            mSessionImpl.notifyContentAllowed();
-        }
-
-        @Override
-        public void notifyContentBlocked(String rating) {
-            mSessionImpl.notifyContentBlocked(TvContentRating.unflattenFromString(rating));
-        }
-
-        @Override
-        public void notifySignalStrength(int strength) {
-            mSessionImpl.notifySignalStrength(strength);
-        }
-
-        @Override
-        public void setSurface(Surface surface) {
-            mSessionImpl.setSurface(surface);
-        }
-
-        @Override
-        public void dispatchSurfaceChanged(int format, int width, int height) {
-            mSessionImpl.dispatchSurfaceChanged(format, width, height);
-        }
-
-        @Override
-        public void notifyBroadcastInfoResponse(BroadcastInfoResponse response) {
-            mSessionImpl.notifyBroadcastInfoResponse(response);
-        }
-
-        @Override
-        public void notifyAdResponse(AdResponse response) {
-            mSessionImpl.notifyAdResponse(response);
-        }
-
-        @Override
-        public void createMediaView(IBinder windowToken, Rect frame) {
-            mSessionImpl.createMediaView(windowToken, frame);
-        }
-
-        @Override
-        public void relayoutMediaView(Rect frame) {
-            mSessionImpl.relayoutMediaView(frame);
-        }
-
-        @Override
-        public void removeMediaView() {
-            mSessionImpl.removeMediaView(true);
-        }
-
-        private final class TvInteractiveAppEventReceiver extends InputEventReceiver {
-            TvInteractiveAppEventReceiver(InputChannel inputChannel, Looper looper) {
-                super(inputChannel, looper);
-            }
-
-            @Override
-            public void onInputEvent(InputEvent event) {
-                if (mSessionImpl == null) {
-                    // The session has been finished.
-                    finishInputEvent(event, false);
-                    return;
-                }
-
-                int handled = mSessionImpl.dispatchInputEvent(event, this);
-                if (handled != TvInteractiveAppManager.Session.DISPATCH_IN_PROGRESS) {
-                    finishInputEvent(
-                            event, handled == TvInteractiveAppManager.Session.DISPATCH_HANDLED);
-                }
-            }
-        }
-    }
-
     @SuppressLint("HandlerLeak")
     private final class ServiceHandler extends Handler {
         private static final int DO_CREATE_SESSION = 1;
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
index 8ecc2a2..eef81e0 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
@@ -16,43 +16,7 @@
 
 package com.android.settingslib.spa.codelab
 
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.navigation.compose.NavHost
-import androidx.navigation.compose.composable
-import androidx.navigation.compose.rememberNavController
-import com.android.settingslib.spa.framework.localNavController
-import com.android.settingslib.spa.theme.SettingsTheme
+import com.android.settingslib.spa.codelab.page.codelabPageRepository
+import com.android.settingslib.spa.framework.SpaActivity
 
-class MainActivity : ComponentActivity() {
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContent {
-            MainContent()
-        }
-    }
-}
-
-object Destinations {
-    const val Home = "Home"
-    const val Preference = "Preference"
-}
-
-@Composable
-private fun MainContent() {
-    SettingsTheme {
-        val navController = rememberNavController()
-        CompositionLocalProvider(navController.localNavController()) {
-            NavHost(
-                navController = navController,
-                startDestination = Destinations.Home,
-            ) {
-                composable(Destinations.Home) { HomeScreen() }
-                composable(Destinations.Preference) { PreferenceCodelab() }
-            }
-        }
-    }
-}
+class MainActivity : SpaActivity(codelabPageRepository)
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt
new file mode 100644
index 0000000..484b604
--- /dev/null
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.codelab.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.navigator
+import com.android.settingslib.spa.framework.toState
+import com.android.settingslib.spa.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+private const val STRING_PARAM_NAME = "stringParam"
+private const val INT_PARAM_NAME = "intParam"
+
+object ArgumentPageProvider : SettingsPageProvider {
+    override val name = Destinations.Argument
+
+    override val arguments = listOf(
+        navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
+        navArgument(INT_PARAM_NAME) { type = NavType.IntType },
+    )
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        ArgumentPage(
+            stringParam = arguments!!.getString(STRING_PARAM_NAME, "default"),
+            intParam = arguments.getInt(INT_PARAM_NAME),
+        )
+    }
+
+    @Composable
+    fun EntryItem(stringParam: String, intParam: Int) {
+        Preference(object : PreferenceModel {
+            override val title = "Sample page with arguments"
+            override val summary =
+                "$STRING_PARAM_NAME=$stringParam, $INT_PARAM_NAME=$intParam".toState()
+            override val onClick = navigator("${Destinations.Argument}/$stringParam/$intParam")
+        })
+    }
+}
+
+@Composable
+fun ArgumentPage(stringParam: String, intParam: Int) {
+    Column {
+        Preference(object : PreferenceModel {
+            override val title = "String param value"
+            override val summary = stringParam.toState()
+        })
+
+        Preference(object : PreferenceModel {
+            override val title = "Int param value"
+            override val summary = intParam.toString().toState()
+        })
+
+        ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = intParam + 1)
+
+        ArgumentPageProvider.EntryItem(stringParam = "bar", intParam = intParam + 1)
+    }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun ArgumentPagePreview() {
+    SettingsTheme {
+        ArgumentPage(stringParam = "foo", intParam = 0)
+    }
+}
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
similarity index 73%
rename from packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt
rename to packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
index 574857f..27c70e4 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.codelab
+package com.android.settingslib.spa.codelab.page
 
+import android.os.Bundle
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material3.MaterialTheme
@@ -24,14 +25,22 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
-import com.android.settingslib.spa.framework.onClickNavigateTo
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.codelab.R
 import com.android.settingslib.spa.theme.SettingsDimension
 import com.android.settingslib.spa.theme.SettingsTheme
-import com.android.settingslib.spa.widget.preference.Preference
-import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+object HomePageProvider : SettingsPageProvider {
+    override val name = Destinations.Home
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        HomePage()
+    }
+}
 
 @Composable
-fun HomeScreen() {
+private fun HomePage() {
     Column {
         Text(
             text = stringResource(R.string.app_name),
@@ -40,10 +49,9 @@
             style = MaterialTheme.typography.headlineMedium,
         )
 
-        Preference(object : PreferenceModel {
-            override val title = "Preference"
-            override val onClick: (() -> Unit) = onClickNavigateTo(Destinations.Preference)
-        })
+        PreferencePageProvider.EntryItem()
+
+        ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = 0)
     }
 }
 
@@ -51,6 +59,6 @@
 @Composable
 private fun HomeScreenPreview() {
     SettingsTheme {
-        HomeScreen()
+        HomePage()
     }
 }
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt
new file mode 100644
index 0000000..862fc1e
--- /dev/null
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.codelab.page
+
+import com.android.settingslib.spa.api.SettingsPageRepository
+
+object Destinations {
+    const val Home = "Home"
+    const val Preference = "Preference"
+    const val Argument = "Argument"
+}
+
+val codelabPageRepository = SettingsPageRepository(
+    allPages = listOf(HomePageProvider, PreferencePageProvider, ArgumentPageProvider),
+    startDestination = Destinations.Home,
+)
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
similarity index 80%
rename from packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt
rename to packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
index 4e24aa1..81627f6 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.codelab
+package com.android.settingslib.spa.codelab.page
 
+import android.os.Bundle
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
@@ -29,14 +30,33 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.navigator
 import com.android.settingslib.spa.framework.toState
 import com.android.settingslib.spa.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import kotlinx.coroutines.delay
 
+object PreferencePageProvider : SettingsPageProvider {
+    override val name = Destinations.Preference
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        PreferencePage()
+    }
+
+    @Composable
+    fun EntryItem() {
+        Preference(object : PreferenceModel {
+            override val title = "Sample Preference"
+            override val onClick = navigator(Destinations.Preference)
+        })
+    }
+}
+
 @Composable
-fun PreferenceCodelab() {
+private fun PreferencePage() {
     Column(Modifier.verticalScroll(rememberScrollState())) {
         Preference(object : PreferenceModel {
             override val title = "Preference"
@@ -82,8 +102,8 @@
 
 @Preview(showBackground = true)
 @Composable
-private fun PreferenceCodelabPreview() {
+private fun PreferencePagePreview() {
     SettingsTheme {
-        PreferenceCodelab()
+        PreferencePage()
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt
new file mode 100644
index 0000000..0ad0003
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.api
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.navigation.NamedNavArgument
+
+/**
+ * An SettingsPageProvider represent a Settings page.
+ */
+interface SettingsPageProvider {
+
+    /** The page name without arguments. */
+    val name: String
+
+    /** The page arguments, default is no arguments. */
+    val arguments: List<NamedNavArgument>
+        get() = emptyList()
+
+    /** The [Composable] used to render this page. */
+    @Composable
+    fun Page(arguments: Bundle?)
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt
new file mode 100644
index 0000000..ce39f4f
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.api
+
+data class SettingsPageRepository(
+    val allPages: List<SettingsPageProvider>,
+    val startDestination: String,
+)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
index 55bc78b..35112ad 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
@@ -39,7 +39,7 @@
 }
 
 @Composable
-fun onClickNavigateTo(route: String): () -> Unit {
+fun navigator(route: String): () -> Unit {
     val navController = LocalNavController.current
     return { navController.navigate(route) }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
new file mode 100644
index 0000000..28a5899e
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.framework
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.api.SettingsPageRepository
+import com.android.settingslib.spa.theme.SettingsTheme
+
+open class SpaActivity(
+    private val settingsPageRepository: SettingsPageRepository,
+) : ComponentActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContent {
+            MainContent()
+        }
+    }
+
+    @Composable
+    private fun MainContent() {
+        SettingsTheme {
+            val navController = rememberNavController()
+            CompositionLocalProvider(navController.localNavController()) {
+                NavHost(navController, settingsPageRepository.startDestination) {
+                    for (page in settingsPageRepository.allPages) {
+                        composable(
+                            route = page.route,
+                            arguments = page.arguments,
+                        ) { navBackStackEntry ->
+                            page.Page(navBackStackEntry.arguments)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private val SettingsPageProvider.route: String
+        get() = name + arguments.joinToString("") { argument -> "/{${argument.name}}" }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
new file mode 100644
index 0000000..d415e9b
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 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 com.android.settingslib.spa.widget.preference
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Divider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.android.settingslib.spa.framework.toState
+import com.android.settingslib.spa.theme.SettingsDimension
+import com.android.settingslib.spa.theme.SettingsOpacity
+import com.android.settingslib.spa.theme.SettingsTheme
+
+@Composable
+internal fun BaseLayout(
+    title: String,
+    subTitle: @Composable () -> Unit,
+    modifier: Modifier = Modifier,
+    icon: (@Composable () -> Unit)? = null,
+    enabled: State<Boolean> = true.toState(),
+    paddingStart: Dp = SettingsDimension.itemPaddingStart,
+    paddingEnd: Dp = SettingsDimension.itemPaddingEnd,
+    paddingVertical: Dp = SettingsDimension.itemPaddingVertical,
+    widget: @Composable () -> Unit = {},
+) {
+    Row(
+        modifier = modifier
+            .fillMaxWidth()
+            .padding(end = paddingEnd),
+        verticalAlignment = Alignment.CenterVertically,
+    ) {
+        val alphaModifier =
+            Modifier.alpha(if (enabled.value) SettingsOpacity.Full else SettingsOpacity.Disabled)
+        BaseIcon(icon, alphaModifier, paddingStart)
+        Titles(
+            title = title,
+            subTitle = subTitle,
+            modifier = alphaModifier
+                .weight(1f)
+                .padding(vertical = paddingVertical),
+        )
+        widget()
+    }
+}
+
+@Composable
+private fun BaseIcon(
+    icon: @Composable (() -> Unit)?,
+    modifier: Modifier,
+    paddingStart: Dp,
+) {
+    if (icon != null) {
+        Box(
+            modifier = modifier.size(SettingsDimension.itemIconContainerSize),
+            contentAlignment = Alignment.Center,
+        ) {
+            icon()
+        }
+    } else {
+        Spacer(modifier = Modifier.width(width = paddingStart))
+    }
+}
+
+// Extracts a scope to avoid frequent recompose outside scope.
+@Composable
+private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) {
+    Column(modifier) {
+        Text(
+            text = title,
+            color = MaterialTheme.colorScheme.onSurface,
+            style = MaterialTheme.typography.titleMedium,
+        )
+        subTitle()
+    }
+}
+
+@Preview
+@Composable
+private fun BaseLayoutPreview() {
+    SettingsTheme {
+        BaseLayout(
+            title = "Title",
+            subTitle = {
+                Divider(thickness = 10.dp)
+            }
+        )
+    }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
index 7476f4e..563a47a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
@@ -16,14 +16,6 @@
 
 package com.android.settingslib.spa.widget.preference
 
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.BatteryChargingFull
 import androidx.compose.material3.Icon
@@ -31,14 +23,11 @@
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import com.android.settingslib.spa.framework.toState
 import com.android.settingslib.spa.theme.SettingsDimension
-import com.android.settingslib.spa.theme.SettingsOpacity
 import com.android.settingslib.spa.theme.SettingsTheme
 
 @Composable
@@ -53,52 +42,25 @@
     paddingVertical: Dp = SettingsDimension.itemPaddingVertical,
     widget: @Composable () -> Unit = {},
 ) {
-    Row(
-        modifier = modifier
-            .fillMaxWidth()
-            .padding(end = paddingEnd),
-        verticalAlignment = Alignment.CenterVertically,
-    ) {
-        val alphaModifier =
-            Modifier.alpha(if (enabled.value) SettingsOpacity.Full else SettingsOpacity.Disabled)
-        if (icon != null) {
-            Box(
-                modifier = alphaModifier.size(SettingsDimension.itemIconContainerSize),
-                contentAlignment = Alignment.Center,
-            ) {
-                icon()
+    BaseLayout(
+        title = title,
+        subTitle = {
+            if (summary.value.isNotEmpty()) {
+                Text(
+                    text = summary.value,
+                    color = MaterialTheme.colorScheme.onSurfaceVariant,
+                    style = MaterialTheme.typography.bodyMedium,
+                )
             }
-        } else {
-            Spacer(modifier = Modifier.width(width = paddingStart))
-        }
-        TitleAndSummary(
-            title = title,
-            summary = summary,
-            modifier = alphaModifier
-                .weight(1f)
-                .padding(vertical = paddingVertical),
-        )
-        widget()
-    }
-}
-
-// Extracts a scope to avoid frequent recompose outside scope.
-@Composable
-private fun TitleAndSummary(title: String, summary: State<String>, modifier: Modifier) {
-    Column(modifier) {
-        Text(
-            text = title,
-            color = MaterialTheme.colorScheme.onSurface,
-            style = MaterialTheme.typography.titleMedium,
-        )
-        if (summary.value.isNotEmpty()) {
-            Text(
-                text = summary.value,
-                color = MaterialTheme.colorScheme.onSurfaceVariant,
-                style = MaterialTheme.typography.bodyMedium,
-            )
-        }
-    }
+        },
+        modifier = modifier,
+        icon = icon,
+        enabled = enabled,
+        paddingStart = paddingStart,
+        paddingEnd = paddingEnd,
+        paddingVertical = paddingVertical,
+        widget = widget,
+    )
 }
 
 @Preview
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 7165c14..1de7668 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Gebruik stelselkeuse (verstek)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Gebruik stelselkeuse (verstek)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Gebruik stelselkeuse (verstek)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 264faad..fe8030f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Lêeroordrag"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoertoestel"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling van kontakte en oproepgeskiedenis"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gebruik vir deling van kontakte en oproepgeskiedenis"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling van internetverbinding"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Teksboodskappe"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-toegang"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luggehalte"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Uitsaai-inligting"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Huiskontroles"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Kies \'n profielprent"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Verstekgebruikerikoon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fisieke sleutelbord"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 1108c82..a900d13 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
     <item msgid="8003118270854840095">"44.1 ኪኸ"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index b68cbd7..d3c034f 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ፋይል ማስተላለፍ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ግቤት መሣሪያ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"የበይነመረብ ድረስ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"የእውቂያዎች እና የጥሪ ታሪክ ማጋራት"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"እውቂያዎችን እና የጥሪ ታሪክን ለማጋራት ይጠቀሙበት"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"የበይነ መረብ ተያያዥ ማጋሪያ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"የጽሑፍ መልዕክቶች"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"የሲም መዳረሻ"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"የአየር ሁኔታ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"የአየር ጥራት"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"የCast መረጃ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"የመገለጫ ሥዕል ይምረጡ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ነባሪ የተጠቃሚ አዶ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"አካላዊ ቁልፍ ሰሌዳ"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index eb4be38..8f7d7d2 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"استخدام اختيار النظام (تلقائي)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"استخدام اختيار النظام (تلقائي)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"استخدام اختيار النظام (تلقائي)"</item>
     <item msgid="8003118270854840095">"44.1 كيلو هرتز"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c8b263b..6783654 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"نقل الملف"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز الإرسال"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"استخدام الإنترنت"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"مشاركة جهات الاتصال وسجل المكالمات"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"استخدام إعدادات بلوتوث لمشاركة جهات الاتصال وسجل المكالمات"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"مشاركة اتصال الإنترنت"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"الرسائل النصية"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‏الوصول إلى شريحة SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"الطقس"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"جودة الهواء"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"معلومات البث"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"اختيار صورة الملف الشخصي"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"رمز المستخدم التلقائي"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"لوحة مفاتيح خارجية"</string>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index df23f67..4c879d0 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
-    <item msgid="4055460186095649420">"এছবিচি"</item>
-    <item msgid="720249083677397051">"এএচি"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ\'"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
-    <item msgid="9024885861221697796">"এছবিচি"</item>
-    <item msgid="4688890470703790013">"এএচি"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ’"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
     <item msgid="8003118270854840095">"৪৪.১ কিল\'হাৰ্টজ"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ea1aff0..543c703 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তৰণ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ইনপুট ডিভাইচ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ইণ্টাৰনেট সংযোগ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"সম্পৰ্কসূচী আৰু কলৰ ইতিহাস শ্বেয়াৰ কৰা"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"সম্পৰ্কসূচী আৰু কলৰ ইতিহাস শ্বেয়াৰ কৰাৰ বাবে ব্যৱহাৰ কৰক"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ইণ্টাৰনেট সংযোগ শ্বেয়াৰ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"পাঠ বাৰ্তা"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ছিম প্ৰৱেশ"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"বতৰ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"বায়ুৰ গুণগত মান"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাষ্টৰ তথ্য"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"এখন প্ৰ’ফাইল চিত্ৰ বাছনি কৰক"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ডিফ’ল্ট ব্যৱহাৰকাৰীৰ চিহ্ন"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"কায়িক কীব’ৰ্ড"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 5163791..48974a7 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Sistem Seçimini istifadə edin (Defolt)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Sistem Seçimini istifadə edin (Defolt)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Sistem Seçimini istifadə edin (Defolt)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 88333e82..f3e5d95 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl transferi"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Daxiletmə cihazı"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"İnternetə giriş"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktlar və zəng tarixçəsi paylaşımı"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kontaktlar və zəng tarixçəsi paylaşımı üçün istifadə edin"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"internet bağlantı paylaşımı"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mətn Mesajları"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-karta giriş"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Hava"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havanın keyfiyyəti"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayım məlumatı"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profil şəkli seçin"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Defolt istifadəçi ikonası"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziki klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 5cc43f6..337da26 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Koristi izbor sistema (podrazumevano)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Koristi izbor sistema (podrazumevano)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Koristi izbor sistema (podrazumevano)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a84d019..6a880aa 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup Internetu"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deljenje kontakata i istorije poziva"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Koristite za deljenje kontakata i istorije poziva"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deljenje internet veze"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM kartici"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet vazduha"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o prebacivanju"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Podrazumevana ikona korisnika"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 6259c2d..d843629 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Выбар сістэмы (стандартны)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Выбар сістэмы (стандартны)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Выбар сістэмы (стандартны)"</item>
     <item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 37f8410..a902426 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Перадача файлаў"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Прылада ўводу"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ у інтэрнэт"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Абагульванне кантактаў і гісторыі выклікаў"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Ужываць для абагульвання кантактаў і гісторыі выклікаў"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Прадастаўленне доступу да Інтэрнэту"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Тэкставыя паведамленні"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ да SIM-карты"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Надвор\'е"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якасць паветра"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Даныя пра трансляцыю"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Выберыце відарыс профілю"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Стандартны карыстальніцкі значок"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Фізічная клавіятура"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 49e66c0..1aad6ca7 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Използване на сист. избор (стандартно)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"Разширено аудиокодиране (AAC)"</item>
-    <item msgid="1049450003868150455">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Използване на сист. избор (стандартно)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"Разширено аудиокодиране (AAC)"</item>
-    <item msgid="8627333814413492563">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Използване на сист. избор (стандартно)"</item>
     <item msgid="8003118270854840095">"44,1 кХц"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index f2cf69e..c512366 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Прехвърляне на файл"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Входно устройство"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Достъп до интернет"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Споделяне на контактите и ист. на обажд."</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Служи за споделяне на контактите и историята на обажданията"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделяне на връзката с интернет"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстови съобщения"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Достъп до SIM картата"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Времето"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество на въздуха"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Предаване: Инф."</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Изберете снимка на потребителския профил"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Икона за основния потребител"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Физическа клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index fdb611b..5e6bb95 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
     <item msgid="8003118270854840095">"৪৪.১ kHz"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 801fb34..23eed04 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তর"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ইনপুট ডিভাইস"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ইন্টারনেট অ্যাক্সেস"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"পরিচিতি এবং কলের ইতিহাস শেয়ার করা"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"পরিচিতি ও কলের ইতিহাস শেয়ার করার জন্য ব্যবহার করুন"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ইন্টারনেট কানেকশন শেয়ার করা হচ্ছে"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"এসএমএস"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"সিম অ্যাক্সেস"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"আবহাওয়া"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"এয়ার কোয়ালিটি"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাস্ট সম্পর্কিত তথ্য"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"হোম কন্ট্রোল"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"একটি প্রোফাইল ছবি বেছে নিন"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ডিফল্ট ব্যবহারকারীর আইকন"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ফিজিক্যাল কীবোর্ড"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 32edef1..262a35f 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Korištenje odabira sistema (zadano)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Korištenje odabira sistema (zadano)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Korištenje odabira sistema (zadano)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 61082f6..78a484f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenošenje fajla"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup internetu"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Dijeljenje kontakata i historije poziva"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Upotrijebite za dijeljenje kontakata i historije poziva"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Dijeljenje internet veze"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet zraka"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o emitiranju"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Zadana ikona korisnika"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index a267af8..8c34a1f 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Utilitza la selecció del sistema (predeterminada)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Utilitza la selecció del sistema (predeterminada)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Utilitza la selecció del sistema (predeterminada)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 881f9d4..606a379 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferència de fitxers"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositiu d\'entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accés a Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartició de contactes i trucades"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Utilitza per compartir contactes i l\'historial de trucades"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartició de connexió d\'Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Missatges de text"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accés a la SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Temps"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualitat de l\'aire"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informació d\'emissió"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Tria una foto de perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icona d\'usuari predeterminat"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclat físic"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index 3eeae64..90bcaa4 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Použít systémový výběr (výchozí)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Použít systémový výběr (výchozí)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Použít systémový výběr (výchozí)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 7f314bd..37c0bb4 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Přenos souborů"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupní zařízení"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Přístup k internetu"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Sdílení kontaktů a historie volání"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používat ke sdílení kontaktů a historie hovorů"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Sdílení internetového připojení"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové zprávy"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Přístup k SIM kartě"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Počasí"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info o odesílání"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Vyberte profilový obrázek"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Výchozí uživatelská ikona"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnice"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 58ca722..155104ae 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Brug systemvalg (standard)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Brug systemvalg (standard)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Brug systemvalg (standard)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c470b81..d80e1ec 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverførsel"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inputenhed"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetadgang"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling af kontakter og opkaldshistorik"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Brug til deling af kontakter og opkaldshistorik"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling af internetforbindelse"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-beskeder"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Adgang til SIM-kort"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vejr"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast-oplysninger"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Vælg et profilbillede"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikon for standardbruger"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index a8eb3f6..31126a8 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Systemauswahl verwenden (Standard)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Systemauswahl verwenden (Standard)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Systemauswahl verwenden (Standard)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 34a622b..d4fafe1 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dateiübertragung"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Eingabegerät"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetzugriff"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Teilen von Kontakten und der Anrufliste"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Zum Teilen von Kontakten und der Anrufliste verwenden"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Freigabe der Internetverbindung"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Zugriff auf SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Wetter"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftqualität"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Streaming-Info"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profilbild auswählen"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Standardmäßiges Nutzersymbol"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Physische Tastatur"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index ccd06fa..70000e1 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index fdc7419..aa613a5 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Μεταφορά αρχείου"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Συσκευή εισόδου"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Πρόσβαση στο Διαδίκτυο"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Κοινοποίηση επαφών και ιστορικού κλήσεων"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Χρήση για την κοινοποίηση επαφών και του ιστορικού κλήσεων"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Κοινή χρήση σύνδεσης στο Διαδίκτυο"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Μηνύματα κειμένου"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Πρόσβαση SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Καιρός"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ποιότητα αέρα"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Πληροφορίες ηθοποιών"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Επιλογή φωτογραφίας προφίλ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Προεπιλεγμένο εικονίδιο χρήστη"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Φυσικό πληκτρολόγιο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Use system selection (default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Use system selection (default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Use system selection (default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Use system selection (default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Use system selection (default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Use system selection (default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index d88bb0e..8650b77 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Use system selection (default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Use system selection (default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Use system selection (default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Use system selection (default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Use system selection (default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Use system selection (default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index aca3eb4..34db380 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎map13‎‏‎‎‏‎"</item>
     <item msgid="8147982633566548515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎map14‎‏‎‎‏‎"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‎Use System Selection (Default)‎‏‎‎‏‎"</item>
-    <item msgid="4055460186095649420">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‎‎SBC‎‏‎‎‏‎"</item>
-    <item msgid="720249083677397051">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎AAC‎‏‎‎‏‎"</item>
-    <item msgid="1049450003868150455">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX">aptX™</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
-    <item msgid="2908219194098827570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX_HD">aptX™ HD</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
-    <item msgid="3825367753087348007">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎LDAC‎‏‎‎‏‎"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎Use System Selection (Default)‎‏‎‎‏‎"</item>
-    <item msgid="9024885861221697796">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎SBC‎‏‎‎‏‎"</item>
-    <item msgid="4688890470703790013">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎AAC‎‏‎‎‏‎"</item>
-    <item msgid="8627333814413492563">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX">aptX™</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
-    <item msgid="3517061573669307965">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="APTX_HD">aptX™ HD</xliff:g>‎‏‎‎‏‏‏‎ audio‎‏‎‎‏‎"</item>
-    <item msgid="2553206901068987657">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎LDAC‎‏‎‎‏‎"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎Use System Selection (Default)‎‏‎‎‏‎"</item>
     <item msgid="8003118270854840095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎44.1 kHz‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 5d775d3..21697b9 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -660,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎Weather‎‏‎‎‏‎"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎Air Quality‎‏‎‎‏‎"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎Cast Info‎‏‎‎‏‎"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎Home Controls‎‏‎‎‏‎"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‎Choose a profile picture‎‏‎‎‏‎"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎Default user icon‎‏‎‎‏‎"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎Physical keyboard‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 6a926d2..9b1aa3a 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usar selección del sistema (predeterminado)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usar selección del sistema (predeterminado)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usar selección del sistema (predeterminado)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 98c1400..27cd0ab 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e historial de llam."</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uso para compartir contactos e historial de llamadas"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a SIM"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info de reparto"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Control de la casa"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Elige una foto de perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ícono de usuario predeterminado"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 7c37fa5..0677864 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usar preferencia del sistema (predeterminado)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usar preferencia del sistema (predeterminado)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usar preferencia del sistema (predeterminado)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 90c4fb8..d221c8d 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e historial de llamadas"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usar para compartir los contactos y el historial de llamadas"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a tarjeta SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Tiempo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de emisión"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Elige una imagen de perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icono de usuario predeterminado"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 14d0fd1..d986ecf 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Süsteemi valiku kasutamine (vaikeseade)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Süsteemi valiku kasutamine (vaikeseade)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Süsteemi valiku kasutamine (vaikeseade)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index a6c787a..f32ae23 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failiedastus"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sisendseade"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Juurdepääs internetile"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktide ja kõneajaloo jagamine"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kasutage kontaktide ja kõneajaloo jagamiseks"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneti-ühenduse jagamine"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstsõnumid"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Juurdepääs SIM-ile"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Ilm"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Õhukvaliteet"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Osatäitjate teave"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Valige profiilipilt"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Vaikekasutajaikoon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Füüsiline klaviatuur"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index cc47e27..d166e1b 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Erabili sistema-hautapena (lehenetsia)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Erabili sistema-hautapena (lehenetsia)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Erabili sistema-hautapena (lehenetsia)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 87cfaa8..bcb57e8 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fitxategi-transferentzia"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrerako gailua"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneteko konexioa"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktuak eta deien historia partekatzeko aukera"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Erabili kontaktuetarako eta deien historia partekatzeko"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneteko konexioa partekatzea"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Testu-mezuak"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIMerako sarbidea"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Eguraldia"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Airearen kalitatea"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Igorpenari buruzko informazioa"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Aukeratu profileko argazki bat"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Erabiltzaile lehenetsiaren ikonoa"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teklatu fisikoa"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index d76389b..b7761dd 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
     <item msgid="8003118270854840095">"۴۴٫۱ کیلوهرتز"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 51d74dd..6abe873 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"انتقال فایل"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"دستگاه ورودی"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"دسترسی به اینترنت"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"هم‌رسانی مخاطبین و سابقه تماس"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"استفاده برای هم‌رسانی مخاطبین و سابقه تماس"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"اشتراک‌گذاری اتصال اینترنت"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"پیام‌های نوشتاری"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"دسترسی سیم‌کارت"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"آب‌وهوا"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"کیفیت هوا"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات پخش محتوا"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیش‌فرض"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"صفحه‌کلید فیزیکی"</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index f828186..2969892 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Käytä järjestelmän valintaa (oletus)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Käytä järjestelmän valintaa (oletus)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Käytä järjestelmän valintaa (oletus)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index c0f90b8..2f3436e 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Tiedostonsiirto"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Syöttölaite"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetyhteys"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Yhteystietojen ja soittohistorian jako"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Käytä yhteystiedoissa ja soittohistorian jakamiseen"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetyhteyden jakaminen"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstiviestit"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-kortin käyttö"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Sää"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ilmanlaatu"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Striimaustiedot"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Valitse profiilikuva"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Oletuskäyttäjäkuvake"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyysinen näppäimistö"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 50c1bcb..12acbb6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Utiliser sélect. du système (par défaut)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Utiliser sélect. du système (par défaut)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Utiliser sélect. du système (par défaut)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 14515cd..28b3cd9 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichier"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Périphérique d\'entrée"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accès Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Partage des contacts et des appels"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Sert à partager des contacts et l\'historique des appels"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partage de connexion Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Messages texte"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info diffusion"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choisir une photo de profil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icône d\'utilisateur par défaut"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 6343f0d..80ac7e4 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Utiliser la sélection du système (par défaut)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Utiliser la sélection du système (par défaut)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Utiliser la sélection du système (par défaut)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 19ea6dd..da1497a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichiers"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Périphérique d\'entrée"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accès Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Partage contacts/historique des appels"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"À utiliser pour partage des contacts/historique des appels"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partage de connexion Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Infos distribution"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Choisissez une photo de profil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icône de l\'utilisateur par défaut"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 22fb223..b6cf48e 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usar selección do sistema (predeterminado)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usa a selección do sistema (predeterminado)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usar selección do sistema (predeterminado)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 94fa72a..7822749 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de ficheiros"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e hist. de chamadas"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uso da opción de compartir contactos e historial de chamadas"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Uso compartido da conexión a Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensaxes de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso á SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"O tempo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidade do aire"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Datos da emisión"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Escolle unha imaxe do perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icona do usuario predeterminado"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 318b5f5..7e668e7 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index a474d82..cebb1fe 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ફાઇલ સ્થાનાંતરણ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ઇનપુટ ડિવાઇસ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ઇન્ટરનેટ ઍક્સેસ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"સંપર્કો અને કૉલ ઇતિહાસની શેરિંગ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"સંપર્કો અને કૉલ ઇતિહાસની શેરિંગ માટે ઉપયોગ કરો"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ઇન્ટરનેટ કનેક્શન શેરિંગ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ સંદેશા"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"સિમ ઍક્સેસ"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"હવામાન"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"હવાની ક્વૉલિટી"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"કાસ્ટ વિશેની માહિતી"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"પ્રોફાઇલ ફોટો પસંદ કરો"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ડિફૉલ્ટ વપરાશકર્તાનું આઇકન"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ભૌતિક કીબોર્ડ"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 61a8f92..13da75b 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 55fc547..417d2b2 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फ़ाइल स्थानांतरण"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिवाइस"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"इंटरनेट ऐक्सेस"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"संपर्क और कॉल का इतिहास शेयर करें"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"इसका इस्तेमाल संपर्क और कॉल का इतिहास शेयर करने के लिए करें"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इंटरनेट कनेक्शन साझाकरण"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"लेख संदेश"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम ऐक्सेस"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवा की क्वालिटी"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टिंग की जानकारी"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफ़ाइल फ़ोटो चुनें"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"उपयोगकर्ता के लिए डिफ़ॉल्ट आइकॉन"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"फ़िज़िकल कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index c979bc4..0e66858 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Upotreba odabira sustava (zadano)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Upotreba odabira sustava (zadano)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Upotreba odabira sustava (zadano)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 55a3e5e..267000f 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prijenos datoteke"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup internetu"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Dijeljenje kontakata i povijesti poziva"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Upotreba za dijeljenje kontakata i povijesti poziva"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Dijeljenje internetske veze"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvaliteta zraka"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Inform. o emitiranju"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Odabir profilne slike"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikona zadanog korisnika"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tipkovnica"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 230e554..a5f37ea 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Rendszerérték (alapértelmezett)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Rendszerérték (alapértelmezett)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Rendszerérték (alapértelmezett)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 2454d1c..69ddad8 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fájlátvitel"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Beviteli eszköz"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetelérés"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Névjegyek és hívásnapló megosztása"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Névjegyek és hívásnapló megosztásához használható"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetkapcsolat megosztása"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Szöveges üzenetek"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-elérés"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Időjárás"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Levegőminőség"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Átküldési információ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profilkép választása"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Alapértelmezett felhasználó ikonja"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizikai billentyűzet"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 2a9c544..50d7c7f 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
     <item msgid="8003118270854840095">"44,1 կՀց"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 8966551..d8efbd3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Ֆայլերի փոխանցում"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ներմուծման սարք"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ինտերնետի հասանելիություն"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Կիսվել կոնտակտներով/զանգերի պատմությամբ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Օգտագործել՝ կոնտակտներով/զանգերի պատմությամբ կիսվելու համար"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ինտերնետ կապի տարածում"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS հաղորդագրություններ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM քարտի հասանելիություն"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Եղանակ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Օդի որակը"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Հեռարձակման տվյալներ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Պրոֆիլի նկար ընտրեք"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Օգտատիրոջ կանխադրված պատկերակ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Ֆիզիկական ստեղնաշար"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 6349e53..5b0ad98 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Gunakan Pilihan Sistem (Default)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c525317..029ad8b 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer file"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat masukan"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Berbagi kontak dan histori panggilan"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gunakan untuk berbagi kontak dan histori panggilan"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Berbagi koneksi internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualitas Udara"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info Transmisi"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Pilih foto profil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna default"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Keyboard fisik"</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 730fcaf..9d481f8 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Nota val kerfisins (sjálfgefið)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Nota val kerfisins (sjálfgefið)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Nota val kerfisins (sjálfgefið)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index c06d2f0..ccf06b0 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Skráaflutningur"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inntakstæki"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetaðgangur"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Tengiliðir, SMS-skilaboð og símtalaferill"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Nota til að deila tengiliðum og símtalaferli"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deiling nettengingar"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Textaskilaboð"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Aðgangur að SIM-korti"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Veður"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Loftgæði"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Útsendingaruppl."</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Veldu prófílmynd"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Tákn sjálfgefins notanda"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Vélbúnaðarlyklaborð"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index b7e114f..62450da3 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usa selezione di sistema (predefinita)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usa selezione di sistema (predefinita)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usa selezione di sistema (predefinita)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b3ac25a..3811152 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Trasferimento file"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo di input"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accesso a Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Condivis. contatti e cronologia chiamate"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usa per condivisione di contatti e cronologia chiamate"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Condivisione connessione Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accesso alla SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualità dell\'aria"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info sul cast"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Scegli un\'immagine del profilo"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icona dell\'utente predefinito"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fisica"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 587016f..49f3fcf 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
     <item msgid="8003118270854840095">"44.1 קילו-הרץ"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index f021b37..3421fb5 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"העברת קבצים"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"מכשיר קלט"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"גישה לאינטרנט"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"שיתוף אנשי הקשר והיסטוריית השיחות"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ההגדרה משמשת לשיתוף של אנשי הקשר והיסטוריית השיחות"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"שיתוף חיבור לאינטרנט"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"הודעות טקסט"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‏גישה ל-SIM"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"מזג אוויר"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"איכות האוויר"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"פרטי ההעברה"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"בית חכם"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"בחירה של תמונת פרופיל"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"סמל המשתמש שמוגדר כברירת מחדל"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"מקלדת פיזית"</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index ad84d9e..d73cc43 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"システムの選択(デフォルト)を使用"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"システムの選択(デフォルト)を使用"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"システムの選択(デフォルト)を使用"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2994e4d..e7d2cf8 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ファイル転送"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"入力デバイス"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"インターネットアクセス"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"連絡先と通話履歴の共有"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"連絡先と通話履歴の共有に使用します"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"インターネット接続の共有"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"テキスト メッセージ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIMアクセス"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"天気"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"大気質"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"キャスト情報"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"プロフィール写真の選択"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"デフォルト ユーザー アイコン"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"物理キーボード"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 01f1dcc7..c0d6f97 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
     <item msgid="8003118270854840095">"44,1 კჰც"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 0c3277b..09f5471 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ფაილების გადაცემა"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"შეყვანის მოწყობილობა"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ინტერნეტზე წვდომა"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"კონტაქტ. და საუბრის ისტორიის გაზიარება"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"გამოიყენეთ კონტაქტებისა და საუბრის ისტორიის გასაზიარებლად"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ინტერნეტ კავშირის გაზიარება"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ტექსტური შეტყობინებები"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM წვდომა"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"ამინდი"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ჰაერის ხარისხი"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ტრანსლირების ინფო"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"სახლის მართვა"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"აირჩიეთ პროფილის სურათი"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"მომხმარებლის ნაგულისხმევი ხატულა"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ფიზიკური კლავიატურა"</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 33fd25b..fc998e7 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Жүйенің таңдағанын алу (әдепкі)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Жүйенің таңдағанын алу (әдепкі)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Жүйенің таңдағанын алу (әдепкі)"</item>
     <item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 63c9575..3281303 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл жіберу"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Кіріс құрылғысы"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке қосылу"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Контактілер мен қоңыраулар тарихын бөлісу"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Контактілер мен қоңыраулар тарихын бөлісу үшін пайдалану"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернет байланысын ортақ қолдану"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Мәтіндік хабарлар"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM картасына кіру"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Ауа райы"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ауа сапасы"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Трансляция ақпараты"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Профиль суретін таңдау"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Әдепкі пайдаланушы белгішесі"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Пернетақта"</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index ef3aa52..a005f4d 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 9b9228a..87c1aa2 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ផ្ទេរ​ឯកសារ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ឧបករណ៍​បញ្ចូល"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ការចូលប្រើ​អ៊ីនធឺណិត"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ការចែករំលែកទំនាក់ទំនង និងប្រវត្តិហៅទូរសព្ទ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ការប្រើសម្រាប់ការចែករំលែកទំនាក់ទំនង និងប្រវត្តិហៅទូរសព្ទ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ចែករំលែក​ការ​តភ្ជាប់​អ៊ីនធឺណិត"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"សារ​ជាអក្សរ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ការចូលដំណើរការស៊ីម"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"អាកាសធាតុ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"គុណភាព​ខ្យល់"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ព័ត៌មានអំពីការបញ្ជូន"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ជ្រើសរើស​រូបភាព​កម្រង​ព័ត៌មាន"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"រូបអ្នកប្រើប្រាស់លំនាំដើម"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ក្ដារចុច​រូបវន្ត"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 6623564..b6014ce 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
@@ -184,7 +172,7 @@
     <item msgid="7300881231043255746">"ಕೆರ್ನಲ್ ಮಾತ್ರ"</item>
   </string-array>
   <string-array name="select_logpersist_summaries">
-    <item msgid="97587758561106269">"ಆಫ್ ಆಗಿದೆ"</item>
+    <item msgid="97587758561106269">"ಆಫ್"</item>
     <item msgid="7126170197336963369">"ಎಲ್ಲಾ ಲಾಗ್ ಬಫರ್‌ಗಳು"</item>
     <item msgid="7167543126036181392">"ಎಲ್ಲಾ ಆದರೆ ರೇಡಿಯೊ ಲಾಗ್ ಬಫರ್‌ಗಳು"</item>
     <item msgid="5135340178556563979">"ಕೆರ್ನಲ್ ಲಾಗ್ ಬಫರ್ ಮಾತ್ರ"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 7071598..ab437e8 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ಇನ್‌ಪುಟ್‌ ಸಾಧನ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ಸಂಪರ್ಕಗಳು ಹಾಗೂ ಕರೆ ಇತಿಹಾಸ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ಸಂಪರ್ಕಗಳು ಮತ್ತು ಕರೆ ಇತಿಹಾಸ ಹಂಚಿಕೆಗಾಗಿ ಬಳಸಿ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ಪಠ್ಯ ಸಂದೇಶಗಳು"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ಸಿಮ್ ಪ್ರವೇಶ"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"ಹವಾಮಾನ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ವಾಯು ಗುಣಮಟ್ಟ"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ಬಿತ್ತರಿಸಿದ ಮಾಹಿತಿ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ಡೀಫಾಲ್ಟ್ ಬಳಕೆದಾರರ ಐಕಾನ್"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index a207706..7138113 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"시스템 설정 사용(기본)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"시스템 설정 사용(기본)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"시스템 설정 사용(기본)"</item>
     <item msgid="8003118270854840095">"44.1kHz"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 6ba289d..2b8ab75 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"파일 전송"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"입력 장치"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"인터넷 액세스"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"연락처 및 통화 기록 공유"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"연락처 및 통화 기록 공유에 사용"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"인터넷 연결 공유"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"문자 메시지"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 액세스"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"날씨"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"대기 상태"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"전송 정보"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"프로필 사진 선택하기"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"기본 사용자 아이콘"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"물리적 키보드"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 67cdc7c..40271f7 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"карта13"</item>
     <item msgid="8147982633566548515">"карта14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Система тандаганды колдонуу (демейки)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Система тандаганды колдонуу (демейки)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Система тандаганды колдонуу (демейки)"</item>
     <item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 3eb43fa..e993e3f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл алмашуу"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Киргизүү түзмөгү"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке мүмкүнчүлүк алуу"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Байланыштарды жана чалуу таржымалын бөлүшүү"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Байланыштарды жана чалуу таржымалын бөлүшүү үчүн колдонуу"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернет байланышын бөлүшүү"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS билдирүүлөрү"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM картаны пайдалануу мүмкүнчүлүгү"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Аба ырайы"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Абанын сапаты"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Тышкы экранга чыгаруу маалыматы"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Профилдин сүрөтүн тандоо"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Демейки колдонуучунун сүрөтчөсү"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Аппараттык баскычтоп"</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 56a9741..792ca39 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 2dcad1f..d295932 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ການໂອນຍ້າຍໄຟລ໌"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ອຸປະກອນປ້ອນຂໍ້ມູນ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ການເຂົ້າເຖິງອິນເຕີເນັດ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ແບ່ງປັນລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຫວັດການໂທ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ໃຊ້ສໍາລັບແບ່ງປັນລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຫວັດການໂທ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ການແບ່ງປັນການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ຂໍ້ຄວາມ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ການ​ເຂົ້າ​ເຖິງ SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"ສະພາບອາກາດ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ຄຸນນະພາບ​ອາກາດ"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ຂໍ້ມູນການສົ່ງສັນຍານ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ເລືອກຮູບໂປຣໄຟລ໌"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ໄອຄອນຜູ້ໃຊ້ເລີ່ມຕົ້ນ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ແປ້ນພິມພາຍນອກ"</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index a7aba78..946f69c 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Naudoti sistemos pasirink. (numatytasis)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Naudoti sistemos pasirink. (numatytasis)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Naudoti sistemos pasirink. (numatytasis)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 8aaec47..e38889b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failo perkėlimas"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Įvesties įrenginys"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prieiga prie interneto"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktų ir skambučių istorijos bendrinimas"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Naudoti kontaktams ir skambučių istorijai bendrinti"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneto ryšio bendrinimas"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Teksto pranešimai"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM prieiga"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Orai"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Oro kokybė"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Perdav. informacija"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Namų sist. valdikl."</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Pasirinkite profilio nuotrauką"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Numatytojo naudotojo piktograma"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizinė klaviatūra"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 840d794..f4ae452 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Sistēmas atlases izmantošana (nokl.)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Sistēmas atlases izmantošana (nokl.)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Sistēmas atlases izmantošana (nokl.)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index fcfb9b89..d899ada 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failu pārsūtīšana"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ievades ierīce"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneta piekļuve"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktpersonu un zvanu vēst. kopīgošana"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Paredzēts kontaktpersonu un zvanu vēstures kopīgošanai"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneta savienojuma koplietošana"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Īsziņas"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Piekļuve SIM kartei"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Laikapstākļi"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Gaisa kvalitāte"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Apraides informācija"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profila attēla izvēle"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Noklusējuma lietotāja ikona"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziskā tastatūra"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 2f22165..9c46f21 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Користи избор на системот (стандардно)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Користи избор на системот (стандардно)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Користи избор на системот (стандардно)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 144de00..c8033e3 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос на датотека"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Влезен уред"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Пристап до интернет"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Споделување контакти и историја на повици"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Користење на споделувањето контакти и историја на повици"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделување конекција на интернет"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстуални пораки"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Пристап до SIM"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Временска прогноза"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет на воздух"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Инфо за улогите"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Контроли за домот"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Изберете профилна слика"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Икона за стандарден корисник"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 3aa9472..4715e2a 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 59cd6bc..089f6af 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ഫയൽ കൈമാറൽ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ഇൻപുട്ട് ഉപകരണം"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ഇന്‍റർനെറ്റ് ആക്‌സസ്"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"കോ‌ൺടാക്‌റ്റുകളും കോൾ ചരിത്രം പങ്കിടലും"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"കോൺടാക്‌റ്റുകളുടെയും കോൾ ചരിത്രം പങ്കിടലിന്റെയും ഉപയോഗം"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ഇന്റർനെറ്റ് കണക്ഷൻ പങ്കിടൽ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"അക്ഷര സന്ദേശങ്ങൾ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"സിം ആക്സസ്"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"കാലാവസ്ഥ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"വായു നിലവാരം"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"കാസ്റ്റ് വിവരങ്ങൾ"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ഹോം കൺട്രോളുകൾ"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"പ്രൊഫൈൽ ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ഡിഫോൾട്ട് ഉപയോക്തൃ ഐക്കൺ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ഫിസിക്കൽ കീബോർഡ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 9bd10a78..63fa53b 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
     <item msgid="8003118270854840095">"44.1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 1bd6bea..cc35053 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл дамжуулалт"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Оруулах төхөөрөмж"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернэт хандалт"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Харилцагчид ба дуудлагын түүх хуваалцах"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Харилцагчид ба дуудлагын түүх хуваалцахад ашиглах"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернэт холболтыг хуваалцах"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Мессеж"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Хандалт"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Цаг агаар"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Агаарын чанар"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Дамжуулах мэдээлэл"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Гэрийн удирдлага"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Профайл зураг сонгох"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Өгөгдмөл хэрэглэгчийн дүрс тэмдэг"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Биет гар"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 45bc5b8..a54f990 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"सिस्टीम निवड वापरा (डीफॉल्ट)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index c163219..1907d00 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानांतरण"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिव्हाइस"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"इंटरनेट अ‍ॅक्सेस"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"संपर्क आणि कॉल इतिहास शेअरिंग"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"संपर्क आणि कॉल इतिहास शेअरिंगसाठी वापरा"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इंटरनेट कनेक्शन शेअररण"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"मजकूर मेसेज"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम अ‍ॅक्सेस"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"हवामान"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवेची गुणवत्ता"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसंबंधित माहिती"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"होम कंट्रोल"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो निवडा"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"डीफॉल्ट वापरकर्ता आयकन"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"वास्तविक कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index d88ea76..b26ed23 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Lalai)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Lalai)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Gunakan Pilihan Sistem (Lalai)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 55c8814..b3929c9 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Pemindahan fail"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Peranti input"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Perkongsian kenalan &amp; sejarah panggilan"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Digunakan untuk perkongsian kenalan dan sejarah panggilan"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Perkongsian sambungan Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesej Teks"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualiti Udara"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maklumat Pelakon"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Pilih gambar profil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna lalai"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Papan kekunci fizikal"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 857a6ae..ed95dfe 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
     <item msgid="8003118270854840095">"၄၄.၁ kHz"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 38b1fe8..f7a33a9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ဖိုင်လွဲပြောင်းခြင်း"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ထည့်သွင်းသော စက်"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"အင်တာနက်ချိတ်ဆက်ခြင်း"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"အဆက်အသွယ်၊ ယခင်ခေါ်ဆိုမှုများ မျှဝေခြင်း"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"အဆက်အသွယ်နှင့် ယခင်ခေါ်ဆိုမှုများ မျှဝေရန် သုံးသည်"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"အင်တာနက်ဆက်သွယ်မှု မျှဝေခြင်း"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"မိုဘိုင်းမက်ဆေ့ဂျ်များ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM အသုံးပြုခြင်း"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"မိုးလေဝသ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"လေထုအရည်အသွေး"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ကာစ် အချက်အလက်"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ပရိုဖိုင်ပုံ ရွေးပါ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"မူရင်းအသုံးပြုသူ သင်္ကေတ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ပကတိ ကီးဘုတ်"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 0f6e1fc..317c2db 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Bruk systemvalg (standard)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Bruk systemvalg (standard)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Bruk systemvalg (standard)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index ef2111d..9b99631 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverføring"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inndataenhet"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internett-tilgang"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling av kontakter og anropslogg"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Bruk for deling av kontakter og anropslogg"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling av internettilkobling"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstmeldinger"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Tilgang til SIM-kortet"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vær"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformasjon"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Velg et profilbilde"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Standard brukerikon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 611066e..b3c3ee2 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
     <item msgid="8003118270854840095">"४४.१ kHz"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 9fa7749..1534cba 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानान्तरण"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट उपकरण"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"इन्टरनेट पहुँच"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"कन्ट्याक्ट र कलको इतिहास सेयर गर्ने"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"कन्ट्याक्ट र कलको इतिहास सेयर गर्न प्रयोग गरियोस्"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इन्टरनेट जडान साझेदारी गर्दै"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"टेक्स्ट म्यासेजहरू"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM पहुँच"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"वायुको गुणस्तर"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसम्बन्धी जानकारी"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो छान्नुहोस्"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"प्रयोगकर्ताको डिफल्ट आइकन"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"भौतिक किबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index e0690df..e809452 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Systeemselectie gebruiken (standaard)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Gebruik systeemselectie (standaard)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Systeemselectie gebruiken (standaard)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index f4cbfd5..ba11b46 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Bestandsoverdracht"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoerapparaat"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacten en gespreksgeschiedenis delen"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gebruiken om contacten en gespreksgeschiedenis te delen"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetverbinding delen"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-berichten"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Sim-toegang"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luchtkwaliteit"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformatie"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Bediening voor in huis"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Kies een profielfoto"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Standaard gebruikersicoon"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiek toetsenbord"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index dd25b3e..d42aeaf 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ସିଷ୍ଟମ୍ ଚୟନ ବ୍ୟବହାର କରନ୍ତୁ (ଡିଫଲ୍ଟ)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ସିଷ୍ଟମ୍‌ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ସିଷ୍ଟମ୍‌ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 76c3671..09fa59d 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ଇନ୍‌ପୁଟ୍‌ ଡିଭାଇସ୍"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ଇଣ୍ଟର୍‌ନେଟ୍‌ ଆକ୍ସେସ୍"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"କଣ୍ଟାକ୍ଟ ଏବଂ କଲ ଇତିହାସ ସେୟାରିଂ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"କଣ୍ଟାକ୍ଟ ଏବଂ କଲ ଇତିହାସ ସେୟାରିଂ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ଇଣ୍ଟର୍‌ନେଟ୍‌ ସଂଯୋଗ ଶେୟାରିଙ୍ଗ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ଟେକ୍ସଟ୍ ମେସେଜ୍"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM ଆକ୍ସେସ୍‌"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"ପାଣିପାଗ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ବାୟୁର ଗୁଣବତ୍ତା"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"କାଷ୍ଟ ସୂଚନା"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ଏକ ପ୍ରୋଫାଇଲ ଛବି ବାଛନ୍ତୁ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ଡିଫଲ୍ଟ ଉପଯୋଗକର୍ତ୍ତା ଆଇକନ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ଫିଜିକାଲ କୀବୋର୍ଡ"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 6ba2145..a3fae22 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index e34ece8..9df0fef 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ਇਨਪੁੱਟ ਡੀਵਾਈਸ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ਸੰਪਰਕ ਅਤੇ ਕਾਲ ਇਤਿਹਾਸ ਸਾਂਝਾ ਕਰਨਾ"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ਸੰਪਰਕ ਅਤੇ ਕਾਲ ਇਤਿਹਾਸ ਸਾਂਝਾ ਕਰਨ ਲਈ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਸਾਂਝਾਕਰਨ"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ਲਿਖਤ ਸੁਨੇਹੇ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"ਸਿਮ ਪਹੁੰਚ"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"ਮੌਸਮ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ਹਵਾ ਦੀ ਕੁਆਲਿਟੀ"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ਕਾਸਟ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"ਕੋਈ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਚੁਣੋ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਰਤੋਂਕਾਰ ਪ੍ਰਤੀਕ"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 5f91d35..f0453d1 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Używaj wyboru systemu (domyślnie)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Używaj wyboru systemu (domyślnie)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Używaj wyboru systemu (domyślnie)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index fe56c61..f4599fd 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Przesyłanie pliku"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Urządzenie wejściowe"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Dostęp do internetu"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Udostępnianie kontaktów i historii połączeń"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Używaj w przypadku udostępniania kontaktów i historii połączeń"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Udostępnianie połączenia internetowego"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-y"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostęp do karty SIM"</string>
@@ -228,7 +226,7 @@
     <string name="category_personal" msgid="6236798763159385225">"Osobiste"</string>
     <string name="category_work" msgid="4014193632325996115">"Służbowe"</string>
     <string name="development_settings_title" msgid="140296922921597393">"Opcje programisty"</string>
-    <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje dla programistów"</string>
+    <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje programisty"</string>
     <string name="development_settings_summary" msgid="8718917813868735095">"Ustaw opcje związane z programowaniem aplikacji."</string>
     <string name="development_settings_not_available" msgid="355070198089140951">"Opcje programisty są niedostępne dla tego użytkownika"</string>
     <string name="vpn_settings_not_available" msgid="2894137119965668920">"Ustawienia VPN są niedostępne dla tego użytkownika"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Pogoda"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Jakość powietrza"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Obsada"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Wybierz zdjęcie profilowe"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikona domyślnego użytkownika"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Klawiatura fizyczna"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index c5a847f..1883ef3 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index aa66c6043..12507c5 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartilhar contatos e histórico de chamadas"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use para compartilhar contatos e o histórico de chamadas"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartilhamento de conexão à Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade ­do ar"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 3e7ee05..985bd51 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Utilizar seleção do sistema (predefinido)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Utilizar seleção do sistema (predefinido)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Utilizar seleção do sistema (predefinido)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index cf76780..4988136 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência do ficheiro"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Part. histórico de chamadas e contactos"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usar para partilha do histórico de chamadas e dos contactos"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partilha da ligação à internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao SIM"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteorologia"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ctr. domésticos"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Escolha uma imagem do perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ícone do utilizador predefinido"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index c5a847f..1883ef3 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index aa66c6043..12507c5 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartilhar contatos e histórico de chamadas"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use para compartilhar contatos e o histórico de chamadas"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartilhamento de conexão à Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade ­do ar"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 454867e..f1e9986 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Folosiți selectarea sistemului (prestabilit)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Folosiți selectarea sistemului (prestabilit)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Folosiți selectarea sistemului (prestabilit)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 946f4b7..f49fcdd 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer de fișiere"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispozitiv de intrare"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acces la internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Acces la agendă și istoricul apelurilor"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Folosiți pentru accesul la agendă și istoricul apelurilor"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Distribuirea conexiunii la internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesaje text"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acces la SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calitatea aerului"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informații artiști"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Alegeți o fotografie de profil"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Pictograma prestabilită a utilizatorului"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastatură fizică"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 28b4695..b1211a5 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Выбор системы (по умолчанию)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Выбор системы (по умолчанию)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Выбор системы (по умолчанию)"</item>
     <item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index bcd83cf..38930a5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Профиль OPP"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Профиль HID"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ к интернету"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Доступ к контактам и журналу звонков"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Использовать для доступа к контактам и журналу звонков"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Профиль PAN"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстовые сообщения"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ к SIM-карте"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество воздуха"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Данные о трансляции"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Выберите фото профиля"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Значок пользователя по умолчанию"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Физическая клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index c2dbf60..8386c1a 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්‍රව්‍යය"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්‍රව්‍යය"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්‍රව්‍යය"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්‍රව්‍යය"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 7f5eb49..fa0296f 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ගොනු හුවමාරුව"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ආදාන උපාංගය"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"අන්තර්ජාල ප්‍රවේශය"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"සම්බන්ධතා සහ ඇමතුම් ඉතිහාසය බෙදා ගැනීම"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"සම්බන්ධතා සහ ඇමතුම් ඉතිහාසය බෙදා ගැනීම සඳහා භාවිතා කරන්න"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"අන්තර්ජාල සම්බන්ධතා බෙදාගැනීම"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"පෙළ පණිවිඩ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM ප්‍රවේශය"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"කාලගුණය"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"වායු ගුණත්වය"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"විකාශ තතු"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"පැතිකඩ පින්තූරයක් තේරීම"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"පෙරනිමි පරිශීලක නිරූපකය"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"භෞතික යතුරු පුවරුව"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index b285888..370b23f 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Použiť voľbu systému (predvolené)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Použiť voľbu systému (predvolené)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Použiť voľbu systému (predvolené)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 31925ea..a7c69c8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupné zariadenie"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prístup na internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľanie kontaktov a histórie hovorov"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používané pri zdieľaní kontaktov a histórie hovorov"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Zdieľanie pripojenia na Internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové správy"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Prístup k SIM karte"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Počasie"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informácie o prenose"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ovládanie domácnosti"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Výber profilovej fotky"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Predvolená ikona používateľa"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnica"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 8db3e99..6e33e38 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Uporabi sistemsko izbiro (privzeto)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Uporabi sistemsko izbiro (privzeto)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Uporabi sistemsko izbiro (privzeto)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 687ff38..7334cea 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vnosna naprava"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetni dostop"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deljenje stikov in zgodovine klicev"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uporabite za deljenje stikov in zgodovine klicev."</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deljenje internetne povezave"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sporočila SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostop do kartice SIM"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kakovost zraka"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"O zasedbi"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Nadzor doma"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"Izbira profilne slike"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Privzeta ikona uporabnika"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fizična tipkovnica"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index a82f716..8a6d853 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7e96990..59359cdf 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferimi i skedarëve"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Pajisja e hyrjes"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Qasje në internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Ndarje: kontakte e historik telefonatash"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Përdor për ndarje kontaktesh e të historikut të telefonatave"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ndarja e lidhjes së internetit"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesazhet me tekst"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Qasje në kartën SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Moti"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Cilësia e ajrit"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Të dhënat e aktorëve"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Zgjidh një fotografi profili"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikona e parazgjedhur e përdoruesit"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fizike"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 4cd83606..7e198bf 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Користи избор система (подразумевано)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Користи избор система (подразумевано)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Користи избор система (подразумевано)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 2842223..eee3f89 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос датотеке"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Улазни уређај"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Приступ Интернету"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Дељење контаката и историје позива"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Користите за дељење контаката и историје позива"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Дељење интернет везе"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ови"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Приступ SIM картици"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Време"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет ваздуха"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Подаци о пребацивању"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Одаберите слику профила"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Подразумевана икона корисника"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 1432ec2..f99a85b 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Använd systemval (standardinställning)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Använd systemval (standardinställning)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Använd systemval (standardinställning)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index b0f8df5..1a8815c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filöverföring"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Indataenhet"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetåtkomst"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Delning av kontakter och samtalshistorik"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Använd för delning av kontakter och samtalshistorik"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Delning av Internetanslutning"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-åtkomst"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Väder"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info om rollistan"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Välj en profilbild"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Ikon för standardanvändare"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiskt tangentbord"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index cb74761..dab4279 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"ramani ya 13"</item>
     <item msgid="8147982633566548515">"ramani ya 14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
     <item msgid="8003118270854840095">"kHz 44.1"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 7e62d3f..5f1d141 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Uhamishaji wa faili"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Kifaa cha kuingiza"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ufikiaji wa intaneti"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kushiriki anwani na rekodi ya simu zilizopigwa"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Tumia kushiriki anwani na rekodi ya simu zilizopigwa"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Kushiriki muunganisho wa tovuti"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ufikiaji wa SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Hali ya Hewa"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ubora wa Hewa"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maelezo ya Wahusika"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Chagua picha ya wasifu"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Aikoni chaguomsingi ya mtumiaji"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Kibodi halisi"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 1f5380f..a0f1fa6 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index abab3fb..b8c37b0 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ஃபைல் இடமாற்றம்"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"உள்ளீட்டுச் சாதனம்"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"இணைய அணுகல்"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"தொடர்புகள் &amp; அழைப்புப் பதிவைப் பகிர்தல்"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"தொடர்புகளையும் அழைப்புப் பதிவையும் பகிர்வதற்குப் பயன்படுத்து"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"இணைய இணைப்பு பகிர்தல்"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"உரைச் செய்திகள்"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"சிம் அணுகல்"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"வானிலை"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"காற்றின் தரம்"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"அலைபரப்புத் தகவல்"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"சுயவிவரப் படத்தைத் தேர்வுசெய்யுங்கள்"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"இயல்புநிலைப் பயனர் ஐகான்"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"கீபோர்டு"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 513fb6e..18a2758 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index a362f24..504c827 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"ఫైల్ బదిలీ"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ఇన్‌పుట్ పరికరం"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"ఇంటర్నెట్ యాక్సెస్"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ షేరింగ్"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"టెక్స్ట్ మెసేజ్‌లు"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM యాక్సెస్"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"వాతావరణం"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"గాలి క్వాలిటీ"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"కాస్ట్ సమాచారం"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"హోమ్ కంట్రోల్స్"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"ప్రొఫైల్ ఫోటోను ఎంచుకోండి"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ఆటోమేటిక్ సెట్టింగ్ యూజర్ చిహ్నం"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"భౌతిక కీబోర్డ్"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 732124a..04a5f4d 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index a4e0508..f33630d 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"การถ่ายโอนไฟล์"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"อุปกรณ์อินพุต"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"การเข้าถึงอินเทอร์เน็ต"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"การแชร์รายชื่อติดต่อและประวัติการโทร"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ใช้สำหรับการแชร์รายชื่อติดต่อและประวัติการโทร"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"การแชร์การเชื่อมต่ออินเทอร์เน็ต"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ข้อความ"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"การเข้าถึงซิม"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"สภาพอากาศ"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"คุณภาพอากาศ"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ข้อมูลแคสต์"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"เลือกรูปโปรไฟล์"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ไอคอนผู้ใช้เริ่มต้น"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"แป้นพิมพ์จริง"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index bdd8706..59cb1f3 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Gamitin ang Pagpili ng System (Default)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Gamitin ang Pagpili ng System (Default)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Gamitin ang Pagpili ng System (Default)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e28fd96..f95f0e50 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Paglilipat ng file"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Device sa pag-input"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Access sa internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts at pagbabahagi ng call history"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gamitin para sa contacts at pagbabahagi ng call history"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Pagbabahagi ng koneksyon sa internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Mga Text Message"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Access sa SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Lagay ng Panahon"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kalidad ng Hangin"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Impormasyon ng Cast"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Pumili ng larawan sa profile"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Icon ng default na user"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Pisikal na keyboard"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 0d0c69a..5ed35fa 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Sistem Seçimini Kullan (Varsayılan)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Sistem Seçimini Kullan (Varsayılan)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Sistem Seçimini Kullan (Varsayılan)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 05ec1cc..2fa2bd1 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dosya aktarımı"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Giriş cihazı"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"İnternet erişimi"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kişi ve çağrı geçmişi paylaşımı"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kişi ve çağrı geçmişi paylaşımı için kullanın"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"İnternet bağlantısı paylaşımı"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Kısa Mesajlar"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Erişimi"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Hava durumu"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Hava Kalitesi"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayın Bilgisi"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profil fotoğrafı seçin"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Varsayılan kullanıcı simgesi"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziksel klavye"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 49a4635..0410bd6 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Використовувати вибір системи (за умовчанням)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Використовувати вибір системи (за умовчанням)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Використовувати вибір системи (за умовчанням)"</item>
     <item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 184d0c1..9be0855 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Передавання файлів"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Пристрій введення"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ до Інтернету"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Надсилання контактів та історії викликів"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Використовуйте, щоб надсилати контакти й історію викликів"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Надання доступу до Інтернету"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстові повідомлення"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ до SIM-карти"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якість повітря"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Акторський склад"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Виберіть зображення профілю"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Значок користувача за умовчанням"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Фізична клавіатура"</string>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 5dc2123..d097458 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 419833a..8eb9a11 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"فائل کی منتقلی"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"ان پٹ آلہ"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"انٹرنیٹ تک رسائی"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"رابطے اور کال کی سرگزشت کا اشتراک"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"رابطے اور کال کی سرگزشت کے اشتراک کے لیے استعمال کریں"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"انٹرنیٹ کنکشن کا اشتراک کرنا"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"ٹیکسٹ پیغامات"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"‏SIM رسائی"</string>
@@ -662,6 +660,7 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"موسم"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"ہوا کا معیار"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"کاسٹ کرنے کی معلومات"</string>
+    <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ہوم کنٹرولز"</string>
     <string name="avatar_picker_title" msgid="8492884172713170652">"پروفائل کی تصویر منتخب کریں"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"ڈیفالٹ صارف کا آئیکن"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"فزیکل کی بورڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 589c592..7d09027 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Tizim tanlovi (birlamchi)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Tizim tanlovi (birlamchi)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Tizim tanlovi (birlamchi)"</item>
     <item msgid="8003118270854840095">"44.1 kGs"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index b1e22af..a5c8683 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl uzatish"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Kiritish qurilmasi"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetga ulanish"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontakt va chaqiruvlar tarixiga kirish"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kontaktlar va chaqiruvlar tarixiga kirish uchun foydalaning"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet aloqasi ulashmasi"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS xabarlari"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM kartaga kirish"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Ob-havo"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havo sifati"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Translatsiya axboroti"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Profil rasmini tanlash"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Foydalanuvchining standart belgisi"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Tashqi klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 4cf8ff4..31867e2 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="2908219194098827570">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
-    <item msgid="3517061573669307965">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
     <item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 71bb08e..45a0465 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Chuyển tệp"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Thiết bị đầu vào"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Truy cập Internet"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Chia sẻ danh bạ và nhật ký cuộc gọi"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Dùng để chia sẻ danh bạ và nhật ký cuộc gọi"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Chia sẻ kết nối internet"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Tin nhắn văn bản"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Truy cập SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Thời tiết"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Chất lượng không khí"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Thông tin về dàn nghệ sĩ"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Chọn một ảnh hồ sơ"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Biểu tượng người dùng mặc định"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Bàn phím thực"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index af87f6f..973d7d0 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"使用系统选择(默认)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"使用系统选择(默认)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"使用系统选择(默认)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f9e087b..2bc8a30 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"文件传输"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"输入设备"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"互联网连接"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"联系人信息和通话记录分享"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用于联系人信息和通话记录分享"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"共享互联网连接"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"短信"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取权限"</string>
@@ -661,7 +659,9 @@
     <string name="dream_complication_title_date" msgid="8661176085446135789">"日期"</string>
     <string name="dream_complication_title_weather" msgid="598609151677172783">"天气"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空气质量"</string>
-    <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投射信息"</string>
+    <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放信息"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"选择个人资料照片"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"默认用户图标"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"实体键盘"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 2099410..87f3825 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"使用系統選擇 (預設)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"使用系統選擇 (預設)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"使用系統選擇 (預設)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index cd93f71..114bc64 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"輸入裝置"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"互聯網連線"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"分享通訊錄及通話記錄"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用於分享通訊錄及通話記錄"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"互聯網連線分享"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"短訊"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣質素"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放資料"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人檔案相片"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 24991e3..529287f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"map13"</item>
     <item msgid="8147982633566548515">"map14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"系統自動選擇 (預設)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
-    <item msgid="3825367753087348007">"LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"系統自動選擇 (預設)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
-    <item msgid="2553206901068987657">"LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"系統自動選擇 (預設)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 4f36742..a7ae213 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"輸入裝置"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"網際網路連線"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"分享聯絡人和通話記錄"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用於分享聯絡人和通話記錄"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"網際網路連線分享"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"簡訊"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取權"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣品質"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"演出者資訊"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人資料相片"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 8732b26..59ead86 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -85,22 +85,10 @@
     <item msgid="7073042887003102964">"Imephu13"</item>
     <item msgid="8147982633566548515">"Imephu14"</item>
   </string-array>
-  <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="2494959071796102843">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
-    <item msgid="4055460186095649420">"SBC"</item>
-    <item msgid="720249083677397051">"I-AAC"</item>
-    <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
-    <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
-    <item msgid="3825367753087348007">"I-LDAC"</item>
-  </string-array>
-  <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="8868109554557331312">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
-    <item msgid="9024885861221697796">"SBC"</item>
-    <item msgid="4688890470703790013">"I-AAC"</item>
-    <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
-    <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
-    <item msgid="2553206901068987657">"I-LDAC"</item>
-  </string-array>
+    <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+    <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+    <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
     <item msgid="926809261293414607">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
     <item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 88c41c5..e037d12 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -117,10 +117,8 @@
     <string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dlulisa ifayela"</string>
     <string name="bluetooth_profile_hid" msgid="2969922922664315866">"Idivaysi yokufakwayo"</string>
     <string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ukufinyelela i-Inthanethi"</string>
-    <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
-    <skip />
-    <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
-    <skip />
+    <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Ukwabelana ngoxhumana nabo nomlando wekholi"</string>
+    <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Ukusetshenziswa kokwabelana ngoxhumana nabo nomlando wekholi"</string>
     <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ukwabelana ngoxhumano lwe-Inthanethi"</string>
     <string name="bluetooth_profile_map" msgid="8907204701162107271">"Imilayezo yombhalo"</string>
     <string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ukufinyelela kwe-SIM"</string>
@@ -662,6 +660,8 @@
     <string name="dream_complication_title_weather" msgid="598609151677172783">"Isimo sezulu"</string>
     <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ikhwalithi Yomoya"</string>
     <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Ulwazi Lokusakaza"</string>
+    <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+    <skip />
     <string name="avatar_picker_title" msgid="8492884172713170652">"Khetha isithombe sephrofayela"</string>
     <string name="default_user_icon_description" msgid="6554047177298972638">"Isithonjana somsebenzisi sokuzenzakalelayo"</string>
     <string name="physical_keyboard_title" msgid="4811935435315835220">"Ikhibhodi ephathekayo"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a79cbb6..b879223 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1610,6 +1610,9 @@
     <string name="dream_complication_title_cast_info">Cast Info</string>
     <!-- Screensaver overlay which displays home controls. [CHAR LIMIT=20] -->
     <string name="dream_complication_title_home_controls">Home Controls</string>
+    <!-- Screensaver overlay which displays smartspace. [CHAR LIMIT=20] -->
+    <string name="dream_complication_title_smartspace">Smartspace</string>
+
 
     <!-- Title for a screen allowing the user to choose a profile picture. [CHAR LIMIT=NONE] -->
     <string name="avatar_picker_title">Choose a profile picture</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index a46e232..2258617 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -92,7 +92,8 @@
             COMPLICATION_TYPE_WEATHER,
             COMPLICATION_TYPE_AIR_QUALITY,
             COMPLICATION_TYPE_CAST_INFO,
-            COMPLICATION_TYPE_HOME_CONTROLS
+            COMPLICATION_TYPE_HOME_CONTROLS,
+            COMPLICATION_TYPE_SMARTSPACE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ComplicationType {}
@@ -103,6 +104,7 @@
     public static final int COMPLICATION_TYPE_AIR_QUALITY = 4;
     public static final int COMPLICATION_TYPE_CAST_INFO = 5;
     public static final int COMPLICATION_TYPE_HOME_CONTROLS = 6;
+    public static final int COMPLICATION_TYPE_SMARTSPACE = 7;
 
     private final Context mContext;
     private final IDreamManager mDreamManager;
@@ -351,6 +353,9 @@
             case COMPLICATION_TYPE_HOME_CONTROLS:
                 res = R.string.dream_complication_title_home_controls;
                 break;
+            case COMPLICATION_TYPE_SMARTSPACE:
+                res = R.string.dream_complication_title_smartspace;
+                break;
             default:
                 return null;
         }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 2f36ab9..8f9ced6 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -23,7 +23,6 @@
 import android.graphics.Color
 import android.graphics.Rect
 import android.os.Looper
-import android.service.dreams.IDreamManager
 import android.util.Log
 import android.util.MathUtils
 import android.view.GhostView
@@ -54,7 +53,7 @@
 class DialogLaunchAnimator
 @JvmOverloads
 constructor(
-    private val dreamManager: IDreamManager,
+    private val callback: Callback,
     private val interactionJankMonitor: InteractionJankMonitor,
     private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
     private val isForTesting: Boolean = false
@@ -126,7 +125,7 @@
         val animatedDialog =
             AnimatedDialog(
                 launchAnimator,
-                dreamManager,
+                callback,
                 interactionJankMonitor,
                 animateFrom,
                 onDialogDismissed = { openedDialogs.remove(it) },
@@ -194,8 +193,12 @@
 
         val dialog = animatedDialog.dialog
 
-        // Don't animate if the dialog is not showing.
-        if (!dialog.isShowing) {
+        // Don't animate if the dialog is not showing or if we are locked and going to show the
+        // bouncer.
+        if (
+            !dialog.isShowing ||
+            (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())
+        ) {
             return null
         }
 
@@ -285,6 +288,23 @@
             ?.let { it.touchSurface = it.prepareForStackDismiss() }
         dialog.dismiss()
     }
+
+    interface Callback {
+        /** Whether the device is currently in dreaming (screensaver) mode. */
+        fun isDreaming(): Boolean
+
+        /**
+         * Whether the device is currently unlocked, i.e. if it is *not* on the keyguard or if the
+         * keyguard can be dismissed.
+         */
+        fun isUnlocked(): Boolean
+
+        /**
+         * Whether we are going to show alternate authentication (like UDFPS) instead of the
+         * traditional bouncer when unlocking the device.
+         */
+        fun isShowingAlternateAuthOnUnlock(): Boolean
+    }
 }
 
 /**
@@ -296,7 +316,7 @@
 
 private class AnimatedDialog(
     private val launchAnimator: LaunchAnimator,
-    private val dreamManager: IDreamManager,
+    private val callback: DialogLaunchAnimator.Callback,
     private val interactionJankMonitor: InteractionJankMonitor,
 
     /** The view that triggered the dialog after being tapped. */
@@ -850,7 +870,7 @@
 
         // If we are dreaming, the dialog was probably closed because of that so we don't animate
         // into the touchSurface.
-        if (dreamManager.isDreaming) {
+        if (callback.isDreaming()) {
             return false
         }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index a8a526a..f7049cf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -48,9 +48,13 @@
     val default: T
 }
 
+/**
+ * Base class for most common boolean flags.
+ *
+ * See [UnreleasedFlag] and [ReleasedFlag] for useful implementations.
+ */
 // Consider using the "parcelize" kotlin library.
-
-data class BooleanFlag @JvmOverloads constructor(
+abstract class BooleanFlag constructor(
     override val id: Int,
     override val default: Boolean = false,
     override val teamfood: Boolean = false,
@@ -60,7 +64,7 @@
     companion object {
         @JvmField
         val CREATOR = object : Parcelable.Creator<BooleanFlag> {
-            override fun createFromParcel(parcel: Parcel) = BooleanFlag(parcel)
+            override fun createFromParcel(parcel: Parcel) = object : BooleanFlag(parcel) {}
             override fun newArray(size: Int) = arrayOfNulls<BooleanFlag>(size)
         }
     }
@@ -80,12 +84,46 @@
     }
 }
 
+/**
+ * A Flag that is is false by default.
+ *
+ * It can be changed or overridden in debug builds but not in release builds.
+ */
+data class UnreleasedFlag @JvmOverloads constructor(
+    override val id: Int,
+    override val teamfood: Boolean = false,
+    override val overridden: Boolean = false
+) : BooleanFlag(id, false, teamfood, overridden)
+
+/**
+ * A Flag that is is true by default.
+ *
+ * It can be changed or overridden in any build, meaning it can be turned off if needed.
+ */
+data class ReleasedFlag @JvmOverloads constructor(
+    override val id: Int,
+    override val teamfood: Boolean = false,
+    override val overridden: Boolean = false
+) : BooleanFlag(id, true, teamfood, overridden)
+
+/**
+ * A Flag that reads its default values from a resource overlay instead of code.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
 data class ResourceBooleanFlag @JvmOverloads constructor(
     override val id: Int,
     @BoolRes override val resourceId: Int,
     override val teamfood: Boolean = false
 ) : ResourceFlag<Boolean>
 
+/**
+ * A Flag that can reads its overrides from DeviceConfig.
+ *
+ * This is generally useful for flags that come from or are used _outside_ of SystemUI.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
 data class DeviceConfigBooleanFlag @JvmOverloads constructor(
     override val id: Int,
     override val name: String,
@@ -94,6 +132,13 @@
     override val teamfood: Boolean = false
 ) : DeviceConfigFlag<Boolean>
 
+/**
+ * A Flag that can reads its overrides from System Properties.
+ *
+ * This is generally useful for flags that come from or are used _outside_ of SystemUI.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
 data class SysPropBooleanFlag @JvmOverloads constructor(
     override val id: Int,
     override val name: String,
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index 2560284..74bd9c6 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -27,7 +27,8 @@
 import javax.inject.Named
 
 @Module(includes = [
-    SettingsUtilModule::class
+    ServerFlagReaderModule::class,
+    SettingsUtilModule::class,
 ])
 abstract class FlagsModule {
     @Binds
@@ -46,4 +47,4 @@
         @Named(ALL_FLAGS)
         fun providesAllFlags(): Map<Int, Flag<*>> = Flags.collectFlags()
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index ab9e01e..38b5c9a 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -19,8 +19,8 @@
 import dagger.Binds
 import dagger.Module
 
-@Module
+@Module(includes = [ServerFlagReaderModule::class])
 abstract class FlagsModule {
     @Binds
     abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
index 23195af..00f1c01 100644
--- a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
@@ -33,6 +33,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.dagger.KeyguardBouncerScope;
 import com.android.systemui.dagger.qualifiers.Main;
 
@@ -208,7 +209,7 @@
             hide();
             if (mKeyguardCallback != null) {
                 mKeyguardCallback.dismiss(/* securityVerified= */ true, userId,
-                        /* bypassSecondaryLockScreen= */true);
+                        /* bypassSecondaryLockScreen= */true, SecurityMode.Invalid);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index eb418ff..b8fcb10 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -179,7 +179,7 @@
             if (dismissKeyguard) {
                 mDismissing = true;
                 mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
-                getKeyguardSecurityCallback().dismiss(true, userId);
+                getKeyguardSecurityCallback().dismiss(true, userId, getSecurityMode());
             }
         } else {
             if (isValidPassword) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index d32219a..db64f05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -90,7 +90,7 @@
                                 Log.i(TAG, "TrustAgent dismissed Keyguard.");
                             }
                             mSecurityCallback.dismiss(false /* authenticated */, userId,
-                                    /* bypassSecondaryLockScreen */ false);
+                                    /* bypassSecondaryLockScreen */ false, SecurityMode.Invalid);
                         } else {
                             mViewMediatorCallback.playTrustedSound();
                         }
@@ -102,9 +102,9 @@
 
         @Override
         public boolean dismiss(boolean authenticated, int targetUserId,
-                boolean bypassSecondaryLockScreen) {
+                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
             return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
-                    authenticated, targetUserId, bypassSecondaryLockScreen);
+                    authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
         }
 
         @Override
@@ -212,7 +212,8 @@
      * @return True if the keyguard is done.
      */
     public boolean dismiss(int targetUserId) {
-        return mSecurityCallback.dismiss(false, targetUserId, false);
+        return mSecurityCallback.dismiss(false, targetUserId, false,
+                getCurrentSecurityMode());
     }
 
     /**
@@ -360,10 +361,10 @@
     }
 
     public boolean handleBackKey() {
-        if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
-                != SecurityMode.None) {
+        SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
+        if (securityMode != SecurityMode.None) {
             mKeyguardSecurityContainerController.dismiss(
-                    false, KeyguardUpdateMonitor.getCurrentUser());
+                    false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
             return true;
         }
         return false;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 98ac640..87300c3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -59,10 +59,11 @@
             return false;
         }
         @Override
-        public void dismiss(boolean securityVerified, int targetUserId) { }
+        public void dismiss(boolean securityVerified, int targetUserId,
+                SecurityMode expectedSecurityMode) { }
         @Override
         public void dismiss(boolean authenticated, int targetId,
-                boolean bypassSecondaryLockScreen) { }
+                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
         @Override
         public void onUserInput() { }
         @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index 58e0fb96..0ea1965 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -55,10 +55,11 @@
     val faceAuthenticated: Boolean,
     val faceDisabled: Boolean,
     val goingToSleep: Boolean,
-    val keyguardAwake: Boolean,
+    val keyguardAwakeExcludingBouncerShowing: Boolean,
     val keyguardGoingAway: Boolean,
     val listeningForFaceAssistant: Boolean,
     val occludingAppRequestingFaceAuth: Boolean,
+    val onlyFaceEnrolled: Boolean,
     val primaryUser: Boolean,
     val scanningAllowedByStrongAuth: Boolean,
     val secureCameraLaunched: Boolean,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index b97d9671..9aa6f03 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -171,7 +171,7 @@
                 if (dismissKeyguard) {
                     mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
                     mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
-                    getKeyguardSecurityCallback().dismiss(true, userId);
+                    getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
                 }
             } else {
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index e384727..bc72f79 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -15,14 +15,17 @@
  */
 package com.android.keyguard;
 
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
 public interface KeyguardSecurityCallback {
 
     /**
      * Dismiss the given security screen.
      * @param securityVerified true if the user correctly entered credentials for the given screen.
      * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+     * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    void dismiss(boolean securityVerified, int targetUserId);
+    void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
 
     /**
      * Dismiss the given security screen.
@@ -30,8 +33,10 @@
      * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
      * @param bypassSecondaryLockScreen true if the user can bypass the secondary lock screen,
      *                                  if any, during this dismissal.
+     * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen);
+    void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
+            SecurityMode expectedSecurityMode);
 
     /**
      * Manually report user activity to keep the device awake.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8fb622a..f697e25 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -236,7 +236,12 @@
 
     // Used to notify the container when something interesting happens.
     public interface SecurityCallback {
-        boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
+        /**
+         * Potentially dismiss the current security screen, after validating that all device
+         * security has been unlocked. Otherwise show the next screen.
+         */
+        boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
+                SecurityMode expectedSecurityMode);
 
         void userActivity();
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 0b3fe46..e1957c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -156,14 +156,17 @@
         }
 
         @Override
-        public void dismiss(boolean authenticated, int targetId) {
-            dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false);
+        public void dismiss(boolean authenticated, int targetId,
+                SecurityMode expectedSecurityMode) {
+            dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false,
+                    expectedSecurityMode);
         }
 
         @Override
         public void dismiss(boolean authenticated, int targetId,
-                boolean bypassSecondaryLockScreen) {
-            mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen);
+                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
+            mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
+                    expectedSecurityMode);
         }
 
         public boolean isVerifyUnlockOnly() {
@@ -385,8 +388,13 @@
         return mCurrentSecurityMode;
     }
 
-    public void dismiss(boolean authenticated, int targetUserId) {
-        mKeyguardSecurityCallback.dismiss(authenticated, targetUserId);
+    /**
+     * Potentially dismiss the current security screen, after validating that all device
+     * security has been unlocked. Otherwise show the next screen.
+     */
+    public void dismiss(boolean authenticated, int targetUserId,
+            SecurityMode expectedSecurityMode) {
+        mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
     }
 
     public void reset() {
@@ -456,12 +464,21 @@
      *     completion.
      * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
      *     secondary lock screen requirement, if any.
+     * @param expectedSecurityMode SecurityMode that is invoking this request. SecurityMode.Invalid
+     *      indicates that no check should be done
      * @return true if keyguard is done
      */
     public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
-            boolean bypassSecondaryLockScreen) {
+            boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
 
         if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+        if (expectedSecurityMode != SecurityMode.Invalid
+                && expectedSecurityMode != getCurrentSecurityMode()) {
+            Log.w(TAG, "Attempted to invoke showNextSecurityScreenOrFinish with securityMode "
+                    + expectedSecurityMode + ", but current mode is " + getCurrentSecurityMode());
+            return false;
+        }
+
         boolean finish = false;
         boolean strongAuth = false;
         int eventSubtype = -1;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 2f6fa14..ecd88e6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -170,7 +170,8 @@
                             mRemainingAttempts = -1;
                             mShowDefaultMessage = true;
                             getKeyguardSecurityCallback().dismiss(
-                                    true, KeyguardUpdateMonitor.getCurrentUser());
+                                    true, KeyguardUpdateMonitor.getCurrentUser(),
+                                    SecurityMode.SimPin);
                         } else {
                             mShowDefaultMessage = false;
                             if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index 47aa43b..203f9b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -69,7 +69,8 @@
             if (simState == TelephonyManager.SIM_STATE_READY) {
                 mRemainingAttempts = -1;
                 mShowDefaultMessage = true;
-                getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+                getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
+                        SecurityMode.SimPuk);
             } else {
                 resetState();
             }
@@ -278,7 +279,8 @@
                             mShowDefaultMessage = true;
 
                             getKeyguardSecurityCallback().dismiss(
-                                    true, KeyguardUpdateMonitor.getCurrentUser());
+                                    true, KeyguardUpdateMonitor.getCurrentUser(),
+                                    SecurityMode.SimPuk);
                         } else {
                             mShowDefaultMessage = false;
                             if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 489b4be..8b5e3c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -213,7 +213,8 @@
      * If no cancel signal has been received after this amount of time, set the biometric running
      * state to stopped to allow Keyguard to retry authentication.
      */
-    private static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
+    @VisibleForTesting
+    protected static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
 
     private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
             "com.android.settings", "com.android.settings.FallbackHome");
@@ -316,10 +317,15 @@
     private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
     private static final int HAL_ERROR_RETRY_MAX = 20;
 
-    private final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
+    @VisibleForTesting
+    protected final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
 
     private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived;
 
+    @VisibleForTesting
+    protected Handler getHandler() {
+        return mHandler;
+    }
     private final Handler mHandler;
 
     private SparseBooleanArray mBiometricEnabledForUser = new SparseBooleanArray();
@@ -707,6 +713,11 @@
 
     private void handleFingerprintAuthFailed() {
         Assert.isMainThread();
+        if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+            Log.d(TAG, "handleFingerprintAuthFailed()"
+                    + " triggered while waiting for cancellation, removing watchdog");
+            mHandler.removeCallbacks(mFpCancelNotReceived);
+        }
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -737,6 +748,11 @@
 
     private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
+        if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+            Log.d(TAG, "handleFingerprintAuthenticated()"
+                    + " triggered while waiting for cancellation, removing watchdog");
+            mHandler.removeCallbacks(mFpCancelNotReceived);
+        }
         try {
             final int userId;
             try {
@@ -2458,8 +2474,11 @@
         }
 
         final boolean statusBarShadeLocked = mStatusBarState == StatusBarState.SHADE_LOCKED;
-        final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
-                && !statusBarShadeLocked;
+        // mKeyguardIsVisible is true even when the bouncer is shown, we don't want to run face auth
+        // on bouncer if both fp and fingerprint are enrolled.
+        final boolean awakeKeyguardExcludingBouncerShowing = mKeyguardIsVisible
+                && mDeviceInteractive && !mGoingToSleep
+                && !statusBarShadeLocked && !mBouncerFullyShown;
         final int user = getCurrentUser();
         final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
         final boolean isLockDown =
@@ -2499,14 +2518,15 @@
         final boolean faceDisabledForUser = isFaceDisabled(user);
         final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
         final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
+        final boolean onlyFaceEnrolled = isOnlyFaceEnrolled();
 
         // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
         final boolean shouldListen =
-                (mBouncerFullyShown && !mGoingToSleep
+                ((mBouncerFullyShown && !mGoingToSleep && onlyFaceEnrolled)
                         || mAuthInterruptActive
                         || mOccludingAppRequestingFace
-                        || awakeKeyguard
+                        || awakeKeyguardExcludingBouncerShowing
                         || shouldListenForFaceAssistant
                         || mAuthController.isUdfpsFingerDown()
                         || mUdfpsBouncerShowing)
@@ -2530,10 +2550,11 @@
                     faceAuthenticated,
                     faceDisabledForUser,
                     mGoingToSleep,
-                    awakeKeyguard,
+                    awakeKeyguardExcludingBouncerShowing,
                     mKeyguardGoingAway,
                     shouldListenForFaceAssistant,
                     mOccludingAppRequestingFace,
+                    onlyFaceEnrolled,
                     mIsPrimaryUser,
                     strongAuthAllowsScanning,
                     mSecureCameraLaunched,
@@ -2543,6 +2564,11 @@
         return shouldListen;
     }
 
+    private boolean isOnlyFaceEnrolled() {
+        return isFaceAuthEnabledForUser(getCurrentUser())
+                && !isUnlockWithFingerprintPossible(getCurrentUser());
+    }
+
     private void maybeLogListenerModelData(KeyguardListenModel model) {
         mLogger.logKeyguardListenerModel(model);
 
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
deleted file mode 100644
index 0db5bef..0000000
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2015 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 com.android.systemui.analytics;
-
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.widget.Toast;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.FalsingPlugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
- * the data containing these events is saved to a file. This data is collected
- * to analyze how a human interaction looks like.
- *
- * A session starts when the screen is turned on.
- * A session ends when the screen is turned off or user unlocks the phone.
- */
-public class DataCollector implements SensorEventListener {
-    private static final String TAG = "DataCollector";
-    private static final String COLLECTOR_ENABLE = "data_collector_enable";
-    private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
-    private static final String ALLOW_REJECTED_TOUCH_REPORTS =
-            "data_collector_allow_rejected_touch_reports";
-    private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION =
-            "data_collector_disable_unlocking";
-
-    private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
-    public static final boolean DEBUG = false;
-
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private final Context mContext;
-
-    // Err on the side of caution, so logging is not started after a crash even tough the screen
-    // is off.
-    private SensorLoggerSession mCurrentSession = null;
-
-    private boolean mEnableCollector = false;
-    private boolean mCollectBadTouches = false;
-    private boolean mCornerSwiping = false;
-    private boolean mTrackingStarted = false;
-    private boolean mAllowReportRejectedTouch = false;
-    private boolean mDisableUnlocking = false;
-
-    private static DataCollector sInstance = null;
-
-    private FalsingPlugin mFalsingPlugin = null;
-
-    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
-        @Override
-        public void onChange(boolean selfChange) {
-            updateConfiguration();
-        }
-    };
-
-    private final PluginListener mPluginListener = new PluginListener<FalsingPlugin>() {
-        public void onPluginConnected(FalsingPlugin plugin, Context context) {
-            mFalsingPlugin = plugin;
-        }
-
-        public void onPluginDisconnected(FalsingPlugin plugin) {
-            mFalsingPlugin = null;
-        }
-    };
-
-    private DataCollector(Context context) {
-        mContext = context;
-
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(COLLECTOR_ENABLE), false,
-                mSettingsObserver,
-                UserHandle.USER_ALL);
-
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(COLLECT_BAD_TOUCHES), false,
-                mSettingsObserver,
-                UserHandle.USER_ALL);
-
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(ALLOW_REJECTED_TOUCH_REPORTS), false,
-                mSettingsObserver,
-                UserHandle.USER_ALL);
-
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false,
-                mSettingsObserver,
-                UserHandle.USER_ALL);
-
-        updateConfiguration();
-
-        Dependency.get(PluginManager.class).addPluginListener(mPluginListener, FalsingPlugin.class);
-    }
-
-    public static DataCollector getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new DataCollector(context);
-        }
-        return sInstance;
-    }
-
-    private void updateConfiguration() {
-        mEnableCollector = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                COLLECTOR_ENABLE, 0);
-        mCollectBadTouches = mEnableCollector && 0 != Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                COLLECT_BAD_TOUCHES, 0);
-        mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                ALLOW_REJECTED_TOUCH_REPORTS, 0);
-        mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
-                mContext.getContentResolver(),
-                DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0);
-    }
-
-    private boolean sessionEntrypoint() {
-        if (isEnabled() && mCurrentSession == null) {
-            onSessionStart();
-            return true;
-        }
-        return false;
-    }
-
-    private void sessionExitpoint(int result) {
-        if (mCurrentSession != null) {
-            onSessionEnd(result);
-        }
-    }
-
-    private void onSessionStart() {
-        mCornerSwiping = false;
-        mTrackingStarted = false;
-        mCurrentSession = new SensorLoggerSession(System.currentTimeMillis(), System.nanoTime());
-    }
-
-    private void onSessionEnd(int result) {
-        SensorLoggerSession session = mCurrentSession;
-        mCurrentSession = null;
-
-        if (mEnableCollector || mDisableUnlocking) {
-            session.end(System.currentTimeMillis(), result);
-            queueSession(session);
-        }
-    }
-
-    public Uri reportRejectedTouch() {
-        if (mCurrentSession == null) {
-            Toast.makeText(mContext, "Generating rejected touch report failed: session timed out.",
-                    Toast.LENGTH_LONG).show();
-            return null;
-        }
-        SensorLoggerSession currentSession = mCurrentSession;
-
-        currentSession.setType(Session.REJECTED_TOUCH_REPORT);
-        currentSession.end(System.currentTimeMillis(), Session.SUCCESS);
-        Session proto = currentSession.toProto();
-
-        byte[] b = Session.toByteArray(proto);
-        File dir = new File(mContext.getExternalCacheDir(), "rejected_touch_reports");
-        dir.mkdir();
-        File touch = new File(dir, "rejected_touch_report_" + System.currentTimeMillis());
-
-        try {
-            new FileOutputStream(touch).write(b);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-
-        return Uri.fromFile(touch);
-    }
-
-    private void queueSession(final SensorLoggerSession currentSession) {
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                byte[] b = Session.toByteArray(currentSession.toProto());
-
-                if (mFalsingPlugin != null) {
-                    mFalsingPlugin.dataCollected(currentSession.getResult() == Session.SUCCESS, b);
-                } else {
-                    String dir = mContext.getFilesDir().getAbsolutePath();
-                    if (currentSession.getResult() != Session.SUCCESS) {
-                        if (!mDisableUnlocking && !mCollectBadTouches) {
-                            return;
-                        }
-                        dir += "/bad_touches";
-                    } else if (!mDisableUnlocking) {
-                        dir += "/good_touches";
-                    }
-
-                    File file = new File(dir);
-                    file.mkdir();
-                    File touch = new File(file, "trace_" + System.currentTimeMillis());
-                    try {
-                        new FileOutputStream(touch).write(b);
-                    } catch (IOException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }
-        });
-    }
-
-    @Override
-    public synchronized void onSensorChanged(SensorEvent event) {
-        if (isEnabled() && mCurrentSession != null) {
-            mCurrentSession.addSensorEvent(event, System.nanoTime());
-        }
-    }
-
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-    }
-
-    /**
-     * @return true if data is being collected - either for data gathering or creating a
-     *         rejected touch report.
-     */
-    public boolean isEnabled() {
-        return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking;
-    }
-
-    public boolean isUnlockingDisabled() {
-        return mDisableUnlocking;
-    }
-    /**
-     * @return true if the full data set for data gathering should be collected - including
-     *         extensive sensor data, which is is not normally included with rejected touch reports.
-     */
-    public boolean isEnabledFull() {
-        return mEnableCollector;
-    }
-
-    public void onScreenTurningOn() {
-        if (sessionEntrypoint()) {
-            if (DEBUG) {
-                Log.d(TAG, "onScreenTurningOn");
-            }
-            addEvent(PhoneEvent.ON_SCREEN_ON);
-        }
-    }
-
-    public void onScreenOnFromTouch() {
-        if (sessionEntrypoint()) {
-            if (DEBUG) {
-                Log.d(TAG, "onScreenOnFromTouch");
-            }
-            addEvent(PhoneEvent.ON_SCREEN_ON_FROM_TOUCH);
-        }
-    }
-
-    public void onScreenOff() {
-        if (DEBUG) {
-            Log.d(TAG, "onScreenOff");
-        }
-        addEvent(PhoneEvent.ON_SCREEN_OFF);
-        sessionExitpoint(Session.FAILURE);
-    }
-
-    public void onSucccessfulUnlock() {
-        if (DEBUG) {
-            Log.d(TAG, "onSuccessfulUnlock");
-        }
-        addEvent(PhoneEvent.ON_SUCCESSFUL_UNLOCK);
-        sessionExitpoint(Session.SUCCESS);
-    }
-
-    public void onBouncerShown() {
-        if (DEBUG) {
-            Log.d(TAG, "onBouncerShown");
-        }
-        addEvent(PhoneEvent.ON_BOUNCER_SHOWN);
-    }
-
-    public void onBouncerHidden() {
-        if (DEBUG) {
-            Log.d(TAG, "onBouncerHidden");
-        }
-        addEvent(PhoneEvent.ON_BOUNCER_HIDDEN);
-    }
-
-    public void onQsDown() {
-        if (DEBUG) {
-            Log.d(TAG, "onQsDown");
-        }
-        addEvent(PhoneEvent.ON_QS_DOWN);
-    }
-
-    public void setQsExpanded(boolean expanded) {
-        if (DEBUG) {
-            Log.d(TAG, "setQsExpanded = " + expanded);
-        }
-        if (expanded) {
-            addEvent(PhoneEvent.SET_QS_EXPANDED_TRUE);
-        } else {
-            addEvent(PhoneEvent.SET_QS_EXPANDED_FALSE);
-        }
-    }
-
-    public void onTrackingStarted() {
-        if (DEBUG) {
-            Log.d(TAG, "onTrackingStarted");
-        }
-        mTrackingStarted = true;
-        addEvent(PhoneEvent.ON_TRACKING_STARTED);
-    }
-
-    public void onTrackingStopped() {
-        if (mTrackingStarted) {
-            if (DEBUG) {
-                Log.d(TAG, "onTrackingStopped");
-            }
-            mTrackingStarted = false;
-            addEvent(PhoneEvent.ON_TRACKING_STOPPED);
-        }
-    }
-
-    public void onNotificationActive() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationActive");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_ACTIVE);
-    }
-
-
-    public void onNotificationDoubleTap() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationDoubleTap");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_DOUBLE_TAP);
-    }
-
-    public void setNotificationExpanded() {
-        if (DEBUG) {
-            Log.d(TAG, "setNotificationExpanded");
-        }
-        addEvent(PhoneEvent.SET_NOTIFICATION_EXPANDED);
-    }
-
-    public void onNotificatonStartDraggingDown() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationStartDraggingDown");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_START_DRAGGING_DOWN);
-    }
-
-    public void onStartExpandingFromPulse() {
-        if (DEBUG) {
-            Log.d(TAG, "onStartExpandingFromPulse");
-        }
-        // TODO: maybe add event
-    }
-
-    public void onExpansionFromPulseStopped() {
-        if (DEBUG) {
-            Log.d(TAG, "onExpansionFromPulseStopped");
-        }
-        // TODO: maybe add event
-    }
-
-    public void onNotificatonStopDraggingDown() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationStopDraggingDown");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DRAGGING_DOWN);
-    }
-
-    public void onNotificationDismissed() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationDismissed");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_DISMISSED);
-    }
-
-    public void onNotificatonStartDismissing() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationStartDismissing");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_START_DISMISSING);
-    }
-
-    public void onNotificatonStopDismissing() {
-        if (DEBUG) {
-            Log.d(TAG, "onNotificationStopDismissing");
-        }
-        addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DISMISSING);
-    }
-
-    public void onCameraOn() {
-        if (DEBUG) {
-            Log.d(TAG, "onCameraOn");
-        }
-        addEvent(PhoneEvent.ON_CAMERA_ON);
-    }
-
-    public void onLeftAffordanceOn() {
-        if (DEBUG) {
-            Log.d(TAG, "onLeftAffordanceOn");
-        }
-        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_ON);
-    }
-
-    public void onAffordanceSwipingStarted(boolean rightCorner) {
-        if (DEBUG) {
-            Log.d(TAG, "onAffordanceSwipingStarted");
-        }
-        mCornerSwiping = true;
-        if (rightCorner) {
-            addEvent(PhoneEvent.ON_RIGHT_AFFORDANCE_SWIPING_STARTED);
-        } else {
-            addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_SWIPING_STARTED);
-        }
-    }
-
-    public void onAffordanceSwipingAborted() {
-        if (mCornerSwiping) {
-            if (DEBUG) {
-                Log.d(TAG, "onAffordanceSwipingAborted");
-            }
-            mCornerSwiping = false;
-            addEvent(PhoneEvent.ON_AFFORDANCE_SWIPING_ABORTED);
-        }
-    }
-
-    public void onUnlockHintStarted() {
-        if (DEBUG) {
-            Log.d(TAG, "onUnlockHintStarted");
-        }
-        addEvent(PhoneEvent.ON_UNLOCK_HINT_STARTED);
-    }
-
-    public void onCameraHintStarted() {
-        if (DEBUG) {
-            Log.d(TAG, "onCameraHintStarted");
-        }
-        addEvent(PhoneEvent.ON_CAMERA_HINT_STARTED);
-    }
-
-    public void onLeftAffordanceHintStarted() {
-        if (DEBUG) {
-            Log.d(TAG, "onLeftAffordanceHintStarted");
-        }
-        addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_HINT_STARTED);
-    }
-
-    public void onTouchEvent(MotionEvent event, int width, int height) {
-        if (mCurrentSession != null) {
-            if (DEBUG) {
-                Log.v(TAG, "onTouchEvent(ev.action="
-                        + MotionEvent.actionToString(event.getAction()) + ")");
-            }
-            mCurrentSession.addMotionEvent(event);
-            mCurrentSession.setTouchArea(width, height);
-        }
-    }
-
-    private void addEvent(int eventType) {
-        if (isEnabled() && mCurrentSession != null) {
-            mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
-        }
-    }
-
-    public boolean isReportingEnabled() {
-        return mAllowReportRejectedTouch;
-    }
-
-    public void onFalsingSessionStarted() {
-        sessionEntrypoint();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
deleted file mode 100644
index d294012..0000000
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2015 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 com.android.systemui.analytics;
-
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
-
-import android.os.Build;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-
-/**
- * Collects touch, sensor and phone events and converts the data to
- * TouchAnalyticsProto.Session.
- */
-public class SensorLoggerSession {
-    private static final String TAG = "SensorLoggerSession";
-
-    private final long mStartTimestampMillis;
-    private final long mStartSystemTimeNanos;
-
-    private long mEndTimestampMillis;
-    private int mType;
-
-    private ArrayList<TouchEvent> mMotionEvents = new ArrayList<>();
-    private ArrayList<SensorEvent> mSensorEvents = new ArrayList<>();
-    private ArrayList<PhoneEvent> mPhoneEvents = new ArrayList<>();
-    private int mTouchAreaHeight;
-    private int mTouchAreaWidth;
-    private int mResult = Session.UNKNOWN;
-
-    public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) {
-        mStartTimestampMillis = startTimestampMillis;
-        mStartSystemTimeNanos = startSystemTimeNanos;
-        mType = Session.REAL;
-    }
-
-    public void setType(int type) {
-        mType = type;
-    }
-
-    public void end(long endTimestampMillis, int result) {
-        mResult = result;
-        mEndTimestampMillis = endTimestampMillis;
-
-        if (DataCollector.DEBUG) {
-            Log.d(TAG, "Ending session result=" + result + " it lasted for " +
-                    (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s");
-        }
-    }
-
-    public void addMotionEvent(MotionEvent motionEvent) {
-        TouchEvent event = motionEventToProto(motionEvent);
-        mMotionEvents.add(event);
-    }
-
-    public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
-        SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos);
-        mSensorEvents.add(event);
-    }
-
-    public void addPhoneEvent(int eventType, long systemTimeNanos) {
-        PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos);
-        mPhoneEvents.add(event);
-    }
-
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder("Session{");
-        sb.append("mStartTimestampMillis=").append(mStartTimestampMillis);
-        sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
-        sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
-        sb.append(", mResult=").append(mResult);
-        sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
-        sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
-        sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
-        sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
-        sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]");
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public Session toProto() {
-        Session proto = new Session();
-        proto.startTimestampMillis = mStartTimestampMillis;
-        proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis;
-        proto.build = Build.FINGERPRINT;
-        proto.deviceId = Build.DEVICE;
-        proto.result = mResult;
-        proto.type = mType;
-        proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
-        proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
-        proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents);
-        proto.touchAreaWidth = mTouchAreaWidth;
-        proto.touchAreaHeight = mTouchAreaHeight;
-        return proto;
-    }
-
-    private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {
-        PhoneEvent proto = new PhoneEvent();
-        proto.type = eventType;
-        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
-        return proto;
-    }
-
-    private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {
-        SensorEvent proto = new SensorEvent();
-        proto.type = ev.sensor.getType();
-        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
-        proto.timestamp = ev.timestamp;
-        proto.values = ev.values.clone();
-        return proto;
-    }
-
-    private TouchEvent motionEventToProto(MotionEvent ev) {
-        int count = ev.getPointerCount();
-        TouchEvent proto = new TouchEvent();
-        proto.timeOffsetNanos = ev.getEventTimeNano() - mStartSystemTimeNanos;
-        proto.action = ev.getActionMasked();
-        proto.actionIndex = ev.getActionIndex();
-        proto.pointers = new TouchEvent.Pointer[count];
-        for (int i = 0; i < count; i++) {
-            TouchEvent.Pointer p = new TouchEvent.Pointer();
-            p.x = ev.getX(i);
-            p.y = ev.getY(i);
-            p.size = ev.getSize(i);
-            p.pressure = ev.getPressure(i);
-            p.id = ev.getPointerId(i);
-            proto.pointers[i] = p;
-        }
-        return proto;
-    }
-
-    public void setTouchArea(int width, int height) {
-        mTouchAreaWidth = width;
-        mTouchAreaHeight = height;
-    }
-
-    public int getResult() {
-        return mResult;
-    }
-
-    public long getStartTimestampMillis() {
-        return mStartTimestampMillis;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index e16ac08..c21e36a 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -97,6 +97,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 
@@ -132,7 +133,7 @@
     private static final int FONT_SEARCH_STEP_PX = 4;
 
     private final Context mContext;
-    private final UiEventLogger mUiEventLogger;
+    private final ClipboardLogger mClipboardLogger;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final DisplayManager mDisplayManager;
     private final DisplayMetrics mDisplayMetrics;
@@ -181,7 +182,7 @@
         final Context displayContext = context.createDisplayContext(getDefaultDisplay());
         mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
 
-        mUiEventLogger = uiEventLogger;
+        mClipboardLogger = new ClipboardLogger(uiEventLogger);
 
         mAccessibilityManager = AccessibilityManager.getInstance(mContext);
         mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class))
@@ -231,7 +232,7 @@
 
             @Override
             public void onSwipeDismissInitiated(Animator animator) {
-                mUiEventLogger.log(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
+                mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
                 mExitAnimator = animator;
             }
 
@@ -249,7 +250,7 @@
         });
 
         mDismissButton.setOnClickListener(view -> {
-            mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
+            mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
             animateOut();
         });
 
@@ -285,7 +286,8 @@
                                 int newDisplayId) {
                             if (mContext.getResources().getConfiguration().orientation
                                     != mOrientation) {
-                                mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+                                mClipboardLogger.logSessionComplete(
+                                        CLIPBOARD_OVERLAY_DISMISSED_OTHER);
                                 hideImmediate();
                             }
                         }
@@ -300,7 +302,7 @@
         });
 
         mTimeoutHandler.setOnTimeoutRunnable(() -> {
-            mUiEventLogger.log(CLIPBOARD_OVERLAY_TIMED_OUT);
+            mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TIMED_OUT);
             animateOut();
         });
 
@@ -308,7 +310,7 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
-                    mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+                    mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
                     animateOut();
                 }
             }
@@ -320,7 +322,7 @@
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (SCREENSHOT_ACTION.equals(intent.getAction())) {
-                    mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+                    mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
                     animateOut();
                 }
             }
@@ -390,7 +392,7 @@
                     mContext.getString(R.string.clipboard_send_nearby_description));
             mRemoteCopyChip.setVisibility(View.VISIBLE);
             mRemoteCopyChip.setOnClickListener((v) -> {
-                mUiEventLogger.log(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
+                mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
                 mContext.startActivity(remoteCopyIntent);
                 animateOut();
             });
@@ -450,7 +452,7 @@
         chip.setContentDescription(action.getTitle());
         chip.setIcon(action.getIcon(), false);
         chip.setPendingIntent(action.getActionIntent(), () -> {
-            mUiEventLogger.log(CLIPBOARD_OVERLAY_ACTION_TAPPED);
+            mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
             animateOut();
         });
         chip.setAlpha(1);
@@ -486,7 +488,7 @@
                         touchRegion.op(tmpRect, Region.Op.UNION);
                         if (!touchRegion.contains(
                                 (int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
-                            mUiEventLogger.log(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
+                            mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
                             animateOut();
                         }
                     }
@@ -497,7 +499,7 @@
     }
 
     private void editImage(Uri uri) {
-        mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
+        mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
         String editorPackage = mContext.getString(R.string.config_screenshotEditor);
         Intent editIntent = new Intent(Intent.ACTION_EDIT);
         if (!TextUtils.isEmpty(editorPackage)) {
@@ -512,7 +514,7 @@
     }
 
     private void editText() {
-        mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
+        mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
         Intent editIntent = new Intent(mContext, EditTextActivity.class);
         editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         mContext.startActivity(editIntent);
@@ -520,13 +522,15 @@
     }
 
     private void shareContent(ClipData clip) {
-        mUiEventLogger.log(CLIPBOARD_OVERLAY_SHARE_TAPPED);
+        mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SHARE_TAPPED);
         Intent shareIntent = new Intent(Intent.ACTION_SEND);
-        shareIntent.putExtra(Intent.EXTRA_TEXT, clip.getItemAt(0).getText().toString());
         shareIntent.setDataAndType(
                 clip.getItemAt(0).getUri(), clip.getDescription().getMimeType(0));
-        shareIntent.putExtra(Intent.EXTRA_STREAM, clip.getItemAt(0).getUri());
-        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        shareIntent.putExtra(Intent.EXTRA_TEXT, clip.getItemAt(0).getText().toString());
+        if (clip.getItemAt(0).getUri() != null) {
+            shareIntent.putExtra(Intent.EXTRA_STREAM, clip.getItemAt(0).getUri());
+            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        }
         Intent chooserIntent = Intent.createChooser(shareIntent, null)
                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
                 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -864,6 +868,7 @@
         mRemoteCopyChip.setVisibility(View.GONE);
         resetActionChips();
         mTimeoutHandler.cancelTimeout();
+        mClipboardLogger.reset();
     }
 
     @MainThread
@@ -969,4 +974,24 @@
             mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
         }
     }
+
+    static class ClipboardLogger {
+        private final UiEventLogger mUiEventLogger;
+        private boolean mGuarded = false;
+
+        ClipboardLogger(UiEventLogger uiEventLogger) {
+            mUiEventLogger = uiEventLogger;
+        }
+
+        void logSessionComplete(@NonNull UiEventLogger.UiEventEnum event) {
+            if (!mGuarded) {
+                mGuarded = true;
+                mUiEventLogger.log(event);
+            }
+        }
+
+        void reset() {
+            mGuarded = false;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index de7bf28..55c1806 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -215,16 +215,15 @@
         final boolean cameraBlocked = mSensorPrivacyController
                 .isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA);
         @DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL;
-        if (micBlocked && cameraBlocked) {
-            iconType = DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED;
-        } else if (!micBlocked && cameraBlocked) {
-            iconType = DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED;
-        } else if (micBlocked && !cameraBlocked) {
-            iconType = DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED;
-        }
-        if (iconType != Resources.ID_NULL) {
-            showIcon(iconType, true);
-        }
+        showIcon(
+                DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED,
+                !micBlocked && cameraBlocked);
+        showIcon(
+                DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED,
+                micBlocked && !cameraBlocked);
+        showIcon(
+                DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
+                micBlocked && cameraBlocked);
     }
 
     private String buildNotificationsContentDescription(int notificationCount) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
index 5457144..29bb2f4 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
@@ -163,7 +163,8 @@
             COMPLICATION_TYPE_WEATHER,
             COMPLICATION_TYPE_AIR_QUALITY,
             COMPLICATION_TYPE_CAST_INFO,
-            COMPLICATION_TYPE_HOME_CONTROLS
+            COMPLICATION_TYPE_HOME_CONTROLS,
+            COMPLICATION_TYPE_SMARTSPACE
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface ComplicationType {}
@@ -175,6 +176,7 @@
     int COMPLICATION_TYPE_AIR_QUALITY = 1 << 3;
     int COMPLICATION_TYPE_CAST_INFO = 1 << 4;
     int COMPLICATION_TYPE_HOME_CONTROLS = 1 << 5;
+    int COMPLICATION_TYPE_SMARTSPACE = 1 << 6;
 
     /**
      * The {@link Host} interface specifies a way a {@link Complication} to communicate with its
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
index dcab90f..d5db63d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
@@ -21,6 +21,7 @@
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_HOME_CONTROLS;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_NONE;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_SMARTSPACE;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
 
@@ -51,6 +52,8 @@
                 return COMPLICATION_TYPE_CAST_INFO;
             case DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS:
                 return COMPLICATION_TYPE_HOME_CONTROLS;
+            case DreamBackend.COMPLICATION_TYPE_SMARTSPACE:
+                return COMPLICATION_TYPE_SMARTSPACE;
             default:
                 return COMPLICATION_TYPE_NONE;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index ac6edba..567bdbc 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -52,6 +52,11 @@
         return mViewHolderProvider.get();
     }
 
+    @Override
+    public int getRequiredTypeAvailability() {
+        return COMPLICATION_TYPE_SMARTSPACE;
+    }
+
     /**
      * {@link CoreStartable} responsbile for registering {@link SmartSpaceComplication} with
      * SystemUI.
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
index 2cee2520..dfa3bcd 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
@@ -23,7 +23,10 @@
  */
 interface FeatureFlags : FlagListenable {
     /** Returns a boolean value for the given flag.  */
-    fun isEnabled(flag: BooleanFlag): Boolean
+    fun isEnabled(flag: UnreleasedFlag): Boolean
+
+    /** Returns a boolean value for the given flag.  */
+    fun isEnabled(flag: ReleasedFlag): Boolean
 
     /** Returns a boolean value for the given flag.  */
     fun isEnabled(flag: ResourceBooleanFlag): Boolean
@@ -39,4 +42,4 @@
 
     /** Returns a string value for the given flag.  */
     fun getString(flag: ResourceStringFlag): String
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index f804325..b4b8795 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -48,6 +48,8 @@
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.PrintWriter;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -84,6 +86,7 @@
     private final Resources mResources;
     private final SystemPropertiesHelper mSystemProperties;
     private final DeviceConfigProxy mDeviceConfigProxy;
+    private final ServerFlagReader mServerFlagReader;
     private final Map<Integer, Flag<?>> mAllFlags;
     private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
     private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
@@ -98,6 +101,7 @@
             @Main Resources resources,
             DumpManager dumpManager,
             DeviceConfigProxy deviceConfigProxy,
+            ServerFlagReader serverFlagReader,
             @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
             CommandRegistry commandRegistry,
             IStatusBarService barService) {
@@ -106,6 +110,7 @@
         mResources = resources;
         mSystemProperties = systemProperties;
         mDeviceConfigProxy = deviceConfigProxy;
+        mServerFlagReader = serverFlagReader;
         mAllFlags = allFlags;
         mBarService = barService;
 
@@ -121,7 +126,16 @@
     }
 
     @Override
-    public boolean isEnabled(@NonNull BooleanFlag flag) {
+    public boolean isEnabled(@NotNull UnreleasedFlag flag) {
+        return isEnabledInternal(flag);
+    }
+
+    @Override
+    public boolean isEnabled(@NotNull ReleasedFlag flag) {
+        return isEnabledInternal(flag);
+    }
+
+    private boolean isEnabledInternal(@NotNull BooleanFlag flag) {
         int id = flag.getId();
         if (!mBooleanFlagCache.containsKey(id)) {
             mBooleanFlagCache.put(id,
@@ -198,14 +212,17 @@
     /** Specific override for Boolean flags that checks against the teamfood list.*/
     private boolean readFlagValue(int id, boolean defaultValue) {
         Boolean result = readBooleanFlagOverride(id);
-        // Only check for teamfood if the default is false.
-        if (!defaultValue && result == null && id != Flags.TEAMFOOD.getId()) {
+        boolean hasServerOverride = mServerFlagReader.hasOverride(id);
+
+        // Only check for teamfood if the default is false
+        // and there is no server override.
+        if (!hasServerOverride && !defaultValue && result == null && id != Flags.TEAMFOOD.getId()) {
             if (mAllFlags.containsKey(id) && mAllFlags.get(id).getTeamfood()) {
                 return isEnabled(Flags.TEAMFOOD);
             }
         }
 
-        return result == null ? defaultValue : result;
+        return result == null ? mServerFlagReader.readServerOverride(id, defaultValue) : result;
     }
 
     private Boolean readBooleanFlagOverride(int id) {
@@ -410,36 +427,38 @@
          */
         @Nullable
         private ParcelableFlag<?> toParcelableFlag(Flag<?> f) {
-            if (f instanceof BooleanFlag) {
-                return new BooleanFlag(
-                        f.getId(),
-                        isEnabled((BooleanFlag) f),
-                        f.getTeamfood(),
-                        readBooleanFlagOverride(f.getId()) != null);
-            }
-            if (f instanceof ResourceBooleanFlag) {
-                return new BooleanFlag(
-                        f.getId(),
-                        isEnabled((ResourceBooleanFlag) f),
-                        f.getTeamfood(),
-                        readBooleanFlagOverride(f.getId()) != null);
-            }
-            if (f instanceof DeviceConfigBooleanFlag) {
-                return new BooleanFlag(
-                        f.getId(), isEnabled((DeviceConfigBooleanFlag) f), f.getTeamfood());
-            }
-            if (f instanceof SysPropBooleanFlag) {
+            boolean enabled;
+            boolean teamfood = f.getTeamfood();
+            boolean overridden;
+
+            if (f instanceof ReleasedFlag) {
+                enabled = isEnabled((ReleasedFlag) f);
+                overridden = readBooleanFlagOverride(f.getId()) != null;
+            } else if (f instanceof UnreleasedFlag) {
+                enabled = isEnabled((UnreleasedFlag) f);
+                overridden = readBooleanFlagOverride(f.getId()) != null;
+            } else if (f instanceof ResourceBooleanFlag) {
+                enabled = isEnabled((ResourceBooleanFlag) f);
+                overridden = readBooleanFlagOverride(f.getId()) != null;
+            } else if (f instanceof DeviceConfigBooleanFlag) {
+                enabled = isEnabled((DeviceConfigBooleanFlag) f);
+                overridden = false;
+            } else if (f instanceof SysPropBooleanFlag) {
                 // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
-                return new BooleanFlag(
-                        f.getId(),
-                        ((SysPropBooleanFlag) f).getDefault(),
-                        false,
-                        !mSystemProperties.get(((SysPropBooleanFlag) f).getName()).isEmpty());
+                enabled = isEnabled((SysPropBooleanFlag) f);
+                teamfood = false;
+                overridden = !mSystemProperties.get(((SysPropBooleanFlag) f).getName()).isEmpty();
+            } else {
+                // TODO: add support for other flag types.
+                Log.w(TAG, "Unsupported Flag Type. Please file a bug.");
+                return null;
             }
 
-            // TODO: add support for other flag types.
-            Log.w(TAG, "Unsupported Flag Type. Please file a bug.");
-            return null;
+            if (enabled) {
+                return new ReleasedFlag(f.getId(), teamfood, overridden);
+            } else {
+                return new UnreleasedFlag(f.getId(), teamfood, overridden);
+            }
         }
     };
 
@@ -540,8 +559,10 @@
         }
 
         private boolean isBooleanFlagEnabled(Flag<?> flag) {
-            if (flag instanceof BooleanFlag) {
-                return isEnabled((BooleanFlag) flag);
+            if (flag instanceof ReleasedFlag) {
+                return isEnabled((ReleasedFlag) flag);
+            } else if (flag instanceof UnreleasedFlag) {
+                return isEnabled((UnreleasedFlag) flag);
             } else if (flag instanceof ResourceBooleanFlag) {
                 return isEnabled((ResourceBooleanFlag) flag);
             } else if (flag instanceof SysPropFlag) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
index 1492a2b..049b17d 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
@@ -19,7 +19,6 @@
 import static java.util.Objects.requireNonNull;
 
 import android.content.res.Resources;
-import android.provider.DeviceConfig;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
@@ -31,6 +30,8 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.DeviceConfigProxy;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.io.PrintWriter;
 import java.util.Map;
 
@@ -47,18 +48,22 @@
     private final Resources mResources;
     private final SystemPropertiesHelper mSystemProperties;
     private final DeviceConfigProxy mDeviceConfigProxy;
+    private final ServerFlagReader mServerFlagReader;
     SparseBooleanArray mBooleanCache = new SparseBooleanArray();
     SparseArray<String> mStringCache = new SparseArray<>();
+    private boolean mInited;
 
     @Inject
     public FeatureFlagsRelease(
             @Main Resources resources,
             SystemPropertiesHelper systemProperties,
             DeviceConfigProxy deviceConfigProxy,
+            ServerFlagReader serverFlagReader,
             DumpManager dumpManager) {
         mResources = resources;
         mSystemProperties = systemProperties;
         mDeviceConfigProxy = deviceConfigProxy;
+        mServerFlagReader = serverFlagReader;
         dumpManager.registerDumpable("SysUIFlags", this);
     }
 
@@ -69,8 +74,13 @@
     public void removeListener(@NonNull Listener listener) {}
 
     @Override
-    public boolean isEnabled(BooleanFlag flag) {
-        return flag.getDefault();
+    public boolean isEnabled(@NotNull UnreleasedFlag flag) {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled(@NotNull ReleasedFlag flag) {
+        return mServerFlagReader.readServerOverride(flag.getId(), true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index c92cf54..e4fc88b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -32,7 +32,7 @@
  *
  * Flag Ids are integers.
  * Ids must be unique. This is enforced in a unit test.
- * Ids need not be sequential. Flags can "claim" a chunk of ids for flags in related featurs with
+ * Ids need not be sequential. Flags can "claim" a chunk of ids for flags in related features with
  * a comment. This is purely for organizational purposes.
  *
  * On public release builds, flags will always return their default value. There is no way to
@@ -41,30 +41,30 @@
  * See {@link FeatureFlagsDebug} for instructions on flipping the flags via adb.
  */
 public class Flags {
-    public static final BooleanFlag TEAMFOOD = new BooleanFlag(1, false);
+    public static final UnreleasedFlag TEAMFOOD = new UnreleasedFlag(1);
 
     /***************************************/
     // 100 - notification
-    public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
-            new BooleanFlag(103, false);
+    public static final UnreleasedFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
+            new UnreleasedFlag(103);
 
-    public static final BooleanFlag NSSL_DEBUG_LINES =
-            new BooleanFlag(105, false);
+    public static final UnreleasedFlag NSSL_DEBUG_LINES =
+            new UnreleasedFlag(105);
 
-    public static final BooleanFlag NSSL_DEBUG_REMOVE_ANIMATION =
-            new BooleanFlag(106, false);
+    public static final UnreleasedFlag NSSL_DEBUG_REMOVE_ANIMATION =
+            new UnreleasedFlag(106);
 
-    public static final BooleanFlag NEW_PIPELINE_CRASH_ON_CALL_TO_OLD_PIPELINE =
-            new BooleanFlag(107, false);
+    public static final UnreleasedFlag NEW_PIPELINE_CRASH_ON_CALL_TO_OLD_PIPELINE =
+            new UnreleasedFlag(107);
 
     public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS =
             new ResourceBooleanFlag(108, R.bool.config_notificationToContents);
 
-    public static final BooleanFlag REMOVE_UNRANKED_NOTIFICATIONS =
-            new BooleanFlag(109, false, true);
+    public static final UnreleasedFlag REMOVE_UNRANKED_NOTIFICATIONS =
+            new UnreleasedFlag(109, true);
 
-    public static final BooleanFlag FSI_REQUIRES_KEYGUARD =
-            new BooleanFlag(110, false, true);
+    public static final UnreleasedFlag FSI_REQUIRES_KEYGUARD =
+            new UnreleasedFlag(110, true);
 
     /***************************************/
     // 200 - keyguard/lockscreen
@@ -73,11 +73,11 @@
     // public static final BooleanFlag KEYGUARD_LAYOUT =
     //         new BooleanFlag(200, true);
 
-    public static final BooleanFlag LOCKSCREEN_ANIMATIONS =
-            new BooleanFlag(201, true);
+    public static final ReleasedFlag LOCKSCREEN_ANIMATIONS =
+            new ReleasedFlag(201);
 
-    public static final BooleanFlag NEW_UNLOCK_SWIPE_ANIMATION =
-            new BooleanFlag(202, true);
+    public static final ReleasedFlag NEW_UNLOCK_SWIPE_ANIMATION =
+            new ReleasedFlag(202);
 
     public static final ResourceBooleanFlag CHARGING_RIPPLE =
             new ResourceBooleanFlag(203, R.bool.flag_charging_ripple);
@@ -92,31 +92,28 @@
      * Whether the KeyguardBottomArea(View|Controller) should use the modern architecture or the old
      * one.
      */
-    public static final BooleanFlag MODERN_BOTTOM_AREA = new BooleanFlag(
-            206,
-            /* default= */ false,
-            /* teamfood= */ true);
+    public static final UnreleasedFlag MODERN_BOTTOM_AREA = new UnreleasedFlag(206, true);
 
-    public static final BooleanFlag LOCKSCREEN_CUSTOM_CLOCKS = new BooleanFlag(207, false);
-
+    public static final UnreleasedFlag LOCKSCREEN_CUSTOM_CLOCKS = new UnreleasedFlag(207);
+  
     /**
      * Flag to enable the usage of the new bouncer data source. This is a refactor of and
      * eventual replacement of KeyguardBouncer.java.
      */
-    public static final BooleanFlag MODERN_BOUNCER = new BooleanFlag(208, true);
+    public static final ReleasedFlag MODERN_BOUNCER = new ReleasedFlag(208);
 
     /***************************************/
     // 300 - power menu
-    public static final BooleanFlag POWER_MENU_LITE =
-            new BooleanFlag(300, true);
+    public static final ReleasedFlag POWER_MENU_LITE =
+            new ReleasedFlag(300);
 
     /***************************************/
     // 400 - smartspace
-    public static final BooleanFlag SMARTSPACE_DEDUPING =
-            new BooleanFlag(400, true);
+    public static final ReleasedFlag SMARTSPACE_DEDUPING =
+            new ReleasedFlag(400);
 
-    public static final BooleanFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
-            new BooleanFlag(401, true);
+    public static final ReleasedFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
+            new ReleasedFlag(401);
 
     public static final ResourceBooleanFlag SMARTSPACE =
             new ResourceBooleanFlag(402, R.bool.flag_smartspace);
@@ -127,11 +124,11 @@
      * @deprecated Not needed anymore
      */
     @Deprecated
-    public static final BooleanFlag NEW_USER_SWITCHER =
-            new BooleanFlag(500, true);
+    public static final ReleasedFlag NEW_USER_SWITCHER =
+            new ReleasedFlag(500);
 
-    public static final BooleanFlag COMBINED_QS_HEADERS =
-            new BooleanFlag(501, false, true);
+    public static final UnreleasedFlag COMBINED_QS_HEADERS =
+            new UnreleasedFlag(501, true);
 
     public static final ResourceBooleanFlag PEOPLE_TILE =
             new ResourceBooleanFlag(502, R.bool.flag_conversations);
@@ -143,9 +140,9 @@
      * @deprecated Not needed anymore
      */
     @Deprecated
-    public static final BooleanFlag NEW_FOOTER = new BooleanFlag(504, true);
+    public static final ReleasedFlag NEW_FOOTER = new ReleasedFlag(504);
 
-    public static final BooleanFlag NEW_HEADER = new BooleanFlag(505, false, true);
+    public static final UnreleasedFlag NEW_HEADER = new UnreleasedFlag(505, true);
     public static final ResourceBooleanFlag FULL_SCREEN_USER_SWITCHER =
             new ResourceBooleanFlag(506, R.bool.config_enableFullscreenUserSwitcher);
 
@@ -154,21 +151,21 @@
     public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
             new ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip);
 
-    public static final BooleanFlag STATUS_BAR_LETTERBOX_APPEARANCE =
-            new BooleanFlag(603, false);
+    public static final UnreleasedFlag STATUS_BAR_LETTERBOX_APPEARANCE =
+            new UnreleasedFlag(603, false);
 
-    public static final BooleanFlag NEW_STATUS_BAR_PIPELINE = new BooleanFlag(604, false);
+    public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE = new UnreleasedFlag(604, true);
 
     /***************************************/
     // 700 - dialer/calls
-    public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP =
-            new BooleanFlag(700, true);
+    public static final ReleasedFlag ONGOING_CALL_STATUS_BAR_CHIP =
+            new ReleasedFlag(700);
 
-    public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE =
-            new BooleanFlag(701, true);
+    public static final ReleasedFlag ONGOING_CALL_IN_IMMERSIVE =
+            new ReleasedFlag(701);
 
-    public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP =
-            new BooleanFlag(702, true);
+    public static final ReleasedFlag ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP =
+            new ReleasedFlag(702);
 
     /***************************************/
     // 800 - general visual/theme
@@ -177,20 +174,19 @@
 
     /***************************************/
     // 801 - region sampling
-    public static final BooleanFlag REGION_SAMPLING =
-            new BooleanFlag(801, false);
+    public static final UnreleasedFlag REGION_SAMPLING = new UnreleasedFlag(801);
 
     /***************************************/
     // 900 - media
-    public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true);
-    public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false);
-    public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true);
-    public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true);
+    public static final ReleasedFlag MEDIA_TAP_TO_TRANSFER = new ReleasedFlag(900);
+    public static final UnreleasedFlag MEDIA_SESSION_ACTIONS = new UnreleasedFlag(901);
+    public static final ReleasedFlag MEDIA_NEARBY_DEVICES = new ReleasedFlag(903);
+    public static final ReleasedFlag MEDIA_MUTE_AWAIT = new ReleasedFlag(904);
 
     // 1000 - dock
-    public static final BooleanFlag SIMULATE_DOCK_THROUGH_CHARGING =
-            new BooleanFlag(1000, true);
-    public static final BooleanFlag DOCK_SETUP_ENABLED = new BooleanFlag(1001, true);
+    public static final ReleasedFlag SIMULATE_DOCK_THROUGH_CHARGING =
+            new ReleasedFlag(1000);
+    public static final ReleasedFlag DOCK_SETUP_ENABLED = new ReleasedFlag(1001);
 
 
     // 1100 - windowing
@@ -214,6 +210,14 @@
     public static final SysPropBooleanFlag HIDE_NAVBAR_WINDOW =
             new SysPropBooleanFlag(1103, "persist.wm.debug.hide_navbar_window", false);
 
+    @Keep
+    public static final SysPropBooleanFlag WM_DESKTOP_WINDOWING =
+            new SysPropBooleanFlag(1104, "persist.wm.debug.desktop_mode", false);
+
+    @Keep
+    public static final SysPropBooleanFlag WM_CAPTION_ON_SHELL =
+            new SysPropBooleanFlag(1105, "persist.wm.debug.caption_on_shell", false);
+
     // 1200 - predictive back
     @Keep
     public static final SysPropBooleanFlag WM_ENABLE_PREDICTIVE_BACK = new SysPropBooleanFlag(
@@ -225,12 +229,12 @@
     public static final SysPropBooleanFlag WM_ALWAYS_ENFORCE_PREDICTIVE_BACK =
             new SysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", false);
 
-    public static final BooleanFlag NEW_BACK_AFFORDANCE =
-            new BooleanFlag(1203, false /* default */, false /* teamfood */);
+    public static final UnreleasedFlag NEW_BACK_AFFORDANCE =
+            new UnreleasedFlag(1203, false /* teamfood */);
 
     // 1300 - screenshots
 
-    public static final BooleanFlag SCREENSHOT_REQUEST_PROCESSOR = new BooleanFlag(1300, false);
+    public static final UnreleasedFlag SCREENSHOT_REQUEST_PROCESSOR = new UnreleasedFlag(1300);
 
     // Pay no attention to the reflection behind the curtain.
     // ========================== Curtain ==========================
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
new file mode 100644
index 0000000..fc5b9f4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 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 com.android.systemui.flags
+
+import com.android.systemui.util.DeviceConfigProxy
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+
+interface ServerFlagReader {
+    /** Returns true if there is a server-side setting stored. */
+    fun hasOverride(flagId: Int): Boolean
+
+    /** Returns any stored server-side setting or the default if not set. */
+    fun readServerOverride(flagId: Int, default: Boolean): Boolean
+}
+
+class ServerFlagReaderImpl @Inject constructor(
+    private val deviceConfig: DeviceConfigProxy
+) : ServerFlagReader {
+    override fun hasOverride(flagId: Int): Boolean =
+        deviceConfig.getProperty(
+            SYSUI_NAMESPACE,
+            getServerOverrideName(flagId)
+        ) != null
+
+    override fun readServerOverride(flagId: Int, default: Boolean): Boolean {
+        return deviceConfig.getBoolean(
+            SYSUI_NAMESPACE,
+            getServerOverrideName(flagId),
+            default
+        )
+    }
+
+    private fun getServerOverrideName(flagId: Int): String {
+        return "flag_override_$flagId"
+    }
+}
+
+private val SYSUI_NAMESPACE = "systemui"
+
+@Module
+interface ServerFlagReaderModule {
+    @Binds
+    fun bindsReader(impl: ServerFlagReaderImpl): ServerFlagReader
+}
+
+class ServerFlagReaderFake : ServerFlagReader {
+    private val flagMap: MutableMap<Int, Boolean> = mutableMapOf()
+
+    override fun hasOverride(flagId: Int): Boolean {
+        return flagMap.containsKey(flagId)
+    }
+
+    override fun readServerOverride(flagId: Int, default: Boolean): Boolean {
+        return flagMap.getOrDefault(flagId, default)
+    }
+
+    fun setFlagValue(flagId: Int, value: Boolean) {
+        flagMap.put(flagId, value)
+    }
+
+    fun eraseFlag(flagId: Int) {
+        flagMap.remove(flagId)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
index dc23684d..6124e10 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -22,17 +22,11 @@
 import com.android.systemui.util.collection.RingBuffer
 import com.google.errorprone.annotations.CompileTimeConstant
 import java.io.PrintWriter
-import java.text.SimpleDateFormat
-import java.util.Arrays.stream
-import java.util.Locale
 import java.util.concurrent.ArrayBlockingQueue
 import java.util.concurrent.BlockingQueue
 import kotlin.concurrent.thread
 import kotlin.math.max
 
-const val UNBOUNDED_STACK_TRACE = -1
-const val NESTED_TRACE_DEPTH = 10
-
 /**
  * A simple ring buffer of recyclable log messages
  *
@@ -74,18 +68,12 @@
  * @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
  * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
  * the maximum, it behaves like a ring buffer.
- * @param rootStackTraceDepth The number of stack trace elements to be logged for an exception when
- * the logBuffer is dumped. Defaulted to -1 [UNBOUNDED_STACK_TRACE] to print the entire stack trace.
- * @param nestedStackTraceDepth The number of stack trace elements to be logged for any nested
- * exceptions present in [Throwable.cause] or [Throwable.suppressedExceptions].
  */
 class LogBuffer @JvmOverloads constructor(
     private val name: String,
     private val maxSize: Int,
     private val logcatEchoTracker: LogcatEchoTracker,
     private val systrace: Boolean = true,
-    private val rootStackTraceDepth: Int = UNBOUNDED_STACK_TRACE,
-    private val nestedStackTraceDepth: Int = NESTED_TRACE_DEPTH,
 ) {
     private val buffer = RingBuffer(maxSize) { LogMessageImpl.create() }
 
@@ -236,7 +224,7 @@
         val iterationStart = if (tailLength <= 0) { 0 } else { max(0, buffer.size - tailLength) }
 
         for (i in iterationStart until buffer.size) {
-            dumpMessage(buffer[i], pw)
+            buffer[i].dump(pw)
         }
     }
 
@@ -264,76 +252,6 @@
         }
     }
 
-    private fun dumpMessage(
-        message: LogMessage,
-        pw: PrintWriter
-    ) {
-        val formattedTimestamp = DATE_FORMAT.format(message.timestamp)
-        val shortLevel = message.level.shortString
-        val messageToPrint = message.messagePrinter(message)
-        val tag = message.tag
-        printLikeLogcat(pw, formattedTimestamp, shortLevel, tag, messageToPrint)
-        message.exception?.let { ex ->
-            printException(
-                pw,
-                formattedTimestamp,
-                shortLevel,
-                ex,
-                tag,
-                stackTraceDepth = rootStackTraceDepth)
-        }
-    }
-
-    private fun printException(
-            pw: PrintWriter,
-            timestamp: String,
-            level: String,
-            exception: Throwable,
-            tag: String,
-            exceptionMessagePrefix: String = "",
-            stackTraceDepth: Int = UNBOUNDED_STACK_TRACE
-    ) {
-        val message = "$exceptionMessagePrefix$exception"
-        printLikeLogcat(pw, timestamp, level, tag, message)
-        var stacktraceStream = stream(exception.stackTrace)
-        if (stackTraceDepth != UNBOUNDED_STACK_TRACE) {
-            stacktraceStream = stacktraceStream.limit(stackTraceDepth.toLong())
-        }
-        stacktraceStream.forEach { line ->
-            printLikeLogcat(pw, timestamp, level, tag, "\tat $line")
-        }
-        exception.cause?.let { cause ->
-            printException(pw, timestamp, level, cause, tag, "Caused by: ", nestedStackTraceDepth)
-        }
-        exception.suppressedExceptions.forEach { suppressed ->
-            printException(
-                pw,
-                timestamp,
-                level,
-                suppressed,
-                tag,
-                "Suppressed: ",
-                nestedStackTraceDepth
-            )
-        }
-    }
-
-    private fun printLikeLogcat(
-        pw: PrintWriter,
-        formattedTimestamp: String,
-        shortLogLevel: String,
-        tag: String,
-        message: String
-    ) {
-        pw.print(formattedTimestamp)
-        pw.print(" ")
-        pw.print(shortLogLevel)
-        pw.print(" ")
-        pw.print(tag)
-        pw.print(": ")
-        pw.println(message)
-    }
-
     private fun echo(message: LogMessage, toLogcat: Boolean, toSystrace: Boolean) {
         if (toLogcat || toSystrace) {
             val strMessage = message.messagePrinter(message)
@@ -370,5 +288,4 @@
 typealias MessageInitializer = LogMessage.() -> Unit
 
 private const val TAG = "LogBuffer"
-private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
 private val FROZEN_MESSAGE = LogMessageImpl.create()
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
index 987aea8..dae2592 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
@@ -16,6 +16,10 @@
 
 package com.android.systemui.log
 
+import java.io.PrintWriter
+import java.text.SimpleDateFormat
+import java.util.Locale
+
 /**
  * Generic data class for storing messages logged to a [LogBuffer]
  *
@@ -50,6 +54,17 @@
     var bool2: Boolean
     var bool3: Boolean
     var bool4: Boolean
+
+    /**
+     * Function that dumps the [LogMessage] to the provided [writer].
+     */
+    fun dump(writer: PrintWriter) {
+        val formattedTimestamp = DATE_FORMAT.format(timestamp)
+        val shortLevel = level.shortString
+        val messageToPrint = messagePrinter(this)
+        printLikeLogcat(writer, formattedTimestamp, shortLevel, tag, messageToPrint)
+        exception?.printStackTrace(writer)
+    }
 }
 
 /**
@@ -61,3 +76,21 @@
  * of the printer for each call, thwarting our attempts at avoiding any sort of allocation.
  */
 typealias MessagePrinter = LogMessage.() -> String
+
+private fun printLikeLogcat(
+    pw: PrintWriter,
+    formattedTimestamp: String,
+    shortLogLevel: String,
+    tag: String,
+    message: String
+) {
+    pw.print(formattedTimestamp)
+    pw.print(" ")
+    pw.print(shortLogLevel)
+    pw.print(" ")
+    pw.print(tag)
+    pw.print(": ")
+    pw.println(message)
+}
+
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 2d7a809..3789cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -302,10 +302,6 @@
      */
     @VisibleForTesting
     void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
-        if (initializeTaskbarIfNecessary()) {
-            return;
-        }
-
         if (display == null) {
             return;
         }
@@ -315,7 +311,7 @@
 
         // We may show TaskBar on the default display for large screen device. Don't need to create
         // navigation bar for this case.
-        if (mIsTablet && isOnDefaultDisplay) {
+        if (isOnDefaultDisplay && initializeTaskbarIfNecessary()) {
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index b44b4de..6e927b0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -42,7 +42,6 @@
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.ViewController
-import com.android.wm.shell.back.BackAnimation
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlin.math.abs
@@ -119,7 +118,7 @@
         private val latencyTracker: LatencyTracker
     ) {
         /** Construct a [BackPanelController].  */
-        fun create(context: Context, backAnimation: BackAnimation?): BackPanelController {
+        fun create(context: Context): BackPanelController {
             val backPanelController = BackPanelController(
                 context,
                 windowManager,
@@ -418,6 +417,7 @@
                 stretchEntryBackIndicator(preThresholdStretchProgress(xTranslation))
             GestureState.INACTIVE ->
                 mView.resetStretch()
+            else -> {}
         }
 
         // set y translation
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index fc6dcd3..6ac3ead 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -574,10 +574,10 @@
     private void resetEdgeBackPlugin() {
         if (mIsNewBackAffordanceEnabled) {
             setEdgeBackPlugin(
-                    mBackPanelControllerFactory.create(mContext, mBackAnimation));
+                    mBackPanelControllerFactory.create(mContext));
         } else {
             setEdgeBackPlugin(
-                    new NavigationBarEdgePanel(mContext, mBackAnimation, mLatencyTracker));
+                    new NavigationBarEdgePanel(mContext, mLatencyTracker));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index eba9d3f..122852f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -43,7 +43,6 @@
 import android.view.WindowManager;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
-import android.window.BackEvent;
 
 import androidx.core.graphics.ColorUtils;
 import androidx.dynamicanimation.animation.DynamicAnimation;
@@ -59,7 +58,6 @@
 import com.android.systemui.plugins.NavigationEdgeBackPlugin;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
 import com.android.systemui.statusbar.VibratorHelper;
-import com.android.wm.shell.back.BackAnimation;
 
 import java.io.PrintWriter;
 import java.util.concurrent.Executor;
@@ -283,14 +281,11 @@
                 }
             };
     private BackCallback mBackCallback;
-    private BackAnimation mBackAnimation;
 
-    public NavigationBarEdgePanel(Context context,
-            BackAnimation backAnimation, LatencyTracker latencyTracker) {
+    public NavigationBarEdgePanel(Context context, LatencyTracker latencyTracker) {
         super(context);
 
         mWindowManager = context.getSystemService(WindowManager.class);
-        mBackAnimation = backAnimation;
         mVibratorHelper = Dependency.get(VibratorHelper.class);
 
         mDensity = context.getResources().getDisplayMetrics().density;
@@ -360,7 +355,6 @@
                 .getDimension(R.dimen.navigation_edge_action_drag_threshold);
         mSwipeProgressThreshold = context.getResources()
                 .getDimension(R.dimen.navigation_edge_action_progress_threshold);
-        initializeBackAnimation();
 
         setVisibility(GONE);
 
@@ -388,17 +382,6 @@
         mLatencyTracker = latencyTracker;
     }
 
-    public void setBackAnimation(BackAnimation backAnimation) {
-        mBackAnimation = backAnimation;
-        initializeBackAnimation();
-    }
-
-    private void initializeBackAnimation() {
-        if (mBackAnimation != null) {
-            mBackAnimation.setSwipeThresholds(mSwipeTriggerThreshold, mSwipeProgressThreshold);
-        }
-    }
-
     @Override
     public void onDestroy() {
         cancelFailsafe();
@@ -484,12 +467,6 @@
 
     @Override
     public void onMotionEvent(MotionEvent event) {
-        if (mBackAnimation != null) {
-            mBackAnimation.onBackMotion(
-                    event.getX(), event.getY(),
-                    event.getActionMasked(),
-                    mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT);
-        }
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
@@ -903,9 +880,6 @@
             // Whenever the trigger back state changes the existing translation animation should be
             // cancelled
             mTranslationAnimation.cancel();
-            if (mBackAnimation != null) {
-                mBackAnimation.setTriggerBack(triggerBack);
-            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
index 1b74ac3..b02a45a 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -18,7 +18,7 @@
 import com.android.systemui.plugins.BcSmartspaceDataPlugin
 import com.android.systemui.smartspace.SmartspacePrecondition
 import com.android.systemui.smartspace.SmartspaceTargetFilter
-import com.android.systemui.smartspace.filters.LockscreenTargetFilter
+import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
 import com.android.systemui.smartspace.preconditions.LockscreenPrecondition
 import dagger.Binds
 import dagger.BindsOptionalOf
@@ -61,7 +61,7 @@
     @Binds
     @Named(LOCKSCREEN_SMARTSPACE_TARGET_FILTER)
     abstract fun provideLockscreenSmartspaceTargetFilter(
-        filter: LockscreenTargetFilter?
+        filter: LockscreenAndDreamTargetFilter?
     ): SmartspaceTargetFilter?
 
     @Binds
@@ -69,4 +69,4 @@
     abstract fun bindSmartspacePrecondition(
         lockscreenPrecondition: LockscreenPrecondition?
     ): SmartspacePrecondition?
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt
rename to packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
index 6ad4901..aa4cf75 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
@@ -32,9 +32,9 @@
 import javax.inject.Inject
 
 /**
- * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen.
+ * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen and dreams.
  */
-class LockscreenTargetFilter @Inject constructor(
+class LockscreenAndDreamTargetFilter @Inject constructor(
     private val secureSettings: SecureSettings,
     private val userTracker: UserTracker,
     private val execution: Execution,
@@ -149,4 +149,4 @@
 
         listeners.forEach { it.onCriteriaChanged() }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 48e3450..0951e82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -19,7 +19,9 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.service.dreams.IDreamManager;
+import android.util.Log;
 
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.statusbar.IStatusBarService;
@@ -60,10 +62,12 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconList;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.statusbar.window.StatusBarWindowController;
 import com.android.systemui.tracing.ProtoTracer;
@@ -274,7 +278,30 @@
     @Provides
     @SysUISingleton
     static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
+            KeyguardStateController keyguardStateController,
+            Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManager,
             InteractionJankMonitor interactionJankMonitor) {
-        return new DialogLaunchAnimator(dreamManager, interactionJankMonitor);
+        DialogLaunchAnimator.Callback callback = new DialogLaunchAnimator.Callback() {
+            @Override
+            public boolean isDreaming() {
+                try {
+                    return dreamManager.isDreaming();
+                } catch (RemoteException e) {
+                    Log.e("DialogLaunchAnimator.Callback", "dreamManager.isDreaming failed", e);
+                    return false;
+                }
+            }
+
+            @Override
+            public boolean isUnlocked() {
+                return keyguardStateController.isUnlocked();
+            }
+
+            @Override
+            public boolean isShowingAlternateAuthOnUnlock() {
+                return statusBarKeyguardViewManager.get().shouldShowAltAuth();
+            }
+        };
+        return new DialogLaunchAnimator(callback, interactionJankMonitor);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index dac532b..e9771d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -471,7 +471,8 @@
         showBouncer(scrimmed);
     }
 
-    private boolean shouldShowAltAuth() {
+    /** Whether we should show the alternate authentication instead of the traditional bouncer. */
+    public boolean shouldShowAltAuth() {
         return mAlternateAuthInterceptor != null
                 && mKeyguardUpdateManager.isUnlockingWithBiometricAllowed(true);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index e22a896..4c76270 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -405,8 +405,8 @@
             }
 
             @Override
-            public void onEntryUpdated(NotificationEntry entry) {
-                BubblesManager.this.onEntryUpdated(entry);
+            public void onEntryUpdated(NotificationEntry entry, boolean fromSystem) {
+                BubblesManager.this.onEntryUpdated(entry, fromSystem);
             }
 
             @Override
@@ -444,9 +444,10 @@
         }
     }
 
-    void onEntryUpdated(NotificationEntry entry) {
+    void onEntryUpdated(NotificationEntry entry, boolean fromSystem) {
+        boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry);
         mBubbles.onEntryUpdated(notifToBubbleEntry(entry),
-                mNotificationInterruptStateProvider.shouldBubbleUp(entry));
+                shouldBubble, fromSystem);
     }
 
     void onEntryRemoved(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 12597e0..eba2795 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -118,6 +118,33 @@
     private final UserInfoController mUserInfoController;
     private final Executor mSysUiMainExecutor;
 
+    // Listeners and callbacks. Note that we prefer member variable over anonymous class here to
+    // avoid the situation that some implementations, like KeyguardUpdateMonitor, use WeakReference
+    // internally and anonymous class could be released after registration.
+    private final ConfigurationController.ConfigurationListener mConfigurationListener =
+            new ConfigurationController.ConfigurationListener() {
+                @Override
+                public void onConfigChanged(Configuration newConfig) {
+                    mShell.onConfigurationChanged(newConfig);
+                }
+            };
+    private final KeyguardStateController.Callback mKeyguardStateCallback =
+            new KeyguardStateController.Callback() {
+                @Override
+                public void onKeyguardShowingChanged() {
+                    mShell.onKeyguardVisibilityChanged(mKeyguardStateController.isShowing(),
+                            mKeyguardStateController.isOccluded(),
+                            mKeyguardStateController.isAnimatingBetweenKeyguardAndSurfaceBehind());
+                }
+            };
+    private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onKeyguardDismissAnimationFinished() {
+                    mShell.onKeyguardDismissAnimationFinished();
+                }
+            };
+
     private boolean mIsSysUiStateValid;
     private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
     private WakefulnessLifecycle.Observer mWakefulnessObserver;
@@ -159,28 +186,11 @@
     public void start() {
         // Notify with the initial configuration and subscribe for new config changes
         mShell.onConfigurationChanged(mContext.getResources().getConfiguration());
-        mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
-            @Override
-            public void onConfigChanged(Configuration newConfig) {
-                mShell.onConfigurationChanged(newConfig);
-            }
-        });
+        mConfigurationController.addCallback(mConfigurationListener);
 
         // Subscribe to keyguard changes
-        mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
-            @Override
-            public void onKeyguardShowingChanged() {
-                mShell.onKeyguardVisibilityChanged(mKeyguardStateController.isShowing(),
-                        mKeyguardStateController.isOccluded(),
-                        mKeyguardStateController.isAnimatingBetweenKeyguardAndSurfaceBehind());
-            }
-        });
-        mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
-            @Override
-            public void onKeyguardDismissAnimationFinished() {
-                mShell.onKeyguardDismissAnimationFinished();
-            }
-        });
+        mKeyguardStateController.addCallback(mKeyguardStateCallback);
+        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
 
         // TODO: Consider piping config change and other common calls to a shell component to
         //  delegate internally
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
index dffad6c..80385e6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
@@ -44,6 +44,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.After;
@@ -190,7 +191,7 @@
 
     private void verifyViewDismissed(SurfaceView v) throws Exception {
         verify(mKeyguardSecurityContainer).removeView(v);
-        verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true);
+        verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true, SecurityMode.Invalid);
         assertThat(mContext.isBound(mComponentName)).isFalse();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index ad6d146..bb455da 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -86,10 +86,11 @@
     becauseCannotSkipBouncer = false,
     biometricSettingEnabledForUser = false,
     bouncerFullyShown = false,
+    onlyFaceEnrolled = false,
     faceAuthenticated = false,
     faceDisabled = false,
     goingToSleep = false,
-    keyguardAwake = false,
+    keyguardAwakeExcludingBouncerShowing = false,
     keyguardGoingAway = false,
     listeningForFaceAssistant = false,
     occludingAppRequestingFaceAuth = false,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index dc87a6a..aecec9d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -21,7 +21,10 @@
 import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
 import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
@@ -76,6 +79,8 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper()
 public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
+    private static final int TARGET_USER_ID = 100;
+
     @Rule
     public MockitoRule mRule = MockitoJUnit.rule();
 
@@ -381,6 +386,44 @@
         verify(mSidefpsController, never()).show();
     }
 
+    @Test
+    public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
+        // GIVEN the current security method is SimPin
+        when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
+        when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID)).thenReturn(false);
+        mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.SimPin);
+
+        // WHEN a request is made from the SimPin screens to show the next security method
+        when(mKeyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.PIN);
+        mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+                /* authenticated= */true,
+                TARGET_USER_ID,
+                /* bypassSecondaryLockScreen= */true,
+                SecurityMode.SimPin);
+
+        // THEN the next security method of PIN is set, and the keyguard is not marked as done
+        verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
+        assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
+                .isEqualTo(SecurityMode.PIN);
+    }
+
+    @Test
+    public void showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged() {
+        //GIVEN current security mode has been set to PIN
+        mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.PIN);
+
+        //WHEN a request comes from SimPin to dismiss the security screens
+        boolean keyguardDone = mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+                /* authenticated= */true,
+                TARGET_USER_ID,
+                /* bypassSecondaryLockScreen= */true,
+                SecurityMode.SimPin);
+
+        //THEN no action has happened, which will not dismiss the security screens
+        assertThat(keyguardDone).isEqualTo(false);
+        verify(mKeyguardUpdateMonitor, never()).getUserHasTrust(anyInt());
+    }
+
     private void setupConditionsToEnableSideFpsHint() {
         attachView();
         setSideFpsHintEnabledFromResources(true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 035404c..c677371 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -22,6 +22,7 @@
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
+import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -109,6 +110,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
+import org.mockito.internal.util.reflection.FieldSetter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -196,11 +198,14 @@
             mBiometricEnabledCallbackArgCaptor;
     @Captor
     private ArgumentCaptor<FaceManager.AuthenticationCallback> mAuthenticationCallbackCaptor;
+    @Captor
+    private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor;
 
     // Direct executor
-    private Executor mBackgroundExecutor = Runnable::run;
-    private Executor mMainExecutor = Runnable::run;
+    private final Executor mBackgroundExecutor = Runnable::run;
+    private final Executor mMainExecutor = Runnable::run;
     private TestableLooper mTestableLooper;
+    private Handler mHandler;
     private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private TestableContext mSpiedContext;
     private MockitoSession mMockitoSession;
@@ -289,6 +294,13 @@
         mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
         biometricsEnabledForCurrentUser();
 
+        mHandler = spy(mKeyguardUpdateMonitor.getHandler());
+        try {
+            FieldSetter.setField(mKeyguardUpdateMonitor,
+                    KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
+        } catch (NoSuchFieldException e) {
+
+        }
         verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
         mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
         mKeyguardUpdateMonitor.registerCallback(mTestCallback);
@@ -328,7 +340,7 @@
 
         when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
         when(mTelephonyManager.getSimState(anyInt())).thenReturn(state);
-        when(mSubscriptionManager.getSubscriptionIds(anyInt())).thenReturn(new int[] { subId });
+        when(mSubscriptionManager.getSubscriptionIds(anyInt())).thenReturn(new int[]{subId});
 
         KeyguardUpdateMonitor testKUM = new TestableKeyguardUpdateMonitor(mSpiedContext);
 
@@ -503,7 +515,7 @@
         // Even SimState Loaded, still need ACTION_SERVICE_STATE turn on mTelephonyCapable
         assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
 
-        Intent intentServiceState =  new Intent(Intent.ACTION_SERVICE_STATE);
+        Intent intentServiceState = new Intent(Intent.ACTION_SERVICE_STATE);
         intentSimState.putExtra(Intent.EXTRA_SIM_STATE
                 , Intent.SIM_STATE_LOADED);
         mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
@@ -518,7 +530,7 @@
         mTestableLooper.processAllMessages();
 
         verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
-                        anyInt());
+                anyInt());
         verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
     }
 
@@ -568,11 +580,12 @@
 
     @Test
     public void testTriesToAuthenticate_whenBouncer() {
+        fingerprintIsNotEnrolled();
         setKeyguardBouncerVisibility(true);
 
         verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
-        verify(mFaceManager).isHardwareDetected();
-        verify(mFaceManager).hasEnrolledTemplates(anyInt());
+        verify(mFaceManager, atLeastOnce()).isHardwareDetected();
+        verify(mFaceManager, atLeastOnce()).hasEnrolledTemplates(anyInt());
     }
 
     @Test
@@ -788,7 +801,8 @@
     public void testBiometricsCleared_whenUserSwitches() throws Exception {
         final IRemoteCallback reply = new IRemoteCallback.Stub() {
             @Override
-            public void sendResult(Bundle data) {} // do nothing
+            public void sendResult(Bundle data) {
+            } // do nothing
         };
         final BiometricAuthenticated dummyAuthentication =
                 new BiometricAuthenticated(true /* authenticated */, true /* strong */);
@@ -806,7 +820,8 @@
     public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
         final IRemoteCallback reply = new IRemoteCallback.Stub() {
             @Override
-            public void sendResult(Bundle data) {} // do nothing
+            public void sendResult(Bundle data) {
+            } // do nothing
         };
         mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
         verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
@@ -1204,6 +1219,7 @@
             throws RemoteException {
         // Face auth should run when the following is true.
         bouncerFullyVisibleAndNotGoingToSleep();
+        fingerprintIsNotEnrolled();
         keyguardNotGoingAway();
         currentUserIsPrimary();
         strongAuthNotRequired();
@@ -1229,7 +1245,7 @@
         mKeyguardUpdateMonitor =
                 new TestableKeyguardUpdateMonitor(mSpiedContext);
 
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
         strongAuthNotRequired();
@@ -1246,7 +1262,7 @@
     @Test
     public void testShouldListenForFace_whenStrongAuthDoesNotAllowScanning_returnsFalse()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
         currentUserIsPrimary();
@@ -1267,9 +1283,10 @@
     @Test
     public void testShouldListenForFace_whenBiometricsDisabledForUser_returnsFalse()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
+        fingerprintIsNotEnrolled();
         currentUserIsPrimary();
         currentUserDoesNotHaveTrust();
         biometricsNotDisabledThroughDevicePolicyManager();
@@ -1289,9 +1306,10 @@
     @Test
     public void testShouldListenForFace_whenUserCurrentlySwitching_returnsFalse()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
+        fingerprintIsNotEnrolled();
         currentUserIsPrimary();
         currentUserDoesNotHaveTrust();
         biometricsNotDisabledThroughDevicePolicyManager();
@@ -1310,9 +1328,10 @@
     @Test
     public void testShouldListenForFace_whenSecureCameraLaunched_returnsFalse()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
+        fingerprintIsNotEnrolled();
         currentUserIsPrimary();
         currentUserDoesNotHaveTrust();
         biometricsNotDisabledThroughDevicePolicyManager();
@@ -1331,7 +1350,7 @@
     @Test
     public void testShouldListenForFace_whenOccludingAppRequestsFaceAuth_returnsTrue()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         bouncerFullyVisibleAndNotGoingToSleep();
         currentUserIsPrimary();
@@ -1354,7 +1373,7 @@
     @Test
     public void testShouldListenForFace_whenBouncerShowingAndDeviceIsAwake_returnsTrue()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         currentUserIsPrimary();
         currentUserDoesNotHaveTrust();
@@ -1366,6 +1385,7 @@
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
 
         bouncerFullyVisibleAndNotGoingToSleep();
+        fingerprintIsNotEnrolled();
         mTestableLooper.processAllMessages();
 
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
@@ -1374,7 +1394,7 @@
     @Test
     public void testShouldListenForFace_whenAuthInterruptIsActive_returnsTrue()
             throws RemoteException {
-        // Face auth should run when the following is true.
+        // Preconditions for face auth to run
         keyguardNotGoingAway();
         currentUserIsPrimary();
         currentUserDoesNotHaveTrust();
@@ -1391,6 +1411,150 @@
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
     }
 
+    @Test
+    public void testShouldListenForFace_whenKeyguardIsAwake_returnsTrue() throws RemoteException {
+        // Preconditions for face auth to run
+        keyguardNotGoingAway();
+        currentUserIsPrimary();
+        currentUserDoesNotHaveTrust();
+        biometricsNotDisabledThroughDevicePolicyManager();
+        biometricsEnabledForCurrentUser();
+        userNotCurrentlySwitching();
+        bouncerFullyVisible();
+
+        statusBarShadeIsLocked();
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+        deviceNotGoingToSleep();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+        deviceIsInteractive();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+        keyguardIsVisible();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+        statusBarShadeIsNotLocked();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+        bouncerNotFullyVisible();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+    }
+
+    @Test
+    public void testShouldListenForFace_whenUdfpsFingerDown_returnsTrue() throws RemoteException {
+        // Preconditions for face auth to run
+        keyguardNotGoingAway();
+        currentUserIsPrimary();
+        currentUserDoesNotHaveTrust();
+        biometricsNotDisabledThroughDevicePolicyManager();
+        biometricsEnabledForCurrentUser();
+        userNotCurrentlySwitching();
+        when(mAuthController.isUdfpsFingerDown()).thenReturn(false);
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+        when(mAuthController.isUdfpsFingerDown()).thenReturn(true);
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+    }
+
+    @Test
+    public void testShouldListenForFace_whenUdfpsBouncerIsShowing_returnsTrue()
+            throws RemoteException {
+        // Preconditions for face auth to run
+        keyguardNotGoingAway();
+        currentUserIsPrimary();
+        currentUserDoesNotHaveTrust();
+        biometricsNotDisabledThroughDevicePolicyManager();
+        biometricsEnabledForCurrentUser();
+        userNotCurrentlySwitching();
+        mTestableLooper.processAllMessages();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+        mKeyguardUpdateMonitor.setUdfpsBouncerShowing(true);
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+    }
+
+    @Test
+    public void testBouncerVisibility_whenBothFingerprintAndFaceIsEnrolled_stopsFaceAuth()
+            throws RemoteException {
+        // Both fingerprint and face are enrolled by default
+        // Preconditions for face auth to run
+        keyguardNotGoingAway();
+        currentUserIsPrimary();
+        currentUserDoesNotHaveTrust();
+        biometricsNotDisabledThroughDevicePolicyManager();
+        biometricsEnabledForCurrentUser();
+        userNotCurrentlySwitching();
+        deviceNotGoingToSleep();
+        deviceIsInteractive();
+        statusBarShadeIsNotLocked();
+        keyguardIsVisible();
+
+        mTestableLooper.processAllMessages();
+
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+
+        mKeyguardUpdateMonitor.requestFaceAuth(true);
+        verify(mFaceManager).authenticate(any(),
+                mCancellationSignalCaptor.capture(),
+                mAuthenticationCallbackCaptor.capture(),
+                any(),
+                anyInt(),
+                anyBoolean());
+        CancellationSignal cancelSignal = mCancellationSignalCaptor.getValue();
+
+        bouncerFullyVisible();
+        mTestableLooper.processAllMessages();
+
+        assertThat(cancelSignal.isCanceled()).isTrue();
+    }
+
+    @Test
+    public void testFingerprintCanAuth_whenCancellationNotReceivedAndAuthFailed() {
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+        mTestableLooper.processAllMessages();
+        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+        verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+                anyInt());
+
+        mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
+        // Make sure keyguard is going away after face auth attempt, and that it calls
+        // updateBiometricStateListeningState.
+        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
+        mTestableLooper.processAllMessages();
+
+        verify(mHandler).postDelayed(mKeyguardUpdateMonitor.mFpCancelNotReceived,
+                DEFAULT_CANCEL_SIGNAL_TIMEOUT);
+
+        mKeyguardUpdateMonitor.onFingerprintAuthenticated(0, true);
+        mTestableLooper.processAllMessages();
+
+        verify(mHandler, times(1)).removeCallbacks(mKeyguardUpdateMonitor.mFpCancelNotReceived);
+        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+        mTestableLooper.processAllMessages();
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true);
+    }
+
+    private void fingerprintIsNotEnrolled() {
+        when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false);
+    }
+
+    private void statusBarShadeIsNotLocked() {
+        mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+    }
+
+    private void statusBarShadeIsLocked() {
+        mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
+    }
+
+    private void keyguardIsVisible() {
+        mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+    }
+
     private void triggerAuthInterrupt() {
         mKeyguardUpdateMonitor.onAuthInterruptDetected(true);
     }
@@ -1468,10 +1632,26 @@
     }
 
     private void bouncerFullyVisibleAndNotGoingToSleep() {
-        mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true, true);
+        bouncerFullyVisible();
+        deviceNotGoingToSleep();
+    }
+
+    private void deviceNotGoingToSleep() {
         mKeyguardUpdateMonitor.dispatchFinishedGoingToSleep(/* value doesn't matter */1);
     }
 
+    private void deviceIsInteractive() {
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+    }
+
+    private void bouncerNotFullyVisible() {
+        setKeyguardBouncerVisibility(false);
+    }
+
+    private void bouncerFullyVisible() {
+        setKeyguardBouncerVisibility(true);
+    }
+
     private void setKeyguardBouncerVisibility(boolean isVisible) {
         mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible, isVisible);
         mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index c48cbb1..0f11241 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -26,6 +26,7 @@
 import junit.framework.Assert.assertNull
 import junit.framework.Assert.assertTrue
 import junit.framework.AssertionFailedError
+import kotlin.concurrent.thread
 import org.junit.After
 import org.junit.Before
 import org.junit.Rule
@@ -34,19 +35,18 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.Spy
 import org.mockito.junit.MockitoJUnit
-import kotlin.concurrent.thread
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper
 class ActivityLaunchAnimatorTest : SysuiTestCase() {
     private val launchContainer = LinearLayout(mContext)
-    private val testLaunchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
+    private val testLaunchAnimator = fakeLaunchAnimator()
     @Mock lateinit var callback: ActivityLaunchAnimator.Callback
     @Mock lateinit var listener: ActivityLaunchAnimator.Listener
     @Spy private val controller = TestLaunchAnimatorController(launchContainer)
@@ -77,12 +77,13 @@
         // We start in a new thread so that we can ensure that the callbacks are called in the main
         // thread.
         thread {
-            animator.startIntentWithAnimation(
+                animator.startIntentWithAnimation(
                     controller = controller,
                     animate = animate,
                     intentStarter = intentStarter
-            )
-        }.join()
+                )
+            }
+            .join()
     }
 
     @Test
@@ -197,14 +198,25 @@
         val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
         val taskInfo = ActivityManager.RunningTaskInfo()
         taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
-        taskInfo.topActivityInfo = ActivityInfo().apply {
-            applicationInfo = ApplicationInfo()
-        }
+        taskInfo.topActivityInfo = ActivityInfo().apply { applicationInfo = ApplicationInfo() }
 
         return RemoteAnimationTarget(
-                0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
-                Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
-                taskInfo, false
+            0,
+            RemoteAnimationTarget.MODE_OPENING,
+            SurfaceControl(),
+            false,
+            Rect(),
+            Rect(),
+            0,
+            Point(),
+            Rect(),
+            bounds,
+            WindowConfiguration(),
+            false,
+            SurfaceControl(),
+            Rect(),
+            taskInfo,
+            false
         )
     }
 }
@@ -213,17 +225,17 @@
  * A simple implementation of [ActivityLaunchAnimator.Controller] which throws if it is called
  * outside of the main thread.
  */
-private class TestLaunchAnimatorController(
-    override var launchContainer: ViewGroup
-) : ActivityLaunchAnimator.Controller {
-    override fun createAnimatorState() = LaunchAnimator.State(
+private class TestLaunchAnimatorController(override var launchContainer: ViewGroup) :
+    ActivityLaunchAnimator.Controller {
+    override fun createAnimatorState() =
+        LaunchAnimator.State(
             top = 100,
             bottom = 200,
             left = 300,
             right = 400,
             topCornerRadius = 10f,
             bottomCornerRadius = 20f
-    )
+        )
 
     private fun assertOnMainThread() {
         if (Looper.myLooper() != Looper.getMainLooper()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index 4218e09..7c1e384 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -5,7 +5,6 @@
 import android.graphics.Color
 import android.graphics.drawable.ColorDrawable
 import android.os.Bundle
-import android.service.dreams.IDreamManager
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.testing.ViewUtils
@@ -38,19 +37,16 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
 class DialogLaunchAnimatorTest : SysuiTestCase() {
-    private val launchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
     private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
     private val attachedViews = mutableSetOf<View>()
 
-    @Mock lateinit var dreamManager: IDreamManager
     @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
     @get:Rule val rule = MockitoJUnit.rule()
 
     @Before
     fun setUp() {
-        dialogLaunchAnimator = DialogLaunchAnimator(
-            dreamManager, interactionJankMonitor, launchAnimator, isForTesting = true
-        )
+        dialogLaunchAnimator =
+            fakeDialogLaunchAnimator(interactionJankMonitor = interactionJankMonitor)
     }
 
     @After
@@ -153,6 +149,22 @@
     }
 
     @Test
+    fun testActivityLaunchWhenLockedWithoutAlternateAuth() {
+        val dialogLaunchAnimator =
+            fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = false)
+        val dialog = createAndShowDialog(dialogLaunchAnimator)
+        assertNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
+    }
+
+    @Test
+    fun testActivityLaunchWhenLockedWithAlternateAuth() {
+        val dialogLaunchAnimator =
+            fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = true)
+        val dialog = createAndShowDialog(dialogLaunchAnimator)
+        assertNotNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
+    }
+
+    @Test
     fun testDialogAnimationIsChangedByAnimator() {
         // Important: the power menu animation relies on this behavior to know when to animate (see
         // http://ag/16774605).
@@ -193,11 +205,13 @@
         verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
     }
 
-    private fun createAndShowDialog(): TestDialog {
+    private fun createAndShowDialog(
+        animator: DialogLaunchAnimator = dialogLaunchAnimator,
+    ): TestDialog {
         val touchSurface = createTouchSurface()
         return runOnMainThreadAndWaitForIdleSync {
             val dialog = TestDialog(context)
-            dialogLaunchAnimator.showFromView(dialog, touchSurface)
+            animator.showFromView(dialog, touchSurface)
             dialog
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt
deleted file mode 100644
index dadf94e..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.android.systemui.animation
-
-/**
- * A [LaunchAnimator.Timings] to be used in tests.
- *
- * Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
- * when computing the progress of a sub-animation (the contents fade in/out).
- */
-val TEST_TIMINGS = LaunchAnimator.Timings(
-    totalDuration = 0L,
-    contentBeforeFadeOutDelay = 1L,
-    contentBeforeFadeOutDuration = 1L,
-    contentAfterFadeInDelay = 1L,
-    contentAfterFadeInDuration = 1L
-)
-
-/** A [LaunchAnimator.Interpolators] to be used in tests. */
-val TEST_INTERPOLATORS = LaunchAnimator.Interpolators(
-    positionInterpolator = Interpolators.STANDARD,
-    positionXInterpolator = Interpolators.STANDARD,
-    contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
-    contentAfterFadeInInterpolator = Interpolators.STANDARD
-)
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
index 2915f5a..e099c92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
@@ -20,6 +20,7 @@
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_CAST_INFO;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_HOME_CONTROLS;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_SMARTSPACE;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
 import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
 import static com.android.systemui.dreams.complication.ComplicationUtils.convertComplicationType;
@@ -60,6 +61,8 @@
                 .isEqualTo(COMPLICATION_TYPE_CAST_INFO);
         assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS))
                 .isEqualTo(COMPLICATION_TYPE_HOME_CONTROLS);
+        assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_SMARTSPACE))
+                .isEqualTo(COMPLICATION_TYPE_SMARTSPACE);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
index b2a4e33..7b1455c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
@@ -19,7 +19,6 @@
 import android.util.SparseArray
 import android.util.SparseBooleanArray
 import androidx.core.util.containsKey
-import java.lang.IllegalStateException
 
 class FakeFeatureFlags : FeatureFlags {
     private val booleanFlags = SparseBooleanArray()
@@ -57,7 +56,10 @@
         stringFlags.put(flag.id, value)
     }
 
-    override fun isEnabled(flag: BooleanFlag): Boolean = requireBooleanValue(flag.id)
+
+    override fun isEnabled(flag: UnreleasedFlag): Boolean = requireBooleanValue(flag.id)
+
+    override fun isEnabled(flag: ReleasedFlag): Boolean = requireBooleanValue(flag.id)
 
     override fun isEnabled(flag: ResourceBooleanFlag): Boolean = requireBooleanValue(flag.id)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
index 7d4b4f5..ff579a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
@@ -29,11 +29,12 @@
 @RunWith(AndroidTestingRunner::class)
 class FakeFeatureFlagsTest : SysuiTestCase() {
 
-    private val booleanFlag = BooleanFlag(-1000)
-    private val stringFlag = StringFlag(-1001)
-    private val resourceBooleanFlag = ResourceBooleanFlag(-1002, resourceId = -1)
-    private val resourceStringFlag = ResourceStringFlag(-1003, resourceId = -1)
-    private val sysPropBooleanFlag = SysPropBooleanFlag(-1004, name = "test")
+    private val unreleasedFlag = UnreleasedFlag(-1000)
+    private val releasedFlag = ReleasedFlag(-1001)
+    private val stringFlag = StringFlag(-1002)
+    private val resourceBooleanFlag = ResourceBooleanFlag(-1003, resourceId = -1)
+    private val resourceStringFlag = ResourceStringFlag(-1004, resourceId = -1)
+    private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, name = "test")
 
     /**
      * FakeFeatureFlags does not honor any default values. All flags which are accessed must be
@@ -49,56 +50,66 @@
             assertThat(ex.message).contains("TEAMFOOD")
         }
         try {
-            assertThat(flags.isEnabled(booleanFlag)).isFalse()
+            assertThat(flags.isEnabled(unreleasedFlag)).isFalse()
             fail("Expected an exception when accessing an unspecified flag.")
         } catch (ex: IllegalStateException) {
             assertThat(ex.message).contains("UNKNOWN(id=-1000)")
         }
         try {
-            assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
-            fail("Expected an exception when accessing an unspecified flag.")
-        } catch (ex: IllegalStateException) {
-            assertThat(ex.message).contains("UNKNOWN(id=-1002)")
-        }
-        try {
-            assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
-            fail("Expected an exception when accessing an unspecified flag.")
-        } catch (ex: IllegalStateException) {
-            assertThat(ex.message).contains("UNKNOWN(id=-1004)")
-        }
-        try {
-            assertThat(flags.getString(stringFlag)).isEmpty()
+            assertThat(flags.isEnabled(releasedFlag)).isFalse()
             fail("Expected an exception when accessing an unspecified flag.")
         } catch (ex: IllegalStateException) {
             assertThat(ex.message).contains("UNKNOWN(id=-1001)")
         }
         try {
-            assertThat(flags.getString(resourceStringFlag)).isEmpty()
+            assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
             fail("Expected an exception when accessing an unspecified flag.")
         } catch (ex: IllegalStateException) {
             assertThat(ex.message).contains("UNKNOWN(id=-1003)")
         }
+        try {
+            assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
+            fail("Expected an exception when accessing an unspecified flag.")
+        } catch (ex: IllegalStateException) {
+            assertThat(ex.message).contains("UNKNOWN(id=-1005)")
+        }
+        try {
+            assertThat(flags.getString(stringFlag)).isEmpty()
+            fail("Expected an exception when accessing an unspecified flag.")
+        } catch (ex: IllegalStateException) {
+            assertThat(ex.message).contains("UNKNOWN(id=-1002)")
+        }
+        try {
+            assertThat(flags.getString(resourceStringFlag)).isEmpty()
+            fail("Expected an exception when accessing an unspecified flag.")
+        } catch (ex: IllegalStateException) {
+            assertThat(ex.message).contains("UNKNOWN(id=-1004)")
+        }
     }
 
     @Test
     fun specifiedFlagsReturnCorrectValues() {
         val flags = FakeFeatureFlags()
-        flags.set(booleanFlag, false)
+        flags.set(unreleasedFlag, false)
+        flags.set(releasedFlag, false)
         flags.set(resourceBooleanFlag, false)
         flags.set(sysPropBooleanFlag, false)
         flags.set(resourceStringFlag, "")
 
-        assertThat(flags.isEnabled(booleanFlag)).isFalse()
+        assertThat(flags.isEnabled(unreleasedFlag)).isFalse()
+        assertThat(flags.isEnabled(releasedFlag)).isFalse()
         assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
         assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
         assertThat(flags.getString(resourceStringFlag)).isEmpty()
 
-        flags.set(booleanFlag, true)
+        flags.set(unreleasedFlag, true)
+        flags.set(releasedFlag, true)
         flags.set(resourceBooleanFlag, true)
         flags.set(sysPropBooleanFlag, true)
         flags.set(resourceStringFlag, "Android")
 
-        assertThat(flags.isEnabled(booleanFlag)).isTrue()
+        assertThat(flags.isEnabled(unreleasedFlag)).isTrue()
+        assertThat(flags.isEnabled(releasedFlag)).isTrue()
         assertThat(flags.isEnabled(resourceBooleanFlag)).isTrue()
         assertThat(flags.isEnabled(sysPropBooleanFlag)).isTrue()
         assertThat(flags.getString(resourceStringFlag)).isEqualTo("Android")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
index 51f3404..4511193 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -35,6 +35,10 @@
 import com.android.systemui.util.mockito.withArgCaptor
 import com.android.systemui.util.settings.SecureSettings
 import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.Serializable
+import java.io.StringWriter
+import java.util.function.Consumer
 import org.junit.Assert
 import org.junit.Before
 import org.junit.Test
@@ -48,12 +52,8 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.MockitoAnnotations
-import java.io.PrintWriter
-import java.io.Serializable
-import java.io.StringWriter
-import java.util.function.Consumer
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
 /**
  * NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -75,10 +75,11 @@
     private val flagMap = mutableMapOf<Int, Flag<*>>()
     private lateinit var broadcastReceiver: BroadcastReceiver
     private lateinit var clearCacheAction: Consumer<Int>
+    private val serverFlagReader = ServerFlagReaderFake()
 
     private val deviceConfig = DeviceConfigProxyFake()
-    private val teamfoodableFlagA = BooleanFlag(500, false, true)
-    private val teamfoodableFlagB = BooleanFlag(501, true, true)
+    private val teamfoodableFlagA = UnreleasedFlag(500, true)
+    private val teamfoodableFlagB = ReleasedFlag(501, true)
 
     @Before
     fun setup() {
@@ -93,6 +94,7 @@
             resources,
             dumpManager,
             deviceConfig,
+            serverFlagReader,
             flagMap,
             commandRegistry,
             barService
@@ -109,40 +111,41 @@
     }
 
     @Test
-    fun testReadBooleanFlag() {
+    fun readBooleanFlag() {
         // Remember that the TEAMFOOD flag is id#1 and has special behavior.
         whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
         whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
-        assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue()
-        assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue()
-        assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse()
-        assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(5, false))).isFalse()
+
+        assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(2))).isTrue()
+        assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(3))).isTrue()
+        assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(4))).isFalse()
+        assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(5))).isFalse()
     }
 
     @Test
-    fun testTeamFoodFlag_False() {
+    fun teamFoodFlag_False() {
         whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false)
         assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse()
         assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
-        testReadBooleanFlag()
+        readBooleanFlag()
     }
 
     @Test
-    fun testTeamFoodFlag_True() {
+    fun teamFoodFlag_True() {
         whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
         assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
         assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
-        testReadBooleanFlag()
+        readBooleanFlag()
     }
 
     @Test
-    fun testTeamFoodFlag_Overridden() {
+    fun teamFoodFlag_Overridden() {
         whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
                 .thenReturn(true)
         whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
@@ -153,11 +156,11 @@
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
-        testReadBooleanFlag()
+        readBooleanFlag()
     }
 
     @Test
-    fun testReadResourceBooleanFlag() {
+    fun readResourceBooleanFlag() {
         whenever(resources.getBoolean(1001)).thenReturn(false)
         whenever(resources.getBoolean(1002)).thenReturn(true)
         whenever(resources.getBoolean(1003)).thenReturn(false)
@@ -182,7 +185,7 @@
     }
 
     @Test
-    fun testReadSysPropBooleanFlag() {
+    fun readSysPropBooleanFlag() {
         whenever(systemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer {
             if ("b".equals(it.getArgument<String?>(0))) {
                 return@thenAnswer true
@@ -198,7 +201,7 @@
     }
 
     @Test
-    fun testReadDeviceConfigBooleanFlag() {
+    fun readDeviceConfigBooleanFlag() {
         val namespace = "test_namespace"
         deviceConfig.setProperty(namespace, "a", "true", false)
         deviceConfig.setProperty(namespace, "b", "false", false)
@@ -213,7 +216,7 @@
     }
 
     @Test
-    fun testReadStringFlag() {
+    fun readStringFlag() {
         whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
         whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
         assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz")
@@ -223,7 +226,7 @@
     }
 
     @Test
-    fun testReadResourceStringFlag() {
+    fun readResourceStringFlag() {
         whenever(resources.getString(1001)).thenReturn("")
         whenever(resources.getString(1002)).thenReturn("resource2")
         whenever(resources.getString(1003)).thenReturn("resource3")
@@ -253,8 +256,8 @@
     }
 
     @Test
-    fun testBroadcastReceiverIgnoresInvalidData() {
-        addFlag(BooleanFlag(1, false))
+    fun broadcastReceiver_IgnoresInvalidData() {
+        addFlag(UnreleasedFlag(1))
         addFlag(ResourceBooleanFlag(2, 1002))
         addFlag(StringFlag(3, "flag3"))
         addFlag(ResourceStringFlag(4, 1004))
@@ -272,10 +275,10 @@
     }
 
     @Test
-    fun testIntentWithIdButNoValueKeyClears() {
-        addFlag(BooleanFlag(1, false))
+    fun intentWithId_NoValueKeyClears() {
+        addFlag(UnreleasedFlag(1))
 
-        // trying to erase an id not in the map does noting
+        // trying to erase an id not in the map does nothing
         broadcastReceiver.onReceive(
             mockContext,
             Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 0)
@@ -291,9 +294,9 @@
     }
 
     @Test
-    fun testSetBooleanFlag() {
-        addFlag(BooleanFlag(1, false))
-        addFlag(BooleanFlag(2, false))
+    fun setBooleanFlag() {
+        addFlag(UnreleasedFlag(1))
+        addFlag(UnreleasedFlag(2))
         addFlag(ResourceBooleanFlag(3, 1003))
         addFlag(ResourceBooleanFlag(4, 1004))
 
@@ -311,7 +314,7 @@
     }
 
     @Test
-    fun testSetStringFlag() {
+    fun setStringFlag() {
         addFlag(StringFlag(1, "flag1"))
         addFlag(ResourceStringFlag(2, 1002))
 
@@ -323,7 +326,7 @@
     }
 
     @Test
-    fun testSetFlagClearsCache() {
+    fun setFlag_ClearsCache() {
         val flag1 = addFlag(StringFlag(1, "flag1"))
         whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original")
 
@@ -345,12 +348,30 @@
     }
 
     @Test
-    fun testRegisterCommand() {
+    fun serverSide_Overrides_MakesFalse() {
+        val flag = ReleasedFlag(100)
+
+        serverFlagReader.setFlagValue(flag.id, false)
+
+        assertThat(mFeatureFlagsDebug.isEnabled(flag)).isFalse()
+    }
+
+    @Test
+    fun serverSide_Overrides_MakesTrue() {
+        val flag = UnreleasedFlag(100)
+
+        serverFlagReader.setFlagValue(flag.id, true)
+
+        assertThat(mFeatureFlagsDebug.isEnabled(flag)).isTrue()
+    }
+
+    @Test
+    fun statusBarCommand_IsRegistered() {
         verify(commandRegistry).registerCommand(anyString(), any())
     }
 
     @Test
-    fun testNoOpCommand() {
+    fun noOpCommand() {
         val cmd = captureCommand()
 
         cmd.execute(pw, ArrayList())
@@ -360,37 +381,73 @@
     }
 
     @Test
-    fun testReadFlagCommand() {
-        addFlag(BooleanFlag(1, false))
+    fun readFlagCommand() {
+        addFlag(UnreleasedFlag(1))
         val cmd = captureCommand()
         cmd.execute(pw, listOf("1"))
         verify(flagManager).readFlagValue<Boolean>(eq(1), any())
     }
 
     @Test
-    fun testSetFlagCommand() {
-        addFlag(BooleanFlag(1, false))
+    fun setFlagCommand() {
+        addFlag(UnreleasedFlag(1))
         val cmd = captureCommand()
         cmd.execute(pw, listOf("1", "on"))
         verifyPutData(1, "{\"type\":\"boolean\",\"value\":true}")
     }
 
     @Test
-    fun testToggleFlagCommand() {
-        addFlag(BooleanFlag(1, true))
+    fun toggleFlagCommand() {
+        addFlag(ReleasedFlag(1))
         val cmd = captureCommand()
         cmd.execute(pw, listOf("1", "toggle"))
         verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}", 2)
     }
 
     @Test
-    fun testEraseFlagCommand() {
-        addFlag(BooleanFlag(1, true))
+    fun eraseFlagCommand() {
+        addFlag(ReleasedFlag(1))
         val cmd = captureCommand()
         cmd.execute(pw, listOf("1", "erase"))
         verify(secureSettings).putStringForUser(eq("key-1"), eq(""), anyInt())
     }
 
+    @Test
+    fun dumpFormat() {
+        val flag1 = ReleasedFlag(1)
+        val flag2 = ResourceBooleanFlag(2, 1002)
+        val flag3 = UnreleasedFlag(3)
+        val flag4 = StringFlag(4, "")
+        val flag5 = StringFlag(5, "flag5default")
+        val flag6 = ResourceStringFlag(6, 1006)
+        val flag7 = ResourceStringFlag(7, 1007)
+
+        whenever(resources.getBoolean(1002)).thenReturn(true)
+        whenever(resources.getString(1006)).thenReturn("resource1006")
+        whenever(resources.getString(1007)).thenReturn("resource1007")
+        whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
+            .thenReturn("override7")
+
+        // WHEN the flags have been accessed
+        assertThat(mFeatureFlagsDebug.isEnabled(flag1)).isTrue()
+        assertThat(mFeatureFlagsDebug.isEnabled(flag2)).isTrue()
+        assertThat(mFeatureFlagsDebug.isEnabled(flag3)).isFalse()
+        assertThat(mFeatureFlagsDebug.getString(flag4)).isEmpty()
+        assertThat(mFeatureFlagsDebug.getString(flag5)).isEqualTo("flag5default")
+        assertThat(mFeatureFlagsDebug.getString(flag6)).isEqualTo("resource1006")
+        assertThat(mFeatureFlagsDebug.getString(flag7)).isEqualTo("override7")
+
+        // THEN the dump contains the flags and the default values
+        val dump = dumpToString()
+        assertThat(dump).contains(" sysui_flag_1: true\n")
+        assertThat(dump).contains(" sysui_flag_2: true\n")
+        assertThat(dump).contains(" sysui_flag_3: false\n")
+        assertThat(dump).contains(" sysui_flag_4: [length=0] \"\"\n")
+        assertThat(dump).contains(" sysui_flag_5: [length=12] \"flag5default\"\n")
+        assertThat(dump).contains(" sysui_flag_6: [length=12] \"resource1006\"\n")
+        assertThat(dump).contains(" sysui_flag_7: [length=9] \"override7\"\n")
+    }
+
     private fun verifyPutData(id: Int, data: String, numReads: Int = 1) {
         inOrder(flagManager, secureSettings).apply {
             verify(flagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>())
@@ -421,42 +478,6 @@
         return captor.value.invoke()
     }
 
-    @Test
-    fun testDump() {
-        val flag1 = BooleanFlag(1, true)
-        val flag2 = ResourceBooleanFlag(2, 1002)
-        val flag3 = BooleanFlag(3, false)
-        val flag4 = StringFlag(4, "")
-        val flag5 = StringFlag(5, "flag5default")
-        val flag6 = ResourceStringFlag(6, 1006)
-        val flag7 = ResourceStringFlag(7, 1007)
-
-        whenever(resources.getBoolean(1002)).thenReturn(true)
-        whenever(resources.getString(1006)).thenReturn("resource1006")
-        whenever(resources.getString(1007)).thenReturn("resource1007")
-        whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
-            .thenReturn("override7")
-
-        // WHEN the flags have been accessed
-        assertThat(mFeatureFlagsDebug.isEnabled(flag1)).isTrue()
-        assertThat(mFeatureFlagsDebug.isEnabled(flag2)).isTrue()
-        assertThat(mFeatureFlagsDebug.isEnabled(flag3)).isFalse()
-        assertThat(mFeatureFlagsDebug.getString(flag4)).isEmpty()
-        assertThat(mFeatureFlagsDebug.getString(flag5)).isEqualTo("flag5default")
-        assertThat(mFeatureFlagsDebug.getString(flag6)).isEqualTo("resource1006")
-        assertThat(mFeatureFlagsDebug.getString(flag7)).isEqualTo("override7")
-
-        // THEN the dump contains the flags and the default values
-        val dump = dumpToString()
-        assertThat(dump).contains(" sysui_flag_1: true\n")
-        assertThat(dump).contains(" sysui_flag_2: true\n")
-        assertThat(dump).contains(" sysui_flag_3: false\n")
-        assertThat(dump).contains(" sysui_flag_4: [length=0] \"\"\n")
-        assertThat(dump).contains(" sysui_flag_5: [length=12] \"flag5default\"\n")
-        assertThat(dump).contains(" sysui_flag_6: [length=12] \"resource1006\"\n")
-        assertThat(dump).contains(" sysui_flag_7: [length=9] \"override7\"\n")
-    }
-
     private fun dumpToString(): String {
         val sw = StringWriter()
         val pw = PrintWriter(sw)
@@ -464,4 +485,4 @@
         pw.flush()
         return sw.toString()
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
index 6b683f4..e94b520 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
@@ -30,8 +30,8 @@
 import org.mockito.Mock
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
 /**
  * NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -44,13 +44,18 @@
     @Mock private lateinit var mResources: Resources
     @Mock private lateinit var mSystemProperties: SystemPropertiesHelper
     @Mock private lateinit var mDumpManager: DumpManager
+    private val serverFlagReader = ServerFlagReaderFake()
 
     private val deviceConfig = DeviceConfigProxyFake()
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, deviceConfig,
+        mFeatureFlagsRelease = FeatureFlagsRelease(
+            mResources,
+            mSystemProperties,
+            deviceConfig,
+            serverFlagReader,
             mDumpManager)
     }
 
@@ -113,4 +118,22 @@
         whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault)
         assertThat(mFeatureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault)
     }
-}
\ No newline at end of file
+
+    @Test
+    fun serverSide_OverridesReleased_MakesFalse() {
+        val flag = ReleasedFlag(100)
+
+        serverFlagReader.setFlagValue(flag.id, false)
+
+        assertThat(mFeatureFlagsRelease.isEnabled(flag)).isFalse()
+    }
+
+    @Test
+    fun serverSide_OverridesUnreleased_Ignored() {
+        val flag = UnreleasedFlag(100)
+
+        serverFlagReader.setFlagValue(flag.id, true)
+
+        assertThat(mFeatureFlagsRelease.isEnabled(flag)).isFalse()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
index a2eca81..17324a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
 import org.junit.Assert.assertThrows
 import org.junit.Before
 import org.junit.Test
@@ -33,9 +34,8 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
-import java.util.function.Consumer
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
 /**
  * NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -64,14 +64,14 @@
         verifyNoMoreInteractions(mFlagSettingsHelper)
 
         // adding the first listener registers the observer
-        mFlagManager.addListener(BooleanFlag(1, true), listener1)
+        mFlagManager.addListener(ReleasedFlag(1), listener1)
         val observer = withArgCaptor<ContentObserver> {
             verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
         }
         verifyNoMoreInteractions(mFlagSettingsHelper)
 
         // adding another listener does nothing
-        mFlagManager.addListener(BooleanFlag(2, true), listener2)
+        mFlagManager.addListener(ReleasedFlag(2), listener2)
         verifyNoMoreInteractions(mFlagSettingsHelper)
 
         // removing the original listener does nothing with second one still present
@@ -89,7 +89,7 @@
         val listener = mock<FlagListenable.Listener>()
         val clearCacheAction = mock<Consumer<Int>>()
         mFlagManager.clearCacheAction = clearCacheAction
-        mFlagManager.addListener(BooleanFlag(1, true), listener)
+        mFlagManager.addListener(ReleasedFlag(1), listener)
         val observer = withArgCaptor<ContentObserver> {
             verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
         }
@@ -101,8 +101,8 @@
     fun testObserverInvokesListeners() {
         val listener1 = mock<FlagListenable.Listener>()
         val listener10 = mock<FlagListenable.Listener>()
-        mFlagManager.addListener(BooleanFlag(1, true), listener1)
-        mFlagManager.addListener(BooleanFlag(10, true), listener10)
+        mFlagManager.addListener(ReleasedFlag(1), listener1)
+        mFlagManager.addListener(ReleasedFlag(10), listener10)
         val observer = withArgCaptor<ContentObserver> {
             verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
         }
@@ -127,8 +127,8 @@
     fun testOnlySpecificFlagListenerIsInvoked() {
         val listener1 = mock<FlagListenable.Listener>()
         val listener10 = mock<FlagListenable.Listener>()
-        mFlagManager.addListener(BooleanFlag(1, true), listener1)
-        mFlagManager.addListener(BooleanFlag(10, true), listener10)
+        mFlagManager.addListener(ReleasedFlag(1), listener1)
+        mFlagManager.addListener(ReleasedFlag(10), listener10)
 
         mFlagManager.dispatchListenersAndMaybeRestart(1, null)
         val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -148,8 +148,8 @@
     @Test
     fun testSameListenerCanBeUsedForMultipleFlags() {
         val listener = mock<FlagListenable.Listener>()
-        mFlagManager.addListener(BooleanFlag(1, true), listener)
-        mFlagManager.addListener(BooleanFlag(10, true), listener)
+        mFlagManager.addListener(ReleasedFlag(1), listener)
+        mFlagManager.addListener(ReleasedFlag(10), listener)
 
         mFlagManager.dispatchListenersAndMaybeRestart(1, null)
         val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -177,7 +177,7 @@
     @Test
     fun testListenerCanSuppressRestart() {
         val restartAction = mock<Consumer<Boolean>>()
-        mFlagManager.addListener(BooleanFlag(1, true)) { event ->
+        mFlagManager.addListener(ReleasedFlag(1)) { event ->
             event.requestNoRestart()
         }
         mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -188,7 +188,7 @@
     @Test
     fun testListenerOnlySuppressesRestartForOwnFlag() {
         val restartAction = mock<Consumer<Boolean>>()
-        mFlagManager.addListener(BooleanFlag(10, true)) { event ->
+        mFlagManager.addListener(ReleasedFlag(10)) { event ->
             event.requestNoRestart()
         }
         mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -199,10 +199,10 @@
     @Test
     fun testRestartWhenNotAllListenersRequestSuppress() {
         val restartAction = mock<Consumer<Boolean>>()
-        mFlagManager.addListener(BooleanFlag(10, true)) { event ->
+        mFlagManager.addListener(ReleasedFlag(10)) { event ->
             event.requestNoRestart()
         }
-        mFlagManager.addListener(BooleanFlag(10, true)) {
+        mFlagManager.addListener(ReleasedFlag(10)) {
             // do not request
         }
         mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -295,4 +295,4 @@
         assertThat(StringFlagSerializer.toSettingsData("foo"))
             .isEqualTo("{\"type\":\"string\",\"value\":\"foo\"}")
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
index 25c3028..250cc48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
@@ -107,11 +107,11 @@
     }
 
     private static class DuplicateFlagContainer {
-        public static final BooleanFlag A_FLAG = new BooleanFlag(0);
-        public static final BooleanFlag B_FLAG = new BooleanFlag(0);
+        public static final BooleanFlag A_FLAG = new UnreleasedFlag(0);
+        public static final BooleanFlag B_FLAG = new UnreleasedFlag(0);
         public static final StringFlag C_FLAG = new StringFlag(0);
 
-        public static final BooleanFlag D_FLAG = new BooleanFlag(1);
+        public static final BooleanFlag D_FLAG = new UnreleasedFlag(1);
 
         public static final DoubleFlag E_FLAG = new DoubleFlag(3);
         public static final DoubleFlag F_FLAG = new DoubleFlag(3);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
index 4abb973..56aff3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
@@ -24,16 +24,11 @@
     @Before
     fun setup() {
         outputWriter = StringWriter()
-        buffer = createBuffer(UNBOUNDED_STACK_TRACE, NESTED_TRACE_DEPTH)
+        buffer = createBuffer()
     }
 
-    private fun createBuffer(rootTraceDepth: Int, nestedTraceDepth: Int): LogBuffer {
-        return LogBuffer("TestBuffer",
-                1,
-                logcatEchoTracker,
-                false,
-                rootStackTraceDepth = rootTraceDepth,
-                nestedStackTraceDepth = nestedTraceDepth)
+    private fun createBuffer(): LogBuffer {
+        return LogBuffer("TestBuffer", 1, logcatEchoTracker, false)
     }
 
     @Test
@@ -56,95 +51,83 @@
     }
 
     @Test
-    fun dump_writesExceptionAndStacktraceLimitedToGivenDepth() {
-        buffer = createBuffer(rootTraceDepth = 2, nestedTraceDepth = -1)
-        // stack trace depth of 5
-        val exception = createTestException("Exception message", "TestClass", 5)
+    fun dump_writesExceptionAndStacktrace() {
+        buffer = createBuffer()
+        val exception = createTestException("Exception message", "TestClass")
         buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
 
         val dumpedString = dumpBuffer()
 
-        // logs are limited to depth 2
-        assertThat(dumpedString).contains("E Tag: Extra message")
-        assertThat(dumpedString).contains("E Tag: java.lang.RuntimeException: Exception message")
-        assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:1)")
-        assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:2)")
-        assertThat(dumpedString)
-                .doesNotContain("E Tag: \tat TestClass.TestMethod(TestClass.java:3)")
+        assertThat(dumpedString).contains("Extra message")
+        assertThat(dumpedString).contains("java.lang.RuntimeException: Exception message")
+        assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
+        assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
     }
 
     @Test
-    fun dump_writesCauseAndStacktraceLimitedToGivenDepth() {
-        buffer = createBuffer(rootTraceDepth = 0, nestedTraceDepth = 2)
+    fun dump_writesCauseAndStacktrace() {
+        buffer = createBuffer()
         val exception = createTestException("Exception message",
                 "TestClass",
-                1,
-                cause = createTestException("The real cause!", "TestClass", 5))
+                cause = createTestException("The real cause!", "TestClass"))
         buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
 
         val dumpedString = dumpBuffer()
 
-        // logs are limited to depth 2
         assertThat(dumpedString)
-                .contains("E Tag: Caused by: java.lang.RuntimeException: The real cause!")
-        assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:1)")
-        assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:2)")
-        assertThat(dumpedString)
-                .doesNotContain("E Tag: \tat TestClass.TestMethod(TestClass.java:3)")
+                .contains("Caused by: java.lang.RuntimeException: The real cause!")
+        assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
+        assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
     }
 
     @Test
-    fun dump_writesSuppressedExceptionAndStacktraceLimitedToGivenDepth() {
-        buffer = createBuffer(rootTraceDepth = 0, nestedTraceDepth = 2)
+    fun dump_writesSuppressedExceptionAndStacktrace() {
+        buffer = createBuffer()
         val exception = RuntimeException("Root exception message")
         exception.addSuppressed(
                 createTestException(
                         "First suppressed exception",
                         "FirstClass",
-                        5,
-                        createTestException("Cause of suppressed exp", "ThirdClass", 5)
+                        createTestException("Cause of suppressed exp", "ThirdClass")
                 ))
         exception.addSuppressed(
-                createTestException("Second suppressed exception", "SecondClass", 5))
+                createTestException("Second suppressed exception", "SecondClass"))
         buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
 
         val dumpedStr = dumpBuffer()
 
-        // logs are limited to depth 2
         // first suppressed exception
         assertThat(dumpedStr)
-                .contains("E Tag: Suppressed: " +
+                .contains("Suppressed: " +
                         "java.lang.RuntimeException: First suppressed exception")
-        assertThat(dumpedStr).contains("E Tag: \tat FirstClass.TestMethod(FirstClass.java:1)")
-        assertThat(dumpedStr).contains("E Tag: \tat FirstClass.TestMethod(FirstClass.java:2)")
-        assertThat(dumpedStr)
-                .doesNotContain("E Tag: \tat FirstClass.TestMethod(FirstClass.java:3)")
+        assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:1)")
+        assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:2)")
 
         assertThat(dumpedStr)
-                .contains("E Tag: Caused by: java.lang.RuntimeException: Cause of suppressed exp")
-        assertThat(dumpedStr).contains("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:1)")
-        assertThat(dumpedStr).contains("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:2)")
-        assertThat(dumpedStr)
-                .doesNotContain("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:3)")
+                .contains("Caused by: java.lang.RuntimeException: Cause of suppressed exp")
+        assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:1)")
+        assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:2)")
 
         // second suppressed exception
         assertThat(dumpedStr)
-                .contains("E Tag: Suppressed: " +
+                .contains("Suppressed: " +
                         "java.lang.RuntimeException: Second suppressed exception")
-        assertThat(dumpedStr).contains("E Tag: \tat SecondClass.TestMethod(SecondClass.java:1)")
-        assertThat(dumpedStr).contains("E Tag: \tat SecondClass.TestMethod(SecondClass.java:2)")
-        assertThat(dumpedStr)
-                .doesNotContain("E Tag: \tat SecondClass.TestMethod(SecondClass.java:3)")
+        assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:1)")
+        assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:2)")
     }
 
     private fun createTestException(
-        message: String,
-        errorClass: String,
-        stackTraceLength: Int,
-        cause: Throwable? = null
+            message: String,
+            errorClass: String,
+            cause: Throwable? = null,
     ): Exception {
         val exception = RuntimeException(message, cause)
-        exception.stackTrace = createStackTraceElements(errorClass, stackTraceLength)
+        exception.stackTrace = (1..5).map { lineNumber ->
+            StackTraceElement(errorClass,
+                    "TestMethod",
+                    "$errorClass.java",
+                    lineNumber)
+        }.toTypedArray()
         return exception
     }
 
@@ -152,16 +135,4 @@
         buffer.dump(PrintWriter(outputWriter), tailLength = 100)
         return outputWriter.toString()
     }
-
-    private fun createStackTraceElements(
-        errorClass: String,
-        stackTraceLength: Int
-    ): Array<StackTraceElement> {
-        return (1..stackTraceLength).map { lineNumber ->
-            StackTraceElement(errorClass,
-                    "TestMethod",
-                    "$errorClass.java",
-                    lineNumber)
-        }.toTypedArray()
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index 3d3ac83..83168cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -305,7 +305,7 @@
         // Then we save an update with the current time
         verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
         componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
-                ?.dropLastWhile { it.isEmpty() }.forEach {
+                .dropLastWhile { it.isEmpty() }.forEach {
             val result = it.split("/")
             assertThat(result.size).isEqualTo(3)
             assertThat(result[2].toLong()).isEqualTo(currentTime)
@@ -392,7 +392,7 @@
         // Then we store the new lastPlayed time
         verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
         componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
-                ?.dropLastWhile { it.isEmpty() }.forEach {
+                .dropLastWhile { it.isEmpty() }.forEach {
                     val result = it.split("/")
                     assertThat(result.size).isEqualTo(3)
                     assertThat(result[2].toLong()).isEqualTo(currentTime)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
similarity index 93%
rename from packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
index 185a838..6b34ca7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
@@ -27,13 +27,14 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.smartspace.filters.LockscreenTargetFilter
+import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
 import com.android.systemui.util.concurrency.Execution
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.withArgCaptor
 import com.android.systemui.util.settings.SecureSettings
 import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -41,18 +42,17 @@
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.atLeast
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
 
 @SmallTest
 @TestableLooper.RunWithLooper
 @RunWith(AndroidTestingRunner::class)
-class LockscreenTargetFilterTest : SysuiTestCase() {
+class LockscreenAndDreamTargetFilterTest : SysuiTestCase() {
     @Mock
     private lateinit var secureSettings: SecureSettings
 
@@ -99,7 +99,7 @@
         `when`(secureSettings
                 .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt()))
                 .thenReturn(0)
-        var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler,
+        var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler,
                 contentResolver, uiExecution)
 
         filter.addListener(listener)
@@ -132,7 +132,7 @@
         `when`(secureSettings
                 .getIntForUser(eq(setting) ?: setting, anyInt(), anyInt()))
                 .thenReturn(0)
-        var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler,
+        var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler,
                 contentResolver, uiExecution)
 
         filter.addListener(listener)
@@ -146,4 +146,4 @@
 
         verify(listener).onCriteriaChanged()
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index fee17c7..18acf3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -33,6 +33,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -621,7 +622,7 @@
         assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
 
         // Send update
-        mEntryListener.onEntryUpdated(mRow);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
 
         // Nothing should have changed
         // Notif is suppressed after expansion
@@ -789,7 +790,7 @@
     @Test
     public void testAddNotif_notBubble() {
         mEntryListener.onEntryAdded(mNonBubbleNotifRow.getEntry());
-        mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry());
+        mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry(), /* fromSystem= */ true);
 
         assertThat(mBubbleController.hasBubbles()).isFalse();
     }
@@ -827,7 +828,7 @@
         NotificationListenerService.Ranking ranking = new RankingBuilder(
                 mRow.getRanking()).setCanBubble(false).build();
         mRow.setRanking(ranking);
-        mEntryListener.onEntryUpdated(mRow);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
 
         assertFalse(mBubbleController.hasBubbles());
         verify(mDeleteIntent, never()).send();
@@ -1432,6 +1433,100 @@
         assertThat(mBubbleData.hasBubbleInStackWithKey(mBubbleEntry.getKey())).isFalse();
     }
 
+    /**
+     * Verifies that if a bubble is in the overflow and a non-interruptive notification update
+     * comes in for it, it stays in the overflow but the entry is updated.
+     */
+    @Test
+    public void testNonInterruptiveUpdate_doesntBubbleFromOverflow() {
+        mEntryListener.onEntryAdded(mRow);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+        assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+        // Dismiss the bubble so it's in the overflow
+        mBubbleController.removeBubble(
+                mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
+        assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey())).isTrue();
+
+        // Update the entry to not show in shade
+        setMetadataFlags(mRow,
+                Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, /* enableFlag= */ true);
+        mBubbleController.updateBubble(mBubbleEntry,
+                /* suppressFlyout= */ false, /* showInShade= */ true);
+
+        // Check that the update was applied - shouldn't be show in shade
+        assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
+        // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+        verify(mBubbleController, times(1)).inflateAndAdd(
+                any(Bubble.class), anyBoolean(), anyBoolean());
+    }
+
+    /**
+     * Verifies that if a bubble is active, and a non-interruptive notification update comes in for
+     * it, it doesn't trigger a new inflate and add for that bubble.
+     */
+    @Test
+    public void testNonInterruptiveUpdate_doesntTriggerInflate() {
+        mEntryListener.onEntryAdded(mRow);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+        assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+        // Update the entry to not show in shade
+        setMetadataFlags(mRow,
+                Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, /* enableFlag= */ true);
+        mBubbleController.updateBubble(mBubbleEntry,
+                /* suppressFlyout= */ false, /* showInShade= */ true);
+
+        // Check that the update was applied - shouldn't be show in shade
+        assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
+        // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+        verify(mBubbleController, times(1)).inflateAndAdd(
+                any(Bubble.class), anyBoolean(), anyBoolean());
+    }
+
+    /**
+     * Verifies that if a bubble is in the overflow and a non-interruptive notification update
+     * comes in for it with FLAG_BUBBLE that the flag is removed.
+     */
+    @Test
+    public void testNonInterruptiveUpdate_doesntOverrideOverflowFlagBubble() {
+        mEntryListener.onEntryAdded(mRow);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+        assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+        // Dismiss the bubble so it's in the overflow
+        mBubbleController.removeBubble(
+                mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
+        assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey())).isTrue();
+        // Once it's in the overflow it's not actively a bubble (doesn't have FLAG_BUBBLE)
+        Bubble b = mBubbleData.getOverflowBubbleWithKey(mBubbleEntry.getKey());
+        assertThat(b.isBubble()).isFalse();
+
+        // Send a non-notifying update that has FLAG_BUBBLE
+        mRow.getSbn().getNotification().flags = FLAG_BUBBLE;
+        assertThat(mRow.getSbn().getNotification().isBubbleNotification()).isTrue();
+        mBubbleController.updateBubble(mBubbleEntry,
+                /* suppressFlyout= */ false, /* showInShade= */ true);
+
+        // Verify that it still doesn't have FLAG_BUBBLE because it's in the overflow.
+        b = mBubbleData.getOverflowBubbleWithKey(mBubbleEntry.getKey());
+        assertThat(b.isBubble()).isFalse();
+    }
+
+    @Test
+    public void testNonSystemUpdatesIgnored() {
+        mEntryListener.onEntryAdded(mRow);
+        assertThat(mBubbleController.hasBubbles()).isTrue();
+
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+
+        // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+        verify(mBubbleController, times(1)).inflateAndAdd(
+                any(Bubble.class), anyBoolean(), anyBoolean());
+    }
+
     /** Creates a bubble using the userId and package. */
     private Bubble createBubble(int userId, String pkg) {
         final UserHandle userHandle = new UserHandle(userId);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index c52ea60f..c83189d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -15,6 +15,8 @@
  */
 package com.android.systemui;
 
+import static com.android.systemui.animation.FakeDialogLaunchAnimatorKt.fakeDialogLaunchAnimator;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -34,6 +36,7 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.broadcast.FakeBroadcastDispatcher;
 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
@@ -119,6 +122,7 @@
         // is missing (constructing the actual one would throw).
         // TODO(b/219008720): Remove this.
         mDependency.injectMockDependency(SystemUIDialogManager.class);
+        mDependency.injectTestDependency(DialogLaunchAnimator.class, fakeDialogLaunchAnimator());
     }
 
     @After
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt
new file mode 100644
index 0000000..990db77
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 com.android.systemui.animation
+
+import com.android.internal.jank.InteractionJankMonitor
+import org.mockito.Mockito.mock
+
+/** A [DialogLaunchAnimator] to be used in tests. */
+@JvmOverloads
+fun fakeDialogLaunchAnimator(
+    isUnlocked: Boolean = true,
+    isShowingAlternateAuthOnUnlock: Boolean = false,
+    interactionJankMonitor: InteractionJankMonitor = mock(InteractionJankMonitor::class.java),
+): DialogLaunchAnimator {
+    return DialogLaunchAnimator(
+        FakeCallback(
+            isUnlocked = isUnlocked,
+            isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
+        ),
+        interactionJankMonitor,
+        fakeLaunchAnimator(),
+        isForTesting = true,
+    )
+}
+
+private class FakeCallback(
+    private val isDreaming: Boolean = false,
+    private val isUnlocked: Boolean = true,
+    private val isShowingAlternateAuthOnUnlock: Boolean = false,
+) : DialogLaunchAnimator.Callback {
+    override fun isDreaming(): Boolean = isDreaming
+    override fun isUnlocked(): Boolean = isUnlocked
+    override fun isShowingAlternateAuthOnUnlock() = isShowingAlternateAuthOnUnlock
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
new file mode 100644
index 0000000..5b431e7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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 com.android.systemui.animation
+
+/** A [LaunchAnimator] to be used in tests. */
+fun fakeLaunchAnimator(): LaunchAnimator {
+    return LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
+}
+
+/**
+ * A [LaunchAnimator.Timings] to be used in tests.
+ *
+ * Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
+ * when computing the progress of a sub-animation (the contents fade in/out).
+ */
+private val TEST_TIMINGS =
+    LaunchAnimator.Timings(
+        totalDuration = 0L,
+        contentBeforeFadeOutDelay = 1L,
+        contentBeforeFadeOutDuration = 1L,
+        contentAfterFadeInDelay = 1L,
+        contentAfterFadeInDuration = 1L
+    )
+
+/** A [LaunchAnimator.Interpolators] to be used in tests. */
+private val TEST_INTERPOLATORS =
+    LaunchAnimator.Interpolators(
+        positionInterpolator = Interpolators.STANDARD,
+        positionXInterpolator = Interpolators.STANDARD,
+        contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
+        contentAfterFadeInInterpolator = Interpolators.STANDARD
+    )
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 9b11a68..a185b58 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1115,10 +1115,7 @@
             registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets));
 
             saveGroupStateAsync(userId);
-
-            if (DEBUG) {
-                Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
-            }
+            Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
         }
 
         return true;
@@ -4251,6 +4248,10 @@
         IAppWidgetHost callbacks;
         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
 
+        private static final boolean DEBUG = true;
+
+        private static final String TAG = "AppWidgetServiceHost";
+
         int tag = TAG_UNDEFINED; // for use while saving state (the index)
         // Sequence no for the last update successfully sent. This is updated whenever a
         // widget update is successfully sent to the host callbacks. As all new/undelivered updates
@@ -4321,6 +4322,11 @@
             final SparseArray<String> uids = new SparseArray<>();
             for (int i = widgets.size() - 1; i >= 0; i--) {
                 final Widget widget = widgets.get(i);
+                if (widget.provider == null) {
+                    if (DEBUG) {
+                        Slog.e(TAG, "Widget with no provider " + widget.toString());
+                    }
+                }
                 final ProviderId providerId = widget.provider.id;
                 uids.put(providerId.uid, providerId.componentName.getPackageName());
             }
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index c9a420e..32dc470 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -138,6 +138,12 @@
                 INetd netd, int userId) {
             return new Vpn(looper, context, nms, netd, userId, new VpnProfileStore());
         }
+
+        /** Create a LockDownVpnTracker. */
+        public LockdownVpnTracker createLockDownVpnTracker(Context context, Handler handler,
+                Vpn vpn, VpnProfile profile) {
+            return new LockdownVpnTracker(context, handler, vpn,  profile);
+        }
     }
 
     public VpnManagerService(Context context, Dependencies deps) {
@@ -502,8 +508,7 @@
                 logw("VPN for user " + user + " not ready yet. Skipping lockdown");
                 return false;
             }
-            setLockdownTracker(
-                    new LockdownVpnTracker(mContext, mHandler, vpn,  profile));
+            setLockdownTracker(mDeps.createLockDownVpnTracker(mContext, mHandler, vpn,  profile));
         }
 
         return true;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 002aa77..e7ea903 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3595,11 +3595,12 @@
 
     /**
      * Bump the given service record into executing state.
-     * @param oomAdjReason The caller requests it to perform the oomAdjUpdate if it's not null.
+     * @param oomAdjReason The caller requests it to perform the oomAdjUpdate not {@link
+     *         OomAdjuster#OOM_ADJ_REASON_NONE}.
      * @return {@code true} if it performed oomAdjUpdate.
      */
-    private boolean bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why,
-            @Nullable String oomAdjReason) {
+    private boolean bumpServiceExecutingLocked(
+            ServiceRecord r, boolean fg, String why, @OomAdjuster.OomAdjReason int oomAdjReason) {
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
                 + why + " of " + r + " in app " + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
@@ -3651,7 +3652,7 @@
             }
         }
         boolean oomAdjusted = false;
-        if (oomAdjReason != null && r.app != null
+        if (oomAdjReason != OomAdjuster.OOM_ADJ_REASON_NONE && r.app != null
                 && r.app.mState.getCurProcState() > ActivityManager.PROCESS_STATE_SERVICE) {
             // Force an immediate oomAdjUpdate, so the client app could be in the correct process
             // state before doing any service related transactions
@@ -4385,7 +4386,7 @@
 
         final ProcessServiceRecord psr = app.mServices;
         final boolean newService = psr.startService(r);
-        bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
+        bumpServiceExecutingLocked(r, execInFg, "create", OomAdjuster.OOM_ADJ_REASON_NONE);
         mAm.updateLruProcessLocked(app, false, null);
         updateServiceForegroundLocked(psr, /* oomAdj= */ false);
         // Force an immediate oomAdjUpdate, so the client app could be in the correct process state
@@ -4511,7 +4512,7 @@
             mAm.grantImplicitAccess(r.userId, si.intent, si.callingId,
                     UserHandle.getAppId(r.appInfo.uid)
             );
-            bumpServiceExecutingLocked(r, execInFg, "start", null /* oomAdjReason */);
+            bumpServiceExecutingLocked(r, execInFg, "start", OomAdjuster.OOM_ADJ_REASON_NONE);
             if (r.fgRequired && !r.fgWaiting) {
                 if (!r.isForeground) {
                     if (DEBUG_BACKGROUND_CHECK) {
@@ -4780,7 +4781,7 @@
                 updateServiceForegroundLocked(r.app.mServices, false);
                 try {
                     oomAdjusted |= bumpServiceExecutingLocked(r, false, "destroy",
-                            oomAdjusted ? null : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
+                            oomAdjusted ? 0 : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
                     mDestroyingServices.add(r);
                     r.destroying = true;
                     r.app.getThread().scheduleStopService(r);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5729a06..744ec9d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14692,6 +14692,17 @@
                 }
             }
 
+            if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID
+                    && callingUid != SYSTEM_UID) {
+                // If it's not debug build and not called from root/shell/system uid, reject it.
+                String msg = "Permission Denial: instrumentation test "
+                        + className + " from pid=" + callingPid + ", uid=" + callingUid
+                        + " not allowed because target package " + ii.targetPackage
+                        + " is not debuggable.";
+                reportStartInstrumentationFailureLocked(watcher, className, msg);
+                throw new SecurityException(msg);
+            }
+
             boolean disableHiddenApiChecks = ai.usesNonSdkApi()
                     || (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
             boolean disableTestApiChecks = disableHiddenApiChecks
@@ -15598,7 +15609,7 @@
      * {@link #enqueueOomAdjTargetLocked}.
      */
     @GuardedBy("this")
-    void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+    void updateOomAdjPendingTargetsLocked(@OomAdjuster.OomAdjReason int oomAdjReason) {
         mOomAdjuster.updateOomAdjPendingTargetsLocked(oomAdjReason);
     }
 
@@ -15617,7 +15628,7 @@
     }
 
     @GuardedBy("this")
-    final void updateOomAdjLocked(String oomAdjReason) {
+    final void updateOomAdjLocked(@OomAdjuster.OomAdjReason int oomAdjReason) {
         mOomAdjuster.updateOomAdjLocked(oomAdjReason);
     }
 
@@ -15629,7 +15640,8 @@
      * @return whether updateOomAdjLocked(app) was successful.
      */
     @GuardedBy("this")
-    final boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+    final boolean updateOomAdjLocked(
+            ProcessRecord app, @OomAdjuster.OomAdjReason int oomAdjReason) {
         return mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
     }
 
@@ -15862,14 +15874,16 @@
         mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
     }
 
-    private void trimApplications(boolean forceFullOomAdj, String oomAdjReason) {
+    private void trimApplications(
+            boolean forceFullOomAdj, @OomAdjuster.OomAdjReason int oomAdjReason) {
         synchronized (this) {
             trimApplicationsLocked(forceFullOomAdj, oomAdjReason);
         }
     }
 
     @GuardedBy("this")
-    private void trimApplicationsLocked(boolean forceFullOomAdj, String oomAdjReason) {
+    private void trimApplicationsLocked(
+            boolean forceFullOomAdj, @OomAdjuster.OomAdjReason int oomAdjReason) {
         // First remove any unused application processes whose package
         // has been removed.
         boolean didSomething = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 6609d4a..dbabe99 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -989,26 +989,40 @@
 
     @NeverCompile
     int runCompact(PrintWriter pw) {
-        String processName = getNextArgRequired();
-        String uid = getNextArgRequired();
-        String op = getNextArgRequired();
         ProcessRecord app;
-        synchronized (mInternal.mProcLock) {
-            app = mInternal.getProcessRecordLocked(processName, Integer.parseInt(uid));
-        }
-        pw.println("Process record found pid: " + app.mPid);
-        if (op.equals("full")) {
-            pw.println("Executing full compaction for " + app.mPid);
+        String op = getNextArgRequired();
+        boolean isFullCompact = op.equals("full");
+        boolean isSomeCompact = op.equals("some");
+        if (isFullCompact || isSomeCompact) {
+            String processName = getNextArgRequired();
+            String uid = getNextArgRequired();
             synchronized (mInternal.mProcLock) {
-                mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppFull(app, true);
+                app = mInternal.getProcessRecordLocked(processName, Integer.parseInt(uid));
             }
-            pw.println("Finished full compaction for " + app.mPid);
-        } else if (op.equals("some")) {
-            pw.println("Executing some compaction for " + app.mPid);
+            pw.println("Process record found pid: " + app.mPid);
+            if (isFullCompact) {
+                pw.println("Executing full compaction for " + app.mPid);
+                synchronized (mInternal.mProcLock) {
+                    mInternal.mOomAdjuster.mCachedAppOptimizer.compactApp(app,
+                            CachedAppOptimizer.CompactProfile.FULL,
+                            CachedAppOptimizer.CompactSource.APP, true);
+                }
+                pw.println("Finished full compaction for " + app.mPid);
+            } else if (isSomeCompact) {
+                pw.println("Executing some compaction for " + app.mPid);
+                synchronized (mInternal.mProcLock) {
+                    mInternal.mOomAdjuster.mCachedAppOptimizer.compactApp(app,
+                            CachedAppOptimizer.CompactProfile.SOME,
+                            CachedAppOptimizer.CompactSource.APP, true);
+                }
+                pw.println("Finished some compaction for " + app.mPid);
+            }
+        } else if (op.equals("system")) {
+            pw.println("Executing system compaction");
             synchronized (mInternal.mProcLock) {
-                mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppSome(app, true);
+                mInternal.mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
             }
-            pw.println("Finished some compaction for " + app.mPid);
+            pw.println("Finished system compaction");
         } else {
             getErrPrintWriter().println("Error: unknown compact command '" + op + "'");
             return -1;
@@ -3570,10 +3584,11 @@
             pw.println("      --allow-background-activity-starts: The receiver may start activities");
             pw.println("          even if in the background.");
             pw.println("      --async: Send without waiting for the completion of the receiver.");
-            pw.println("  compact <process_name> <Package UID> [some|full]");
+            pw.println("  compact [some|full|system] <process_name> <Package UID>");
             pw.println("      Force process compaction.");
             pw.println("      some: execute file compaction.");
             pw.println("      full: execute anon + file compaction.");
+            pw.println("      system: system compaction.");
             pw.println("  instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
             pw.println("          [--user <USER_ID> | current]");
             pw.println("          [--no-hidden-api-checks [--no-test-api-access]]");
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index c88d82c..45265ac 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -25,7 +25,6 @@
 import android.app.ApplicationExitInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
-import android.os.Debug;
 import android.os.Handler;
 import android.os.Message;
 import android.os.PowerManagerInternal;
@@ -40,20 +39,21 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.ProcLocksReader;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.ServiceThread;
-
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
@@ -99,7 +99,7 @@
     private static final int COMPACT_ACTION_NONE = 0;
     private static final int COMPACT_ACTION_FILE = 1;
     private static final int COMPACT_ACTION_ANON = 2;
-    private static final int COMPACT_ACTION_FULL = 3;
+    private static final int COMPACT_ACTION_ALL = 3;
 
     private static final String COMPACT_ACTION_STRING[] = {"", "file", "anon", "all"};
 
@@ -112,7 +112,7 @@
     // Defaults for phenotype flags.
     @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
     @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true;
-    @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL;
+    @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_ALL;
     @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
@@ -147,14 +147,33 @@
     @VisibleForTesting
     interface ProcessDependencies {
         long[] getRss(int pid);
-        void performCompaction(String action, int pid) throws IOException;
+        void performCompaction(CompactAction action, int pid) throws IOException;
+    }
+
+    // This indicates the compaction we want to perform
+    public enum CompactProfile {
+        SOME, // File compaction
+        FULL // File+anon compaction
+    }
+
+    // Low level actions that can be performed for compaction
+    // currently determined by the compaction profile
+    public enum CompactAction {
+        NONE, // No compaction
+        FILE, // File+anon compaction
+        ANON,
+        ALL
+    }
+
+    // This indicates the process OOM memory state that initiated the compaction request
+    public enum CompactSource { APP, PERSISTENT, BFGS }
+
+    public enum CancelCompactReason {
+        SCREEN_ON, // screen was turned on which cancels all compactions.
+        OOM_IMPROVEMENT // process moved out of cached state and into a more perceptible state.
     }
 
     // Handler constants.
-    static final int COMPACT_PROCESS_SOME = 1;
-    static final int COMPACT_PROCESS_FULL = 2;
-    static final int COMPACT_PROCESS_PERSISTENT = 3;
-    static final int COMPACT_PROCESS_BFGS = 4;
     static final int COMPACT_PROCESS_MSG = 1;
     static final int COMPACT_SYSTEM_MSG = 2;
     static final int SET_FROZEN_PROCESS_MSG = 3;
@@ -165,6 +184,12 @@
     // on swap resources as file.
     static final double COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD = 0.2;
 
+    // Size of history for the last 20 compactions for any process
+    static final int LAST_COMPACTED_ANY_PROCESS_STATS_HISTORY_SIZE = 20;
+
+    // Amount of processes supported to record for their last compaction.
+    static final int LAST_COMPACTION_FOR_PROCESS_STATS_SIZE = 256;
+
     static final int DO_FREEZE = 1;
     static final int REPORT_UNFREEZE = 2;
 
@@ -273,15 +298,16 @@
 
     private final SettingsContentObserver mSettingsObserver;
 
-    private final Object mPhenotypeFlagLock = new Object();
+    @VisibleForTesting
+    final Object mPhenotypeFlagLock = new Object();
 
     // Configured by phenotype. Updates from the server take effect immediately.
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting volatile String mCompactActionSome =
-            compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
+    @VisibleForTesting
+    volatile CompactAction mCompactActionSome = compactActionIntToAction(DEFAULT_COMPACT_ACTION_1);
     @GuardedBy("mPhenotypeFlagLock")
-    @VisibleForTesting volatile String mCompactActionFull =
-            compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
+    @VisibleForTesting
+    volatile CompactAction mCompactActionFull = compactActionIntToAction(DEFAULT_COMPACT_ACTION_2);
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
     @GuardedBy("mPhenotypeFlagLock")
@@ -333,31 +359,139 @@
     // facilitate removal of the oldest entry.
     @VisibleForTesting
     @GuardedBy("mProcLock")
-    LinkedHashMap<Integer, LastCompactionStats> mLastCompactionStats =
-            new LinkedHashMap<Integer, LastCompactionStats>() {
+    LinkedHashMap<Integer, SingleCompactionStats> mLastCompactionStats =
+            new LinkedHashMap<Integer, SingleCompactionStats>() {
                 @Override
                 protected boolean removeEldestEntry(Map.Entry eldest) {
-                    return size() > 100;
+                    return size() > LAST_COMPACTION_FOR_PROCESS_STATS_SIZE;
                 }
-    };
+            };
 
-    // Compaction Stats
-    private int mSomeCompactionCount;
-    private int mFullCompactionCount;
-    private int mPersistentCompactionCount;
-    private int mBfgsCompactionCount;
-    private long mSomeCompactRequest;
-    private long mFullCompactRequest;
-    private long mPersistentCompactRequest;
-    private long mBfgsCompactRequest;
-    private long mProcCompactionsRequested;
-    private long mProcCompactionsPerformed;
-    private long mProcCompactionsNoPidThrottled;
-    private long mProcCompactionsOomAdjThrottled;
-    private long mProcCompactionsTimeThrottled;
-    private long mProcCompactionsRSSThrottled;
-    private long mProcCompactionsMiscThrottled;
+    LinkedList<SingleCompactionStats> mCompactionStatsHistory =
+            new LinkedList<SingleCompactionStats>() {
+                @Override
+                public boolean add(SingleCompactionStats e) {
+                    if (size() >= LAST_COMPACTED_ANY_PROCESS_STATS_HISTORY_SIZE) {
+                        this.remove();
+                    }
+                    return super.add(e);
+                }
+            };
+
+    class AggregatedCompactionStats {
+        // Throttling stats
+        public long mFullCompactRequested;
+        public long mSomeCompactRequested;
+        public long mFullCompactPerformed;
+        public long mSomeCompactPerformed;
+        public long mProcCompactionsNoPidThrottled;
+        public long mProcCompactionsOomAdjThrottled;
+        public long mProcCompactionsTimeThrottled;
+        public long mProcCompactionsRSSThrottled;
+        public long mProcCompactionsMiscThrottled;
+
+        // Memory stats
+        public long mTotalDeltaAnonRssKBs;
+        public long mTotalZramConsumedKBs;
+        public long mTotalAnonMemFreedKBs;
+        public long mSumOrigAnonRss;
+        public double mMaxCompactEfficiency;
+
+        // Cpu time
+        public long mTotalCpuTimeMillis;
+
+        public long getThrottledSome() { return mSomeCompactRequested - mSomeCompactPerformed; }
+
+        public long getThrottledFull() { return mFullCompactRequested - mFullCompactPerformed; }
+
+        public void addMemStats(long anonRssSaved, long zramConsumed, long memFreed,
+                long origAnonRss, long totalCpuTimeMillis) {
+            final double compactEfficiency = memFreed / (double) origAnonRss;
+            if (compactEfficiency > mMaxCompactEfficiency) {
+                mMaxCompactEfficiency = compactEfficiency;
+            }
+            mTotalDeltaAnonRssKBs += anonRssSaved;
+            mTotalZramConsumedKBs += zramConsumed;
+            mTotalAnonMemFreedKBs += memFreed;
+            mSumOrigAnonRss += origAnonRss;
+            mTotalCpuTimeMillis += totalCpuTimeMillis;
+        }
+
+        public void dump(PrintWriter pw) {
+            long totalCompactRequested = mSomeCompactRequested + mFullCompactRequested;
+            long totalCompactPerformed = mSomeCompactPerformed + mFullCompactPerformed;
+            pw.println("    Performed / Requested:");
+            pw.println("      Some: (" + mSomeCompactPerformed + "/" + mSomeCompactRequested + ")");
+            pw.println("      Full: (" + mFullCompactPerformed + "/" + mFullCompactRequested + ")");
+
+            long throttledSome = getThrottledSome();
+            long throttledFull = getThrottledFull();
+
+            if (throttledSome > 0 || throttledFull > 0) {
+                pw.println("    Throttled:");
+                pw.println("       Some: " + throttledSome + " Full: " + throttledFull);
+                pw.println("    Throttled by Type:");
+                final long compactionsThrottled = totalCompactRequested - totalCompactPerformed;
+                // Any throttle that was not part of the previous categories
+                final long unaccountedThrottled = compactionsThrottled
+                        - mProcCompactionsNoPidThrottled - mProcCompactionsOomAdjThrottled
+                        - mProcCompactionsTimeThrottled - mProcCompactionsRSSThrottled
+                        - mProcCompactionsMiscThrottled;
+                pw.println("       NoPid: " + mProcCompactionsNoPidThrottled
+                        + " OomAdj: " + mProcCompactionsOomAdjThrottled + " Time: "
+                        + mProcCompactionsTimeThrottled + " RSS: " + mProcCompactionsRSSThrottled
+                        + " Misc: " + mProcCompactionsMiscThrottled
+                        + " Unaccounted: " + unaccountedThrottled);
+                final double compactThrottlePercentage =
+                        (compactionsThrottled / (double) totalCompactRequested) * 100.0;
+                pw.println("    Throttle Percentage: " + compactThrottlePercentage);
+            }
+
+            if (mFullCompactPerformed > 0) {
+                pw.println("    -----Memory Stats----");
+                pw.println("    Total Delta Anon RSS (KB) : " + mTotalDeltaAnonRssKBs);
+                pw.println("    Total Physical ZRAM Consumed (KB): " + mTotalZramConsumedKBs);
+                pw.println("    Total Anon Memory Freed (KB): " + mTotalAnonMemFreedKBs);
+                // This tells us how much anon memory we were able to free thanks to running
+                // compaction
+                pw.println("    Avg Compaction Efficiency (Anon Freed/Anon RSS): "
+                        + (mTotalAnonMemFreedKBs / (double) mSumOrigAnonRss));
+                pw.println("    Max Compaction Efficiency: " + mMaxCompactEfficiency);
+                // This tells us how effective is the compression algorithm in physical memory
+                pw.println("    Avg Compression Ratio (1 - ZRAM Consumed/DeltaAnonRSS): "
+                        + (1.0 - mTotalZramConsumedKBs / (double) mTotalDeltaAnonRssKBs));
+                long avgKBsPerProcCompact = mFullCompactPerformed > 0
+                        ? (mTotalAnonMemFreedKBs / mFullCompactPerformed)
+                        : 0;
+                pw.println("    Avg Anon Mem Freed/Compaction (KB) : " + avgKBsPerProcCompact);
+                double compactionCost =
+                        mTotalCpuTimeMillis / (mTotalAnonMemFreedKBs / 1024.0); // ms/MB
+                pw.println("    Compaction Cost (ms/MB): " + compactionCost);
+            }
+        }
+    }
+
+    class AggregatedProcessCompactionStats extends AggregatedCompactionStats {
+        public final String processName;
+
+        AggregatedProcessCompactionStats(String processName) { this.processName = processName; }
+    }
+
+    class AggregatedSourceCompactionStats extends AggregatedCompactionStats {
+        public final CompactSource sourceType;
+
+        AggregatedSourceCompactionStats(CompactSource sourceType) { this.sourceType = sourceType; }
+    }
+
+    private final LinkedHashMap<String, AggregatedProcessCompactionStats> mPerProcessCompactStats =
+            new LinkedHashMap<>(256);
+    private final EnumMap<CompactSource, AggregatedSourceCompactionStats> mPerSourceCompactStats =
+            new EnumMap<>(CompactSource.class);
+    private long mTotalCompactionDowngrades;
     private long mSystemCompactionsPerformed;
+    private long mSystemTotalMemFreed;
+    private EnumMap<CancelCompactReason, Integer> mTotalCompactionsCancelled =
+            new EnumMap<>(CancelCompactReason.class);
 
     private final ProcessDependencies mProcessDependencies;
     private final ProcLocksReader mProcLocksReader;
@@ -450,34 +584,61 @@
             pw.println("  "  + KEY_COMPACT_PROC_STATE_THROTTLE + "="
                     + Arrays.toString(mProcStateThrottle.toArray(new Integer[0])));
 
-            pw.println(" Requested:  " + mSomeCompactRequest + " some, " + mFullCompactRequest
-                    + " full, " + mPersistentCompactRequest + " persistent, "
-                    + mBfgsCompactRequest + " BFGS compactions.");
-            pw.println(" Performed: " + mSomeCompactionCount + " some, " + mFullCompactionCount
-                    + " full, " + mPersistentCompactionCount + " persistent, "
-                    + mBfgsCompactionCount + " BFGS compactions.");
-            pw.println(" Process Compactions Requested: " + mProcCompactionsRequested);
-            pw.println(" Process Compactions Performed: " + mProcCompactionsPerformed);
-            long compactionsThrottled = mProcCompactionsRequested - mProcCompactionsPerformed;
-            pw.println(" Process Compactions Throttled: " + compactionsThrottled);
-            double compactThrottlePercentage =
-                    (compactionsThrottled / (double) mProcCompactionsRequested) * 100.0;
-            pw.println(" Process Compactions Throttle Percentage: " + compactThrottlePercentage);
-            pw.println("        NoPid Throttled: " + mProcCompactionsNoPidThrottled);
-            pw.println("        OomAdj Throttled: " + mProcCompactionsOomAdjThrottled);
-            pw.println("        Time Throttled: " + mProcCompactionsTimeThrottled);
-            pw.println("        RSS Throttled: " + mProcCompactionsRSSThrottled);
-            pw.println("        Misc Throttled: " + mProcCompactionsMiscThrottled);
-            long unaccountedThrottled = compactionsThrottled - mProcCompactionsNoPidThrottled
-                    - mProcCompactionsOomAdjThrottled - mProcCompactionsTimeThrottled
-                    - mProcCompactionsRSSThrottled - mProcCompactionsMiscThrottled;
-            // Any throttle that was not part of the previous categories
-            pw.println("        Unaccounted Throttled: " + unaccountedThrottled);
+            pw.println(" Per-Process Compaction Stats");
+            long totalCompactPerformedSome = 0;
+            long totalCompactPerformedFull = 0;
+            for (AggregatedProcessCompactionStats stats : mPerProcessCompactStats.values()) {
+                pw.println("-----" + stats.processName + "-----");
+                totalCompactPerformedSome += stats.mSomeCompactPerformed;
+                totalCompactPerformedFull += stats.mFullCompactPerformed;
+                stats.dump(pw);
+                pw.println();
+            }
+            pw.println();
+            pw.println(" Per-Source Compaction Stats");
+            for (AggregatedSourceCompactionStats stats : mPerSourceCompactStats.values()) {
+                pw.println("-----" + stats.sourceType + "-----");
+                stats.dump(pw);
+                pw.println();
+            }
+            pw.println();
 
-            pw.println(" System Compactions Performed: " + mSystemCompactionsPerformed);
+            pw.println("Total Compactions Performed by profile: " + totalCompactPerformedSome
+                    + " some, " + totalCompactPerformedFull + " full");
+            pw.println("Total compactions downgraded: " + mTotalCompactionDowngrades);
+            pw.println("Total compactions cancelled by reason: ");
+            for (CancelCompactReason reason : mTotalCompactionsCancelled.keySet()) {
+                pw.println("    " + reason + ": " + mTotalCompactionsCancelled.get(reason));
+            }
+            pw.println();
 
+            pw.println(" System Compaction Memory Stats");
+            pw.println("    Compactions Performed: " + mSystemCompactionsPerformed);
+            pw.println("    Total Memory Freed (KB): " + mSystemTotalMemFreed);
+            double avgKBsPerSystemCompact = mSystemCompactionsPerformed > 0
+                    ? mSystemTotalMemFreed / mSystemCompactionsPerformed
+                    : 0;
+            pw.println("    Avg Mem Freed per Compact (KB): " + avgKBsPerSystemCompact);
+            pw.println();
             pw.println("  Tracking last compaction stats for " + mLastCompactionStats.size()
                     + " processes.");
+            pw.println("Last Compaction per process stats:");
+            pw.println("    (ProcessName,Source,DeltaAnonRssKBs,ZramConsumedKBs,AnonMemFreedKBs,"
+                    + "CompactEfficiency,CompactCost(ms/MB),procState,oomAdj,oomAdjReason)");
+            for (Map.Entry<Integer, SingleCompactionStats> entry :
+                    mLastCompactionStats.entrySet()) {
+                SingleCompactionStats stats = entry.getValue();
+                stats.dump(pw);
+            }
+            pw.println();
+            pw.println("Last 20 Compactions Stats:");
+            pw.println("    (ProcessName,Source,DeltaAnonRssKBs,ZramConsumedKBs,AnonMemFreedKBs,"
+                    + "CompactEfficiency,CompactCost(ms/MB),procState,oomAdj,oomAdjReason)");
+            for (SingleCompactionStats stats : mCompactionStatsHistory) {
+                stats.dump(pw);
+            }
+            pw.println();
+
             pw.println("  " + KEY_USE_FREEZER + "=" + mUseFreezer);
             pw.println("  " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
             pw.println("  " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout);
@@ -500,25 +661,9 @@
                     }
                 }
             }
-            if (DEBUG_COMPACTION) {
-                for (Map.Entry<Integer, LastCompactionStats> entry
-                        : mLastCompactionStats.entrySet()) {
-                    int pid = entry.getKey();
-                    LastCompactionStats stats = entry.getValue();
-                    pw.println("    " + pid + ": "
-                            + Arrays.toString(stats.getRssAfterCompaction()));
-                }
-            }
         }
     }
 
-    @GuardedBy("mProcLock")
-    void compactAppSome(ProcessRecord app, boolean force) {
-        app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_SOME);
-        ++mSomeCompactRequest;
-        compactApp(app, force, "some");
-    }
-
     // This method returns true only if requirements are met. Note, that requirements are different
     // from throttles applied at the time a compaction is trying to be executed in the sense that
     // these are not subject to change dependent on time or memory as throttles usually do.
@@ -546,46 +691,38 @@
     }
 
     @GuardedBy("mProcLock")
-    void compactAppFull(ProcessRecord app, boolean force) {
-        boolean oomAdjEnteredCached = (app.mState.getSetAdj() < mCompactThrottleMinOomAdj
-                                              || app.mState.getSetAdj() > mCompactThrottleMaxOomAdj)
-                && app.mState.getCurAdj() >= mCompactThrottleMinOomAdj
-                && app.mState.getCurAdj() <= mCompactThrottleMaxOomAdj;
-        if (DEBUG_COMPACTION) {
-            Slog.d(TAG_AM,
-                    " compactAppFull requested for " + app.processName + " force: " + force
-                            + " oomAdjEnteredCached: " + oomAdjEnteredCached);
+    boolean compactApp(
+            ProcessRecord app, CompactProfile compactProfile, CompactSource source, boolean force) {
+        app.mOptRecord.setReqCompactSource(source);
+        app.mOptRecord.setReqCompactProfile(compactProfile);
+        AggregatedSourceCompactionStats perSourceStats = getPerSourceAggregatedCompactStat(source);
+        AggregatedCompactionStats perProcStats =
+                getPerProcessAggregatedCompactStat(app.processName);
+        switch (compactProfile) {
+            case SOME:
+                ++perProcStats.mSomeCompactRequested;
+                ++perSourceStats.mSomeCompactRequested;
+                break;
+            case FULL:
+                ++perProcStats.mFullCompactRequested;
+                ++perSourceStats.mFullCompactRequested;
+                break;
+            default:
+                Slog.e(TAG_AM,
+                        "Unimplemented compaction type, consider adding it.");
+                return false;
         }
-        ++mFullCompactRequest;
-        // Apply OOM adj score throttle for Full App Compaction.
-        if (force || oomAdjEnteredCached) {
-            app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
-            compactApp(app, force, "Full");
-        } else {
-            if (DEBUG_COMPACTION) {
-                Slog.d(TAG_AM, "Skipping full compaction for " + app.processName
-                        + " oom adj score changed from " + app.mState.getSetAdj()
-                        + " to " + app.mState.getCurAdj());
-            }
-        }
-    }
 
-    @GuardedBy("mProcLock")
-    void compactAppPersistent(ProcessRecord app) {
-        app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_PERSISTENT);
-        ++mPersistentCompactRequest;
-        compactApp(app, false, "Persistent");
-    }
-
-    @GuardedBy("mProcLock")
-    boolean compactApp(ProcessRecord app, boolean force, String compactRequestType) {
-        if (!app.mOptRecord.hasPendingCompact() && meetsCompactionRequirements(app)) {
+        if (!app.mOptRecord.hasPendingCompact() && (meetsCompactionRequirements(app) || force)) {
             final String processName = (app.processName != null ? app.processName : "");
             if (DEBUG_COMPACTION) {
-                Slog.d(TAG_AM, "compactApp " + compactRequestType + " " + processName);
+                Slog.d(TAG_AM,
+                        "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
+                                + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
             }
             Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_COMPACTION_TRACK,
-                    "compactApp " + compactRequestType + " " + processName);
+                    "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
+                            + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
             app.mOptRecord.setHasPendingCompact(true);
             app.mOptRecord.setForceCompact(force);
             mPendingCompactionProcesses.add(app);
@@ -596,14 +733,53 @@
 
         if (DEBUG_COMPACTION) {
             Slog.d(TAG_AM,
-                    " compactApp Skipped for " + app.processName
-                            + " pendingCompact= " + app.mOptRecord.hasPendingCompact()
-                            + " meetsCompactionRequirements=" + meetsCompactionRequirements(app)
-                            + ". Requested compact: " + app.mOptRecord.getReqCompactAction());
+                    " compactApp Skipped for " + app.processName + " pendingCompact= "
+                            + app.mOptRecord.hasPendingCompact() + " meetsCompactionRequirements="
+                            + meetsCompactionRequirements(app) + ". Requested compact profile: "
+                            + app.mOptRecord.getReqCompactProfile().name() + ". Compact source "
+                            + app.mOptRecord.getReqCompactSource().name());
         }
         return false;
     }
 
+    private CompactAction resolveCompactActionForProfile(CompactProfile profile) {
+        CompactAction action;
+        switch (profile) {
+            case SOME:
+                action = CompactAction.FILE;
+                break;
+            case FULL:
+                action = CompactAction.ALL;
+                break;
+            default:
+                action = CompactAction.NONE;
+        }
+        return action;
+    }
+
+    private AggregatedProcessCompactionStats getPerProcessAggregatedCompactStat(
+            String processName) {
+        if (processName == null) {
+            processName = "";
+        }
+        AggregatedProcessCompactionStats stats = mPerProcessCompactStats.get(processName);
+        if (stats == null) {
+            stats = new AggregatedProcessCompactionStats(processName);
+            mPerProcessCompactStats.put(processName, stats);
+        }
+        return stats;
+    }
+
+    private AggregatedSourceCompactionStats getPerSourceAggregatedCompactStat(
+            CompactSource source) {
+        AggregatedSourceCompactionStats stats = mPerSourceCompactStats.get(source);
+        if (stats == null) {
+            stats = new AggregatedSourceCompactionStats(source);
+            mPerSourceCompactStats.put(source, stats);
+        }
+        return stats;
+    }
+
     @GuardedBy("mProcLock")
     boolean shouldCompactPersistent(ProcessRecord app, long now) {
         return (app.mOptRecord.getLastCompactTime() == 0
@@ -611,13 +787,6 @@
     }
 
     @GuardedBy("mProcLock")
-    void compactAppBfgs(ProcessRecord app) {
-        ++mBfgsCompactRequest;
-        app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_BFGS);
-        compactApp(app, false, " Bfgs");
-    }
-
-    @GuardedBy("mProcLock")
     boolean shouldCompactBFGS(ProcessRecord app, long now) {
         return (app.mOptRecord.getLastCompactTime() == 0
                 || (now - app.mOptRecord.getLastCompactTime()) > mCompactThrottleBFGS);
@@ -648,11 +817,27 @@
     static private native void cancelCompaction();
 
     /**
+     * Returns the cpu time for the current thread
+     */
+    static private native long threadCpuTimeNs();
+
+    /**
      * Retrieves the free swap percentage.
      */
     static private native double getFreeSwapPercent();
 
     /**
+     * Retrieves the total used physical ZRAM
+     */
+    static private native long getUsedZramMemory();
+
+    /**
+     * Amount of memory that has been made free due to compaction.
+     * It represents uncompressed memory size - compressed memory size.
+     */
+    static private native long getMemoryFreedCompaction();
+
+    /**
      * Reads the flag value from DeviceConfig to determine whether app compaction
      * should be enabled, and starts the freeze/compaction thread if needed.
      */
@@ -851,8 +1036,8 @@
         int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2);
 
-        mCompactActionSome = compactActionIntToString(compactAction1);
-        mCompactActionFull = compactActionIntToString(compactAction2);
+        mCompactActionSome = compactActionIntToAction(compactAction1);
+        mCompactActionFull = compactActionIntToAction(compactAction2);
     }
 
     @GuardedBy("mPhenotypeFlagLock")
@@ -1019,13 +1204,12 @@
         return true;
     }
 
-    @VisibleForTesting
-    static String compactActionIntToString(int action) {
-        if (action < 0 || action >= COMPACT_ACTION_STRING.length) {
-            return "";
+    static CompactAction compactActionIntToAction(int action) {
+        if (action < 0 || action >= CompactAction.values().length) {
+            return CompactAction.NONE;
         }
 
-        return COMPACT_ACTION_STRING[action];
+        return CompactAction.values()[action];
     }
 
     // This will ensure app will be out of the freezer for at least mFreezerDebounceTimeout.
@@ -1202,16 +1386,17 @@
         if(wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
             // Remove any pending compaction we may have scheduled to happen while screen was off
             Slog.e(TAG_AM, "Cancel pending or running compactions as system is awake");
-            cancelAllCompactions();
+            cancelAllCompactions(CancelCompactReason.SCREEN_ON);
         }
     }
 
-    void cancelAllCompactions() {
+    void cancelAllCompactions(CancelCompactReason reason) {
         synchronized (mProcLock) {
             int size = mPendingCompactionProcesses.size();
             ProcessRecord record;
             for (int i=0; i < size; ++i) {
                 record = mPendingCompactionProcesses.get(i);
+                cancelCompactionForProcess(record, reason);
                 // The process record is kept alive after compactions are cleared,
                 // so make sure to reset the compaction state to avoid skipping any future
                 // compactions due to a stale value here.
@@ -1222,53 +1407,64 @@
         cancelCompaction();
     }
 
+    @GuardedBy("mProcLock")
+    void cancelCompactionForProcess(ProcessRecord app, CancelCompactReason cancelReason) {
+        boolean cancelled = false;
+        if (!mPendingCompactionProcesses.isEmpty() && mPendingCompactionProcesses.contains(app)) {
+            app.mOptRecord.setHasPendingCompact(false);
+            mPendingCompactionProcesses.remove(app);
+            cancelled = true;
+        }
+        if (DefaultProcessDependencies.mPidCompacting == app.mPid) {
+            cancelCompaction();
+            cancelled = true;
+        }
+        if (cancelled) {
+            if (mTotalCompactionsCancelled.containsKey(cancelReason)) {
+                int count = mTotalCompactionsCancelled.get(cancelReason);
+                mTotalCompactionsCancelled.put(cancelReason, count + 1);
+            } else {
+                mTotalCompactionsCancelled.put(cancelReason, 1);
+            }
+            if (DEBUG_COMPACTION) {
+                Slog.d(TAG_AM,
+                        "Cancelled pending or running compactions for process: " +
+                                app.processName != null ? app.processName : "" +
+                                " reason: " + cancelReason.name());
+            }
+        }
+    }
+
     @GuardedBy({"mService", "mProcLock"})
     void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) {
         // Cancel any currently executing compactions
         // if the process moved out of cached state
-        if (DefaultProcessDependencies.mPidCompacting == app.mPid && newAdj < oldAdj
-                && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
-            cancelCompaction();
+        if (newAdj < oldAdj && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
+            cancelCompactionForProcess(app, CancelCompactReason.OOM_IMPROVEMENT);
         }
 
         if (oldAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
                 && (newAdj == ProcessList.PREVIOUS_APP_ADJ || newAdj == ProcessList.HOME_APP_ADJ)) {
             // Perform a minor compaction when a perceptible app becomes the prev/home app
-            compactAppSome(app, false);
+            compactApp(app, CompactProfile.SOME, CompactSource.APP, false);
         } else if (oldAdj < ProcessList.CACHED_APP_MIN_ADJ
                 && newAdj >= ProcessList.CACHED_APP_MIN_ADJ
                 && newAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
             // Perform a major compaction when any app enters cached
-            compactAppFull(app, false);
+            compactApp(app, CompactProfile.FULL, CompactSource.APP, false);
         }
     }
 
     /**
-     * This method resolves which compaction method we should use for the proposed compaction.
+     * Applies a compaction downgrade when swap is low.
      */
-    int resolveCompactionAction(int pendingAction) {
-        int resolvedAction;
-
-        switch (pendingAction) {
-            case COMPACT_PROCESS_SOME:
-                resolvedAction = COMPACT_ACTION_FILE;
-                break;
-            // For the time being, treat these as equivalent.
-            case COMPACT_PROCESS_FULL:
-            case COMPACT_PROCESS_PERSISTENT:
-            case COMPACT_PROCESS_BFGS:
-                resolvedAction = COMPACT_ACTION_FULL;
-                break;
-            default:
-                resolvedAction = COMPACT_ACTION_NONE;
-                break;
-        }
-
+    CompactProfile downgradeCompactionIfRequired(CompactProfile profile) {
         // Downgrade compaction under swap memory pressure
-        if (resolvedAction == COMPACT_ACTION_FULL) {
+        if (profile == CompactProfile.FULL) {
             double swapFreePercent = getFreeSwapPercent();
             if (swapFreePercent < COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD) {
-                resolvedAction = COMPACT_ACTION_FILE;
+                profile = CompactProfile.SOME;
+                ++mTotalCompactionDowngrades;
                 if (DEBUG_COMPACTION) {
                     Slog.d(TAG_AM,
                             "Downgraded compaction to file only due to low swap."
@@ -1277,20 +1473,69 @@
             }
         }
 
-        return resolvedAction;
+        return profile;
     }
 
     @VisibleForTesting
-    static final class LastCompactionStats {
+    static final class SingleCompactionStats {
+        private static final float STATSD_SAMPLE_RATE = 0.1f;
+        private static final Random mRandom = new Random();
         private final long[] mRssAfterCompaction;
+        public CompactSource mSourceType;
+        public String mProcessName;
+        public final int mUid;
+        public long mDeltaAnonRssKBs;
+        public long mZramConsumedKBs;
+        public long mAnonMemFreedKBs;
+        public float mCpuTimeMillis;
+        public long mOrigAnonRss;
+        public int mProcState;
+        public int mOomAdj;
+        public @OomAdjuster.OomAdjReason int mOomAdjReason;
 
-        LastCompactionStats(long[] rss) {
+        SingleCompactionStats(long[] rss, CompactSource source, String processName,
+                long deltaAnonRss, long zramConsumed, long anonMemFreed, long origAnonRss,
+                long cpuTimeMillis, int procState, int oomAdj,
+                @OomAdjuster.OomAdjReason int oomAdjReason, int uid) {
             mRssAfterCompaction = rss;
+            mSourceType = source;
+            mProcessName = processName;
+            mUid = uid;
+            mDeltaAnonRssKBs = deltaAnonRss;
+            mZramConsumedKBs = zramConsumed;
+            mAnonMemFreedKBs = anonMemFreed;
+            mCpuTimeMillis = cpuTimeMillis;
+            mOrigAnonRss = origAnonRss;
+            mProcState = procState;
+            mOomAdj = oomAdj;
+            mOomAdjReason = oomAdjReason;
+        }
+
+        double getCompactEfficiency() { return mAnonMemFreedKBs / (double) mOrigAnonRss; }
+
+        double getCompactCost() {
+            // mCpuTimeMillis / (anonMemFreedKBs/1024) and metric is in (ms/MB)
+            return mCpuTimeMillis / (double) mAnonMemFreedKBs * 1024;
         }
 
         long[] getRssAfterCompaction() {
             return mRssAfterCompaction;
         }
+
+        void dump(PrintWriter pw) {
+            pw.println("    (" + mProcessName + "," + mSourceType.name() + "," + mDeltaAnonRssKBs
+                    + "," + mZramConsumedKBs + "," + mAnonMemFreedKBs + "," + getCompactEfficiency()
+                    + "," + getCompactCost() + "," + mProcState + "," + mOomAdj + ","
+                    + OomAdjuster.oomAdjReasonToString(mOomAdjReason) + ")");
+        }
+
+        void sendStat() {
+            if (mRandom.nextFloat() < STATSD_SAMPLE_RATE) {
+                FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPACTED_V2, mUid, mProcState,
+                        mOomAdj, mDeltaAnonRssKBs, mZramConsumedKBs, mCpuTimeMillis, mOrigAnonRss,
+                        mOomAdjReason);
+            }
+        }
     }
 
     private final class MemCompactionHandler extends Handler {
@@ -1298,13 +1543,12 @@
             super(mCachedAppOptimizerThread.getLooper());
         }
 
-        private boolean shouldOomAdjThrottleCompaction(ProcessRecord proc, int action) {
+        private boolean shouldOomAdjThrottleCompaction(ProcessRecord proc) {
             final String name = proc.processName;
 
             // don't compact if the process has returned to perceptible
             // and this is only a cached/home/prev compaction
-            if ((action == COMPACT_ACTION_FILE || action == COMPACT_ACTION_FULL)
-                    && (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
+            if (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                 if (DEBUG_COMPACTION) {
                     Slog.d(TAG_AM,
                             "Skipping compaction as process " + name + " is "
@@ -1316,51 +1560,52 @@
             return false;
         }
 
-        private boolean shouldTimeThrottleCompaction(
-                ProcessRecord proc, long start, int pendingAction) {
+        private boolean shouldTimeThrottleCompaction(ProcessRecord proc, long start,
+                CompactProfile pendingProfile, CompactSource source) {
             final ProcessCachedOptimizerRecord opt = proc.mOptRecord;
             final String name = proc.processName;
 
-            int lastCompactAction = opt.getLastCompactAction();
+            CompactProfile lastCompactProfile = opt.getLastCompactProfile();
             long lastCompactTime = opt.getLastCompactTime();
 
             // basic throttling
-            // use the Phenotype flag knobs to determine whether current/prevous
-            // compaction combo should be throtted or not
-
+            // use the Phenotype flag knobs to determine whether current/previous
+            // compaction combo should be throttled or not.
             // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
             // should very seldom change, and taking the risk of using the wrong action is
             // preferable to taking the lock for every single compaction action.
             if (lastCompactTime != 0) {
-                if (pendingAction == COMPACT_PROCESS_SOME) {
-                    if ((lastCompactAction == COMPACT_PROCESS_SOME
-                                && (start - lastCompactTime < mCompactThrottleSomeSome))
-                            || (lastCompactAction == COMPACT_PROCESS_FULL
-                                    && (start - lastCompactTime < mCompactThrottleSomeFull))) {
-                        if (DEBUG_COMPACTION) {
-                            Slog.d(TAG_AM,
-                                    "Skipping some compaction for " + name
-                                            + ": too soon. throttle=" + mCompactThrottleSomeSome
-                                            + "/" + mCompactThrottleSomeFull
-                                            + " last=" + (start - lastCompactTime) + "ms ago");
+                if (source == CompactSource.APP) {
+                    if (pendingProfile == CompactProfile.SOME) {
+                        if ((lastCompactProfile == CompactProfile.SOME
+                                    && (start - lastCompactTime < mCompactThrottleSomeSome))
+                                || (lastCompactProfile == CompactProfile.FULL
+                                        && (start - lastCompactTime < mCompactThrottleSomeFull))) {
+                            if (DEBUG_COMPACTION) {
+                                Slog.d(TAG_AM,
+                                        "Skipping some compaction for " + name
+                                                + ": too soon. throttle=" + mCompactThrottleSomeSome
+                                                + "/" + mCompactThrottleSomeFull
+                                                + " last=" + (start - lastCompactTime) + "ms ago");
+                            }
+                            return true;
                         }
-                        return true;
-                    }
-                } else if (pendingAction == COMPACT_PROCESS_FULL) {
-                    if ((lastCompactAction == COMPACT_PROCESS_SOME
-                                && (start - lastCompactTime < mCompactThrottleFullSome))
-                            || (lastCompactAction == COMPACT_PROCESS_FULL
-                                    && (start - lastCompactTime < mCompactThrottleFullFull))) {
-                        if (DEBUG_COMPACTION) {
-                            Slog.d(TAG_AM,
-                                    "Skipping full compaction for " + name
-                                            + ": too soon. throttle=" + mCompactThrottleFullSome
-                                            + "/" + mCompactThrottleFullFull
-                                            + " last=" + (start - lastCompactTime) + "ms ago");
+                    } else if (pendingProfile == CompactProfile.FULL) {
+                        if ((lastCompactProfile == CompactProfile.SOME
+                                    && (start - lastCompactTime < mCompactThrottleFullSome))
+                                || (lastCompactProfile == CompactProfile.FULL
+                                        && (start - lastCompactTime < mCompactThrottleFullFull))) {
+                            if (DEBUG_COMPACTION) {
+                                Slog.d(TAG_AM,
+                                        "Skipping full compaction for " + name
+                                                + ": too soon. throttle=" + mCompactThrottleFullSome
+                                                + "/" + mCompactThrottleFullFull
+                                                + " last=" + (start - lastCompactTime) + "ms ago");
+                            }
+                            return true;
                         }
-                        return true;
                     }
-                } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) {
+                } else if (source == CompactSource.PERSISTENT) {
                     if (start - lastCompactTime < mCompactThrottlePersistent) {
                         if (DEBUG_COMPACTION) {
                             Slog.d(TAG_AM,
@@ -1370,7 +1615,7 @@
                         }
                         return true;
                     }
-                } else if (pendingAction == COMPACT_PROCESS_BFGS) {
+                } else if (source == CompactSource.BFGS) {
                     if (start - lastCompactTime < mCompactThrottleBFGS) {
                         if (DEBUG_COMPACTION) {
                             Slog.d(TAG_AM,
@@ -1386,11 +1631,10 @@
             return false;
         }
 
-        private boolean shouldThrottleMiscCompaction(
-                ProcessRecord proc, int procState, int action) {
-            final String name = proc.processName;
+        private boolean shouldThrottleMiscCompaction(ProcessRecord proc, int procState) {
             if (mProcStateThrottle.contains(procState)) {
                 if (DEBUG_COMPACTION) {
+                    final String name = proc.processName;
                     Slog.d(TAG_AM,
                             "Skipping full compaction for process " + name + "; proc state is "
                                     + procState);
@@ -1398,21 +1642,13 @@
                 return true;
             }
 
-            if (COMPACT_ACTION_NONE == action) {
-                if (DEBUG_COMPACTION) {
-                    Slog.d(TAG_AM,
-                            "Skipping compaction for process " + name + "since action is None");
-                }
-                return true;
-            }
-
             return false;
         }
 
         private boolean shouldRssThrottleCompaction(
-                int action, int pid, String name, long[] rssBefore) {
+                CompactProfile profile, int pid, String name, long[] rssBefore) {
             long anonRssBefore = rssBefore[RSS_ANON_INDEX];
-            LastCompactionStats lastCompactionStats = mLastCompactionStats.get(pid);
+            SingleCompactionStats lastCompactionStats = mLastCompactionStats.get(pid);
 
             if (rssBefore[RSS_TOTAL_INDEX] == 0 && rssBefore[RSS_FILE_INDEX] == 0
                     && rssBefore[RSS_ANON_INDEX] == 0 && rssBefore[RSS_SWAP_INDEX] == 0) {
@@ -1424,7 +1660,7 @@
                 return true;
             }
 
-            if (action == COMPACT_ACTION_FULL || action == COMPACT_ACTION_ANON) {
+            if (profile == CompactProfile.FULL) {
                 if (mFullAnonRssThrottleKb > 0L && anonRssBefore < mFullAnonRssThrottleKb) {
                     if (DEBUG_COMPACTION) {
                         Slog.d(TAG_AM,
@@ -1461,13 +1697,16 @@
                     ProcessRecord proc;
                     final ProcessCachedOptimizerRecord opt;
                     int pid;
-                    String action;
+                    CompactAction resolvedAction;
                     final String name;
-                    int requestedAction, lastCompactAction;
+                    CompactProfile lastCompactProfile;
                     long lastCompactTime;
-                    int lastOomAdj = msg.arg1;
+                    int newOomAdj = msg.arg1;
                     int procState = msg.arg2;
                     boolean forceCompaction;
+                    CompactSource compactSource;
+                    CompactProfile requestedProfile;
+                    int oomAdjReason;
                     synchronized (mProcLock) {
                         if (mPendingCompactionProcesses.isEmpty()) {
                             if (DEBUG_COMPACTION) {
@@ -1479,42 +1718,53 @@
                         opt = proc.mOptRecord;
                         forceCompaction = opt.isForceCompact();
                         opt.setForceCompact(false); // since this is a one-shot operation
-
-                        requestedAction = opt.getReqCompactAction();
                         pid = proc.getPid();
                         name = proc.processName;
                         opt.setHasPendingCompact(false);
-                        lastCompactAction = opt.getLastCompactAction();
+                        compactSource = opt.getReqCompactSource();
+                        requestedProfile = opt.getReqCompactProfile();
+                        lastCompactProfile = opt.getLastCompactProfile();
                         lastCompactTime = opt.getLastCompactTime();
+                        oomAdjReason = opt.getLastOomAdjChangeReason();
                     }
 
-                    ++mProcCompactionsRequested;
+                    AggregatedSourceCompactionStats perSourceStats =
+                            getPerSourceAggregatedCompactStat(opt.getReqCompactSource());
+                    AggregatedProcessCompactionStats perProcessStats =
+                            getPerProcessAggregatedCompactStat(name);
+
                     long[] rssBefore;
                     if (pid == 0) {
                         // not a real process, either one being launched or one being killed
                         if (DEBUG_COMPACTION) {
                             Slog.d(TAG_AM, "Compaction failed, pid is 0");
                         }
-                        ++mProcCompactionsNoPidThrottled;
+                        ++perSourceStats.mProcCompactionsNoPidThrottled;
+                        ++perProcessStats.mProcCompactionsNoPidThrottled;
                         return;
                     }
 
                     if (!forceCompaction) {
-                        if (shouldOomAdjThrottleCompaction(proc, requestedAction)) {
-                            ++mProcCompactionsOomAdjThrottled;
+                        if (shouldOomAdjThrottleCompaction(proc)) {
+                            ++perProcessStats.mProcCompactionsOomAdjThrottled;
+                            ++perSourceStats.mProcCompactionsOomAdjThrottled;
                             return;
                         }
-                        if (shouldTimeThrottleCompaction(proc, start, requestedAction)) {
-                            ++mProcCompactionsTimeThrottled;
+                        if (shouldTimeThrottleCompaction(
+                                    proc, start, requestedProfile, compactSource)) {
+                            ++perProcessStats.mProcCompactionsTimeThrottled;
+                            ++perSourceStats.mProcCompactionsTimeThrottled;
                             return;
                         }
-                        if (shouldThrottleMiscCompaction(proc, procState, requestedAction)) {
-                            ++mProcCompactionsMiscThrottled;
+                        if (shouldThrottleMiscCompaction(proc, procState)) {
+                            ++perProcessStats.mProcCompactionsMiscThrottled;
+                            ++perSourceStats.mProcCompactionsMiscThrottled;
                             return;
                         }
                         rssBefore = mProcessDependencies.getRss(pid);
-                        if (shouldRssThrottleCompaction(requestedAction, pid, name, rssBefore)) {
-                            ++mProcCompactionsRSSThrottled;
+                        if (shouldRssThrottleCompaction(requestedProfile, pid, name, rssBefore)) {
+                            ++perProcessStats.mProcCompactionsRSSThrottled;
+                            ++perSourceStats.mProcCompactionsRSSThrottled;
                             return;
                         }
                     } else {
@@ -1524,71 +1774,78 @@
                         }
                     }
 
-                    // Now we've passed through all the throttles and are going to compact, update
-                    // bookkeeping.
-                    switch (requestedAction) {
-                        case COMPACT_PROCESS_SOME:
-                            mSomeCompactionCount++;
-                            break;
-                        case COMPACT_PROCESS_FULL:
-                            mFullCompactionCount++;
-                            break;
-                        case COMPACT_PROCESS_PERSISTENT:
-                            mPersistentCompactionCount++;
-                            break;
-                        case COMPACT_PROCESS_BFGS:
-                            mBfgsCompactionCount++;
-                            break;
-                        default:
-                            break;
-                    }
-
-                    int resolvedAction = resolveCompactionAction(requestedAction);
-                    action = compactActionIntToString(resolvedAction);
+                    CompactProfile resolvedProfile =
+                            downgradeCompactionIfRequired(requestedProfile);
+                    resolvedAction = resolveCompactActionForProfile(resolvedProfile);
 
                     try {
                         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
-                                "Compact " + action + ": " + name);
-                        ++mProcCompactionsPerformed;
-                        long zramFreeKbBefore = Debug.getZramFreeKb();
-                        mProcessDependencies.performCompaction(action, pid);
+                                "Compact " + resolvedAction.name() + ": " + name
+                                        + " lastOomAdjReason: " + oomAdjReason);
+                        long zramUsedKbBefore = getUsedZramMemory();
+                        long startCpuTime = threadCpuTimeNs();
+                        mProcessDependencies.performCompaction(resolvedAction, pid);
+                        long endCpuTime = threadCpuTimeNs();
                         long[] rssAfter = mProcessDependencies.getRss(pid);
                         long end = SystemClock.uptimeMillis();
                         long time = end - start;
-                        long zramFreeKbAfter = Debug.getZramFreeKb();
+                        long deltaCpuTimeNanos = endCpuTime - startCpuTime;
+                        long zramUsedKbAfter = getUsedZramMemory();
                         long deltaTotalRss = rssAfter[RSS_TOTAL_INDEX] - rssBefore[RSS_TOTAL_INDEX];
                         long deltaFileRss = rssAfter[RSS_FILE_INDEX] - rssBefore[RSS_FILE_INDEX];
                         long deltaAnonRss = rssAfter[RSS_ANON_INDEX] - rssBefore[RSS_ANON_INDEX];
                         long deltaSwapRss = rssAfter[RSS_SWAP_INDEX] - rssBefore[RSS_SWAP_INDEX];
-                        EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
-                                rssBefore[RSS_TOTAL_INDEX], rssBefore[RSS_FILE_INDEX],
-                                rssBefore[RSS_ANON_INDEX], rssBefore[RSS_SWAP_INDEX], deltaTotalRss,
-                                deltaFileRss, deltaAnonRss, deltaSwapRss, time, lastCompactAction,
-                                lastCompactTime, lastOomAdj, procState, zramFreeKbBefore,
-                                zramFreeKbAfter - zramFreeKbBefore);
-                        // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
-                        // on every single compaction for a flag that will seldom change and the
-                        // impact of reading the wrong value here is low.
-                        if (mRandom.nextFloat() < mCompactStatsdSampleRate) {
-                            FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPACTED, pid, name,
-                                    requestedAction, rssBefore[RSS_TOTAL_INDEX],
-                                    rssBefore[RSS_FILE_INDEX], rssBefore[RSS_ANON_INDEX],
-                                    rssBefore[RSS_SWAP_INDEX], rssAfter[RSS_TOTAL_INDEX],
-                                    rssAfter[RSS_FILE_INDEX], rssAfter[RSS_ANON_INDEX],
-                                    rssAfter[RSS_SWAP_INDEX], time, lastCompactAction,
-                                    lastCompactTime, lastOomAdj,
-                                    ActivityManager.processStateAmToProto(procState),
-                                    zramFreeKbBefore, zramFreeKbAfter);
+                        switch (opt.getReqCompactProfile()) {
+                            case SOME:
+                                ++perSourceStats.mSomeCompactPerformed;
+                                ++perProcessStats.mSomeCompactPerformed;
+                                break;
+                            case FULL:
+                                ++perSourceStats.mFullCompactPerformed;
+                                ++perProcessStats.mFullCompactPerformed;
+                                long anonRssSavings = -deltaAnonRss;
+                                long zramConsumed = zramUsedKbAfter - zramUsedKbBefore;
+                                long memFreed = anonRssSavings - zramConsumed;
+                                long totalCpuTimeMillis = deltaCpuTimeNanos / 1000000;
+                                long origAnonRss = rssBefore[RSS_ANON_INDEX];
+
+                                // Negative stats would skew averages and will likely be due to
+                                // noise of system doing other things so we put a floor at 0 to
+                                // avoid negative values.
+                                anonRssSavings = anonRssSavings > 0 ? anonRssSavings : 0;
+                                zramConsumed = zramConsumed > 0 ? zramConsumed : 0;
+                                memFreed = memFreed > 0 ? memFreed : 0;
+
+                                perProcessStats.addMemStats(anonRssSavings, zramConsumed, memFreed,
+                                        origAnonRss, totalCpuTimeMillis);
+                                perSourceStats.addMemStats(anonRssSavings, zramConsumed, memFreed,
+                                        origAnonRss, totalCpuTimeMillis);
+                                SingleCompactionStats memStats = new SingleCompactionStats(rssAfter,
+                                        compactSource, name, anonRssSavings, zramConsumed, memFreed,
+                                        origAnonRss, totalCpuTimeMillis, procState, newOomAdj,
+                                        oomAdjReason, proc.uid);
+                                mLastCompactionStats.remove(pid);
+                                mLastCompactionStats.put(pid, memStats);
+                                mCompactionStatsHistory.add(memStats);
+                                memStats.sendStat();
+                                break;
+                            default:
+                                // We likely missed adding this category, it needs to be added
+                                // if we end up here. In the meantime, gracefully fallback to
+                                // attribute to app.
+                                Slog.wtf(TAG_AM, "Compaction: Unknown requested action");
+                                return;
                         }
+                        EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name,
+                                resolvedAction.name(), rssBefore[RSS_TOTAL_INDEX],
+                                rssBefore[RSS_FILE_INDEX], rssBefore[RSS_ANON_INDEX],
+                                rssBefore[RSS_SWAP_INDEX], deltaTotalRss, deltaFileRss,
+                                deltaAnonRss, deltaSwapRss, time, lastCompactProfile.name(),
+                                lastCompactTime, newOomAdj, procState, zramUsedKbBefore,
+                                zramUsedKbBefore - zramUsedKbAfter);
                         synchronized (mProcLock) {
                             opt.setLastCompactTime(end);
-                            opt.setLastCompactAction(resolvedAction);
-                        }
-                        if (resolvedAction == COMPACT_ACTION_FULL
-                                || resolvedAction == COMPACT_ACTION_ANON) {
-                            // Remove entry and insert again to update insertion order.
-                            mLastCompactionStats.remove(pid);
-                            mLastCompactionStats.put(pid, new LastCompactionStats(rssAfter));
+                            opt.setLastCompactProfile(requestedProfile);
                         }
                     } catch (Exception e) {
                         // nothing to do, presumably the process died
@@ -1603,7 +1860,10 @@
                 case COMPACT_SYSTEM_MSG: {
                     ++mSystemCompactionsPerformed;
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem");
+                    long memFreedBefore = getMemoryFreedCompaction();
                     compactSystem();
+                    long memFreedAfter = getMemoryFreedCompaction();
+                    mSystemTotalMemFreed += memFreedAfter - memFreedBefore;
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 }
@@ -1809,14 +2069,14 @@
 
         // Compact process.
         @Override
-        public void performCompaction(String action, int pid) throws IOException {
+        public void performCompaction(CompactAction action, int pid) throws IOException {
             mPidCompacting = pid;
-            if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])) {
-                compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG);
-            } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FILE])) {
-                compactProcess(pid, COMPACT_ACTION_FILE_FLAG);
-            } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) {
-                compactProcess(pid, COMPACT_ACTION_ANON_FLAG);
+            if (action == CompactAction.ALL) {
+                    compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG);
+            } else if (action == CompactAction.FILE) {
+                    compactProcess(pid, COMPACT_ACTION_FILE_FLAG);
+            } else if (action == CompactAction.ANON) {
+                    compactProcess(pid, COMPACT_ACTION_ANON_FLAG);
             }
             mPidCompacting = -1;
         }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9607e40..8759f230 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -76,9 +76,11 @@
 import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
+import android.app.AppProtoEnums;
 import android.app.ApplicationExitInfo;
 import android.app.usage.UsageEvents;
 import android.compat.annotation.ChangeId;
@@ -113,6 +115,8 @@
 import com.android.server.wm.WindowProcessController;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -122,20 +126,97 @@
  */
 public class OomAdjuster {
     static final String TAG = "OomAdjuster";
-    static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
-    static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
-    static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
-    static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
-    static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
-    static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
-    static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
-    static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
-    static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
-    static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
-    static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
-    static final String OOM_ADJ_REASON_ALLOWLIST = OOM_ADJ_REASON_METHOD + "_allowlistChange";
-    static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
-    static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
+
+    static final int OOM_ADJ_REASON_NONE = 0;
+    static final int OOM_ADJ_REASON_ACTIVITY = 1;
+    static final int OOM_ADJ_REASON_FINISH_RECEIVER = 2;
+    static final int OOM_ADJ_REASON_START_RECEIVER = 3;
+    static final int OOM_ADJ_REASON_BIND_SERVICE = 4;
+    static final int OOM_ADJ_REASON_UNBIND_SERVICE = 5;
+    static final int OOM_ADJ_REASON_START_SERVICE = 6;
+    static final int OOM_ADJ_REASON_GET_PROVIDER = 7;
+    static final int OOM_ADJ_REASON_REMOVE_PROVIDER = 8;
+    static final int OOM_ADJ_REASON_UI_VISIBILITY = 9;
+    static final int OOM_ADJ_REASON_ALLOWLIST = 10;
+    static final int OOM_ADJ_REASON_PROCESS_BEGIN = 11;
+    static final int OOM_ADJ_REASON_PROCESS_END = 12;
+
+    @IntDef(prefix = {"OOM_ADJ_REASON_"},
+            value = {OOM_ADJ_REASON_NONE, OOM_ADJ_REASON_ACTIVITY, OOM_ADJ_REASON_FINISH_RECEIVER,
+                    OOM_ADJ_REASON_START_RECEIVER, OOM_ADJ_REASON_BIND_SERVICE,
+                    OOM_ADJ_REASON_UNBIND_SERVICE, OOM_ADJ_REASON_START_SERVICE,
+                    OOM_ADJ_REASON_GET_PROVIDER, OOM_ADJ_REASON_REMOVE_PROVIDER,
+                    OOM_ADJ_REASON_UI_VISIBILITY, OOM_ADJ_REASON_ALLOWLIST,
+                    OOM_ADJ_REASON_PROCESS_BEGIN, OOM_ADJ_REASON_PROCESS_END})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface OomAdjReason {}
+
+    public static final int oomAdjReasonToProto(@OomAdjReason int oomReason) {
+        switch (oomReason) {
+            case OOM_ADJ_REASON_NONE:
+                return AppProtoEnums.OOM_ADJ_REASON_NONE;
+            case OOM_ADJ_REASON_ACTIVITY:
+                return AppProtoEnums.OOM_ADJ_REASON_ACTIVITY;
+            case OOM_ADJ_REASON_FINISH_RECEIVER:
+                return AppProtoEnums.OOM_ADJ_REASON_FINISH_RECEIVER;
+            case OOM_ADJ_REASON_START_RECEIVER:
+                return AppProtoEnums.OOM_ADJ_REASON_START_RECEIVER;
+            case OOM_ADJ_REASON_BIND_SERVICE:
+                return AppProtoEnums.OOM_ADJ_REASON_BIND_SERVICE;
+            case OOM_ADJ_REASON_UNBIND_SERVICE:
+                return AppProtoEnums.OOM_ADJ_REASON_UNBIND_SERVICE;
+            case OOM_ADJ_REASON_START_SERVICE:
+                return AppProtoEnums.OOM_ADJ_REASON_START_SERVICE;
+            case OOM_ADJ_REASON_GET_PROVIDER:
+                return AppProtoEnums.OOM_ADJ_REASON_GET_PROVIDER;
+            case OOM_ADJ_REASON_REMOVE_PROVIDER:
+                return AppProtoEnums.OOM_ADJ_REASON_REMOVE_PROVIDER;
+            case OOM_ADJ_REASON_UI_VISIBILITY:
+                return AppProtoEnums.OOM_ADJ_REASON_UI_VISIBILITY;
+            case OOM_ADJ_REASON_ALLOWLIST:
+                return AppProtoEnums.OOM_ADJ_REASON_ALLOWLIST;
+            case OOM_ADJ_REASON_PROCESS_BEGIN:
+                return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN;
+            case OOM_ADJ_REASON_PROCESS_END:
+                return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END;
+            default:
+                return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
+        }
+    }
+
+    public static final String oomAdjReasonToString(@OomAdjReason int oomReason) {
+        final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
+        switch (oomReason) {
+            case OOM_ADJ_REASON_NONE:
+                return OOM_ADJ_REASON_METHOD + "_meh";
+            case OOM_ADJ_REASON_ACTIVITY:
+                return OOM_ADJ_REASON_METHOD + "_activityChange";
+            case OOM_ADJ_REASON_FINISH_RECEIVER:
+                return OOM_ADJ_REASON_METHOD + "_finishReceiver";
+            case OOM_ADJ_REASON_START_RECEIVER:
+                return OOM_ADJ_REASON_METHOD + "_startReceiver";
+            case OOM_ADJ_REASON_BIND_SERVICE:
+                return OOM_ADJ_REASON_METHOD + "_bindService";
+            case OOM_ADJ_REASON_UNBIND_SERVICE:
+                return OOM_ADJ_REASON_METHOD + "_unbindService";
+            case OOM_ADJ_REASON_START_SERVICE:
+                return OOM_ADJ_REASON_METHOD + "_startService";
+            case OOM_ADJ_REASON_GET_PROVIDER:
+                return OOM_ADJ_REASON_METHOD + "_getProvider";
+            case OOM_ADJ_REASON_REMOVE_PROVIDER:
+                return OOM_ADJ_REASON_METHOD + "_removeProvider";
+            case OOM_ADJ_REASON_UI_VISIBILITY:
+                return OOM_ADJ_REASON_METHOD + "_uiVisibility";
+            case OOM_ADJ_REASON_ALLOWLIST:
+                return OOM_ADJ_REASON_METHOD + "_allowlistChange";
+            case OOM_ADJ_REASON_PROCESS_BEGIN:
+                return OOM_ADJ_REASON_METHOD + "_processBegin";
+            case OOM_ADJ_REASON_PROCESS_END:
+                return OOM_ADJ_REASON_METHOD + "_processEnd";
+            default:
+                return "_unknown";
+        }
+    }
 
     /**
      * Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used
@@ -418,14 +499,14 @@
      * Update OomAdj for all processes in LRU list
      */
     @GuardedBy("mService")
-    void updateOomAdjLocked(String oomAdjReason) {
+    void updateOomAdjLocked(@OomAdjReason int oomAdjReason) {
         synchronized (mProcLock) {
             updateOomAdjLSP(oomAdjReason);
         }
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    private void updateOomAdjLSP(String oomAdjReason) {
+    private void updateOomAdjLSP(@OomAdjReason int oomAdjReason) {
         if (checkAndEnqueueOomAdjTargetLocked(null)) {
             // Simply return as there is an oomAdjUpdate ongoing
             return;
@@ -441,7 +522,7 @@
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    private void performUpdateOomAdjLSP(String oomAdjReason) {
+    private void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
         // Clear any pending ones because we are doing a full update now.
         mPendingProcessSet.clear();
@@ -458,14 +539,14 @@
      * @param oomAdjReason
      */
     @GuardedBy("mService")
-    boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+    boolean updateOomAdjLocked(ProcessRecord app, @OomAdjReason int oomAdjReason) {
         synchronized (mProcLock) {
             return updateOomAdjLSP(app, oomAdjReason);
         }
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
+    private boolean updateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
         if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
             updateOomAdjLSP(oomAdjReason);
             return true;
@@ -487,10 +568,10 @@
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
+    private boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
 
-        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
         mService.mOomAdjProfiler.oomAdjStarted();
         mAdjSeq++;
 
@@ -509,6 +590,7 @@
         state.setCurBoundByNonBgRestrictedApp(false);
         // Check if this process is in the pending list too, remove from pending list if so.
         mPendingProcessSet.remove(app);
+        app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
         boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp,
                 SystemClock.uptimeMillis());
         // The 'app' here itself might or might not be in the cycle, for example,
@@ -688,7 +770,7 @@
      * {@link #enqueueOomAdjTargetLocked}.
      */
     @GuardedBy("mService")
-    void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+    void updateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) {
         // First check if there is pending full update
         if (mPendingFullOomAdjUpdate) {
             mPendingFullOomAdjUpdate = false;
@@ -716,10 +798,11 @@
     }
 
     @GuardedBy("mService")
-    private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) {
+    private void performUpdateOomAdjPendingTargetsLocked(
+            @OomAdjuster.OomAdjReason int oomAdjReason) {
         final ProcessRecord topApp = mService.getTopApp();
 
-        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
         mService.mOomAdjProfiler.oomAdjStarted();
 
         final ArrayList<ProcessRecord> processes = mTmpProcessList;
@@ -741,11 +824,11 @@
      * get evaluated recursively here.
      */
     @GuardedBy({"mService", "mProcLock"})
-    private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp,
+    private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
             ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
             boolean startProfiling) {
         if (startProfiling) {
-            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
             mService.mOomAdjProfiler.oomAdjStarted();
         }
         final long now = SystemClock.uptimeMillis();
@@ -806,6 +889,7 @@
             final ProcessStateRecord state = app.mState;
             if (!app.isKilledByAm() && app.getThread() != null) {
                 state.setProcStateChanged(false);
+                app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
                 computeOomAdjLSP(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
                         computeClients); // It won't enter cycle if not computing clients.
                 // if any app encountered a cycle, we need to perform an additional loop later
@@ -2582,11 +2666,13 @@
                         // processing of the requests. As a result, there is throttling both here
                         // and in CachedAppOptimizer.
                         && mCachedAppOptimizer.shouldCompactPersistent(app, now)) {
-                    mCachedAppOptimizer.compactAppPersistent(app);
+                    mCachedAppOptimizer.compactApp(app, CachedAppOptimizer.CompactProfile.FULL,
+                            CachedAppOptimizer.CompactSource.PERSISTENT, false);
                 } else if (state.getCurProcState()
                                 == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                         && mCachedAppOptimizer.shouldCompactBFGS(app, now)) {
-                    mCachedAppOptimizer.compactAppBfgs(app);
+                    mCachedAppOptimizer.compactApp(app, CachedAppOptimizer.CompactProfile.FULL,
+                            CachedAppOptimizer.CompactSource.BFGS, false);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index a613729..fb41a39 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -39,16 +39,24 @@
     private long mLastCompactTime;
 
     /**
-     * The most recent compaction action requested for this app.
+     * The most recent compaction profile requested for this app.
      */
-    @GuardedBy("mProcLock")
-    private int mReqCompactAction;
+    @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mReqCompactProfile;
+
+    /**
+     * Source that requested the latest compaction for this app.
+     */
+    @GuardedBy("mProcLock") private CachedAppOptimizer.CompactSource mReqCompactSource;
+
+    /**
+     * Last oom adjust change reason for this app.
+     */
+    @GuardedBy("mProcLock") private @OomAdjuster.OomAdjReason int mLastOomAdjChangeReason;
 
     /**
      * The most recent compaction action performed for this app.
      */
-    @GuardedBy("mProcLock")
-    private int mLastCompactAction;
+    @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mLastCompactProfile;
 
     /**
      * This process has been scheduled for a memory compaction.
@@ -105,23 +113,49 @@
     }
 
     @GuardedBy("mProcLock")
-    int getReqCompactAction() {
-        return mReqCompactAction;
+    CachedAppOptimizer.CompactProfile getReqCompactProfile() {
+        return mReqCompactProfile;
     }
 
     @GuardedBy("mProcLock")
-    void setReqCompactAction(int reqCompactAction) {
-        mReqCompactAction = reqCompactAction;
+    void setReqCompactProfile(CachedAppOptimizer.CompactProfile reqCompactProfile) {
+        mReqCompactProfile = reqCompactProfile;
     }
 
     @GuardedBy("mProcLock")
-    int getLastCompactAction() {
-        return mLastCompactAction;
+    CachedAppOptimizer.CompactSource getReqCompactSource() {
+        return mReqCompactSource;
     }
 
     @GuardedBy("mProcLock")
-    void setLastCompactAction(int lastCompactAction) {
-        mLastCompactAction = lastCompactAction;
+    void setReqCompactSource(CachedAppOptimizer.CompactSource stat) {
+        mReqCompactSource = stat;
+    }
+
+    @GuardedBy("mProcLock")
+    void setLastOomAdjChangeReason(@OomAdjuster.OomAdjReason int reason) {
+        mLastOomAdjChangeReason = reason;
+    }
+
+    @GuardedBy("mProcLock")
+    @OomAdjuster.OomAdjReason
+    int getLastOomAdjChangeReason() {
+        return mLastOomAdjChangeReason;
+    }
+
+    @GuardedBy("mProcLock")
+    CachedAppOptimizer.CompactProfile getLastCompactProfile() {
+        if (mLastCompactProfile == null) {
+            // The first compaction won't have a previous one, so assign one to avoid crashing.
+            mLastCompactProfile = CachedAppOptimizer.CompactProfile.SOME;
+        }
+
+        return mLastCompactProfile;
+    }
+
+    @GuardedBy("mProcLock")
+    void setLastCompactProfile(CachedAppOptimizer.CompactProfile lastCompactProfile) {
+        mLastCompactProfile = lastCompactProfile;
     }
 
     @GuardedBy("mProcLock")
@@ -216,7 +250,8 @@
     @GuardedBy("mProcLock")
     void dump(PrintWriter pw, String prefix, long nowUptime) {
         pw.print(prefix); pw.print("lastCompactTime="); pw.print(mLastCompactTime);
-        pw.print(" lastCompactAction="); pw.println(mLastCompactAction);
+        pw.print(" lastCompactProfile=");
+        pw.println(mLastCompactProfile);
         pw.print(prefix);
         pw.print("hasPendingCompaction=");
         pw.print(mPendingCompact);
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index dd73cbe..854b818 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -25,20 +25,6 @@
 import static com.android.internal.R.styleable.GameModeConfig_allowGameFpsOverride;
 import static com.android.internal.R.styleable.GameModeConfig_supportsBatteryGameMode;
 import static com.android.internal.R.styleable.GameModeConfig_supportsPerformanceGameMode;
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -48,10 +34,10 @@
 import android.app.ActivityManager;
 import android.app.GameManager;
 import android.app.GameManager.GameMode;
+import android.app.GameManagerInternal;
 import android.app.GameModeInfo;
 import android.app.GameState;
 import android.app.IGameManagerService;
-import android.app.compat.PackageOverride;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -75,9 +61,7 @@
 import android.os.Message;
 import android.os.PowerManagerInternal;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.UserManager;
 import android.provider.DeviceConfig;
@@ -92,8 +76,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.compat.CompatibilityOverrideConfig;
-import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
@@ -140,10 +122,6 @@
     static final int WRITE_SETTINGS_DELAY = 10 * 1000;  // 10 seconds
     static final int LOADING_BOOST_MAX_DURATION = 5 * 1000;  // 5 seconds
 
-    static final PackageOverride COMPAT_ENABLED = new PackageOverride.Builder().setEnabled(true)
-            .build();
-    static final PackageOverride COMPAT_DISABLED = new PackageOverride.Builder().setEnabled(false)
-            .build();
     private static final String PACKAGE_NAME_MSG_KEY = "packageName";
     private static final String USER_ID_MSG_KEY = "userId";
     private static final String GAME_MODE_INTERVENTION_LIST_FILE_NAME =
@@ -156,7 +134,6 @@
     private final Handler mHandler;
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
-    private final IPlatformCompat mPlatformCompat;
     private final PowerManagerInternal mPowerManagerInternal;
     private final File mSystemDir;
     @VisibleForTesting
@@ -180,8 +157,6 @@
         mHandler = new SettingsHandler(looper);
         mPackageManager = mContext.getPackageManager();
         mUserManager = mContext.getSystemService(UserManager.class);
-        mPlatformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mSystemDir = new File(Environment.getDataDirectory(), "system");
         mSystemDir.mkdirs();
@@ -212,8 +187,6 @@
         mHandler = new SettingsHandler(looper);
         mPackageManager = mContext.getPackageManager();
         mUserManager = mContext.getSystemService(UserManager.class);
-        mPlatformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mSystemDir = new File(dataDir, "system");
         mSystemDir.mkdirs();
@@ -326,14 +299,10 @@
                     break;
                 }
                 case POPULATE_GAME_MODE_SETTINGS: {
-                    // Scan all game packages and re-enforce the configured compat mode overrides
-                    // as the DeviceConfig may have be wiped/since last reboot and we can't risk
-                    // having overrides configured for packages that no longer have any DeviceConfig
-                    // and thus any way to escape compat mode.
                     removeMessages(POPULATE_GAME_MODE_SETTINGS, msg.obj);
                     final int userId = (int) msg.obj;
                     final String[] packageNames = getInstalledGamePackageNames(userId);
-                    updateConfigsForUser(userId, packageNames);
+                    updateConfigsForUser(userId, false /*checkGamePackage*/, packageNames);
                     break;
                 }
                 case SET_GAME_STATE: {
@@ -402,7 +371,8 @@
         @Override
         public void onPropertiesChanged(Properties properties) {
             final String[] packageNames = properties.getKeyset().toArray(new String[0]);
-            updateConfigsForUser(ActivityManager.getCurrentUser(), packageNames);
+            updateConfigsForUser(ActivityManager.getCurrentUser(), true /*checkGamePackage*/,
+                    packageNames);
         }
 
         @Override
@@ -411,39 +381,6 @@
         }
     }
 
-    // Turn the raw string to the corresponding CompatChange id.
-    static long getCompatChangeId(String raw) {
-        switch (raw) {
-            case "0.3":
-                return DOWNSCALE_30;
-            case "0.35":
-                return DOWNSCALE_35;
-            case "0.4":
-                return DOWNSCALE_40;
-            case "0.45":
-                return DOWNSCALE_45;
-            case "0.5":
-                return DOWNSCALE_50;
-            case "0.55":
-                return DOWNSCALE_55;
-            case "0.6":
-                return DOWNSCALE_60;
-            case "0.65":
-                return DOWNSCALE_65;
-            case "0.7":
-                return DOWNSCALE_70;
-            case "0.75":
-                return DOWNSCALE_75;
-            case "0.8":
-                return DOWNSCALE_80;
-            case "0.85":
-                return DOWNSCALE_85;
-            case "0.9":
-                return DOWNSCALE_90;
-        }
-        return 0;
-    }
-
     public enum FrameRate {
         FPS_DEFAULT(0),
         FPS_30(30),
@@ -553,7 +490,9 @@
 
         private static final String GAME_MODE_CONFIG_NODE_NAME = "game-mode-config";
         private final String mPackageName;
-        private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs;
+        private final Object mModeConfigLock = new Object();
+        @GuardedBy("mModeConfigLock")
+        private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs = new ArrayMap<>();
         private boolean mPerfModeOptedIn;
         private boolean mBatteryModeOptedIn;
         private boolean mAllowDownscale;
@@ -562,7 +501,6 @@
 
         GamePackageConfiguration(String packageName, int userId) {
             mPackageName = packageName;
-            mModeConfigs = new ArrayMap<>();
             try {
                 final ApplicationInfo ai = mPackageManager.getApplicationInfoAsUser(packageName,
                         PackageManager.GET_META_DATA, userId);
@@ -647,6 +585,13 @@
             return xmlFound;
         }
 
+        GameModeConfiguration getOrAddDefaultGameModeConfiguration(int gameMode) {
+            synchronized (mModeConfigLock) {
+                mModeConfigs.putIfAbsent(gameMode, new GameModeConfiguration(gameMode));
+                return mModeConfigs.get(gameMode);
+            }
+        }
+
         /**
          * GameModeConfiguration contains all the values for all the interventions associated with
          * a game mode.
@@ -657,17 +602,26 @@
             public static final String MODE_KEY = "mode";
             public static final String SCALING_KEY = "downscaleFactor";
             public static final String FPS_KEY = "fps";
-            public static final String DEFAULT_SCALING = "1.0";
-            public static final String DEFAULT_FPS = "";
             public static final String ANGLE_KEY = "useAngle";
             public static final String LOADING_BOOST_KEY = "loadingBoost";
 
+            public static final float DEFAULT_SCALING = -1f;
+            public static final String DEFAULT_FPS = "";
+            public static final boolean DEFAULT_USE_ANGLE = false;
+            public static final int DEFAULT_LOADING_BOOST_DURATION = -1;
+
             private final @GameMode int mGameMode;
-            private String mScaling;
-            private String mFps;
+            private float mScaling = DEFAULT_SCALING;
+            private String mFps = DEFAULT_FPS;
             private final boolean mUseAngle;
             private final int mLoadingBoostDuration;
 
+            GameModeConfiguration(int gameMode) {
+                mGameMode = gameMode;
+                mUseAngle = DEFAULT_USE_ANGLE;
+                mLoadingBoostDuration = DEFAULT_LOADING_BOOST_DURATION;
+            }
+
             GameModeConfiguration(KeyValueListParser parser) {
                 mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED);
                 // isGameModeOptedIn() returns if an app will handle all of the changes necessary
@@ -675,7 +629,7 @@
                 // GameManagerService) will not do anything for the app (like window scaling or
                 // using ANGLE).
                 mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode)
-                        ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING);
+                        ? DEFAULT_SCALING : parser.getFloat(SCALING_KEY, DEFAULT_SCALING);
 
                 mFps = mAllowFpsOverride && !willGamePerformOptimizations(mGameMode)
                         ? parser.getString(FPS_KEY, DEFAULT_FPS) : DEFAULT_FPS;
@@ -684,21 +638,22 @@
                 // - The app has not opted in to performing the work itself AND
                 // - The Phenotype config has enabled it.
                 mUseAngle = mAllowAngle && !willGamePerformOptimizations(mGameMode)
-                        && parser.getBoolean(ANGLE_KEY, false);
+                        && parser.getBoolean(ANGLE_KEY, DEFAULT_USE_ANGLE);
 
-                mLoadingBoostDuration = willGamePerformOptimizations(mGameMode) ? -1
-                        : parser.getInt(LOADING_BOOST_KEY, -1);
+                mLoadingBoostDuration = willGamePerformOptimizations(mGameMode)
+                        ? DEFAULT_LOADING_BOOST_DURATION
+                        : parser.getInt(LOADING_BOOST_KEY, DEFAULT_LOADING_BOOST_DURATION);
             }
 
             public int getGameMode() {
                 return mGameMode;
             }
 
-            public String getScaling() {
+            public synchronized float getScaling() {
                 return mScaling;
             }
 
-            public int getFps() {
+            public synchronized int getFps() {
                 return GameManagerService.getFpsInt(mFps);
             }
 
@@ -710,15 +665,15 @@
                 return mLoadingBoostDuration;
             }
 
-            public void setScaling(String scaling) {
+            public synchronized void setScaling(float scaling) {
                 mScaling = scaling;
             }
 
-            public void setFpsStr(String fpsStr) {
+            public synchronized void setFpsStr(String fpsStr) {
                 mFps = fpsStr;
             }
 
-            public boolean isValid() {
+            public boolean isActive() {
                 return (mGameMode == GameManager.GAME_MODE_STANDARD
                         || mGameMode == GameManager.GAME_MODE_PERFORMANCE
                         || mGameMode == GameManager.GAME_MODE_BATTERY)
@@ -733,13 +688,6 @@
                         + mUseAngle + ",Fps:" + mFps + ",Loading Boost Duration:"
                         + mLoadingBoostDuration + "]";
             }
-
-            /**
-             * Get the corresponding compat change id for the current scaling string.
-             */
-            public long getCompatChangeId() {
-                return GameManagerService.getCompatChangeId(mScaling);
-            }
         }
 
         public String getPackageName() {
@@ -761,8 +709,10 @@
 
         private int getAvailableGameModesBitfield() {
             int field = 0;
-            for (final int mode : mModeConfigs.keySet()) {
-                field |= modeToBitmask(mode);
+            synchronized (mModeConfigLock) {
+                for (final int mode : mModeConfigs.keySet()) {
+                    field |= modeToBitmask(mode);
+                }
             }
             if (mBatteryModeOptedIn) {
                 field |= modeToBitmask(GameManager.GAME_MODE_BATTERY);
@@ -803,27 +753,43 @@
          * @return The package's GameModeConfiguration for the provided mode or null if absent
          */
         public GameModeConfiguration getGameModeConfiguration(@GameMode int gameMode) {
-            return mModeConfigs.get(gameMode);
+            synchronized (mModeConfigLock) {
+                return mModeConfigs.get(gameMode);
+            }
         }
 
         /**
-         * Insert a new GameModeConfiguration
+         * Inserts a new GameModeConfiguration
          */
         public void addModeConfig(GameModeConfiguration config) {
-            if (config.isValid()) {
-                mModeConfigs.put(config.getGameMode(), config);
+            if (config.isActive()) {
+                synchronized (mModeConfigLock) {
+                    mModeConfigs.put(config.getGameMode(), config);
+                }
             } else {
-                Slog.w(TAG, "Invalid game mode config for "
+                Slog.w(TAG, "Attempt to add inactive game mode config for "
                         + mPackageName + ":" + config.toString());
             }
         }
 
-        public boolean isValid() {
-            return mModeConfigs.size() > 0 || mBatteryModeOptedIn || mPerfModeOptedIn;
+        public boolean isActive() {
+            synchronized (mModeConfigLock) {
+                return mModeConfigs.size() > 0 || mBatteryModeOptedIn || mPerfModeOptedIn;
+            }
         }
 
         public String toString() {
-            return "[Name:" + mPackageName + " Modes: " + mModeConfigs.toString() + "]";
+            synchronized (mModeConfigLock) {
+                return "[Name:" + mPackageName + " Modes: " + mModeConfigs.toString() + "]";
+            }
+        }
+    }
+
+    private final class LocalService extends GameManagerInternal {
+        @Override
+        public float getResolutionScalingFactor(String packageName, int userId) {
+            final int gameMode = getGameModeFromSettings(packageName, userId);
+            return getResolutionScalingFactorInternal(packageName, gameMode, userId);
         }
     }
 
@@ -837,13 +803,13 @@
 
         public Lifecycle(Context context) {
             super(context);
+            mService = new GameManagerService(context);
         }
 
         @Override
         public void onStart() {
-            final Context context = getContext();
-            mService = new GameManagerService(context);
             publishBinderService(Context.GAME_SERVICE, mService);
+            mService.publishLocalService();
             mService.registerDeviceConfigListener();
             mService.registerPackageReceiver();
         }
@@ -894,15 +860,7 @@
     }
 
     private @GameMode int[] getAvailableGameModesUnchecked(String packageName) {
-        GamePackageConfiguration config = null;
-        synchronized (mOverrideConfigLock) {
-            config = mOverrideConfigs.get(packageName);
-        }
-        if (config == null) {
-            synchronized (mDeviceConfigLock) {
-                config = mConfigs.get(packageName);
-            }
-        }
+        final GamePackageConfiguration config = getConfig(packageName);
         if (config == null) {
             return new int[]{};
         }
@@ -933,8 +891,8 @@
     private @GameMode int getGameModeFromSettings(String packageName, @UserIdInt int userId) {
         synchronized (mLock) {
             if (!mSettings.containsKey(userId)) {
-                Slog.w(TAG, "User ID '" + userId + "' does not have a Game Mode"
-                        + " selected for package: '" + packageName + "'");
+                Slog.d(TAG, "User ID '" + userId + "' does not have a Game Mode"
+                            + " selected for package: '" + packageName + "'");
                 return GameManager.GAME_MODE_UNSUPPORTED;
             }
 
@@ -1055,19 +1013,19 @@
         if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
             return false;
         }
-
+        final GamePackageConfiguration config;
         synchronized (mDeviceConfigLock) {
-            final GamePackageConfiguration config = mConfigs.get(packageName);
+            config = mConfigs.get(packageName);
             if (config == null) {
                 return false;
             }
-            GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
-                    config.getGameModeConfiguration(gameMode);
-            if (gameModeConfiguration == null) {
-                return false;
-            }
-            return gameModeConfiguration.getUseAngle();
         }
+        GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
+                config.getGameModeConfiguration(gameMode);
+        if (gameModeConfiguration == null) {
+            return false;
+        }
+        return gameModeConfiguration.getUseAngle();
     }
 
     /**
@@ -1082,19 +1040,19 @@
         if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
             return -1;
         }
-
+        final GamePackageConfiguration config;
         synchronized (mDeviceConfigLock) {
-            final GamePackageConfiguration config = mConfigs.get(packageName);
-            if (config == null) {
-                return -1;
-            }
-            GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
-                    config.getGameModeConfiguration(gameMode);
-            if (gameModeConfiguration == null) {
-                return -1;
-            }
-            return gameModeConfiguration.getLoadingBoostDuration();
+            config = mConfigs.get(packageName);
         }
+        if (config == null) {
+            return -1;
+        }
+        GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
+                config.getGameModeConfiguration(gameMode);
+        if (gameModeConfiguration == null) {
+            return -1;
+        }
+        return gameModeConfiguration.getLoadingBoostDuration();
     }
 
     /**
@@ -1159,6 +1117,66 @@
         mGameServiceController.setGameServiceProvider(packageName);
     }
 
+
+    /**
+     * Updates the resolution scaling factor for the package's target game mode and activates it.
+     *
+     * @param scalingFactor enable scaling override over any other compat scaling if positive,
+     *                      or disable the override otherwise
+     * @throws SecurityException        if caller doesn't have
+     *                                  {@link android.Manifest.permission#MANAGE_GAME_MODE}
+     *                                  permission.
+     * @throws IllegalArgumentException if the user ID provided doesn't exist.
+     */
+    @Override
+    @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+    public void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor,
+            int userId) throws SecurityException, IllegalArgumentException {
+        checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+        synchronized (mLock) {
+            if (!mSettings.containsKey(userId)) {
+                throw new IllegalArgumentException("User " + userId + " wasn't started");
+            }
+        }
+        setGameModeConfigOverride(packageName, userId, gameMode, null /*fpsStr*/,
+                Float.toString(scalingFactor));
+    }
+
+    /**
+     * Gets the resolution scaling factor for the package's target game mode.
+     *
+     * @return scaling factor for the game mode if exists or negative value otherwise.
+     * @throws SecurityException        if caller doesn't have
+     *                                  {@link android.Manifest.permission#MANAGE_GAME_MODE}
+     *                                  permission.
+     * @throws IllegalArgumentException if the user ID provided doesn't exist.
+     */
+    @Override
+    @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+    public float getResolutionScalingFactor(String packageName, int gameMode, int userId)
+            throws SecurityException, IllegalArgumentException {
+        checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+        synchronized (mLock) {
+            if (!mSettings.containsKey(userId)) {
+                throw new IllegalArgumentException("User " + userId + " wasn't started");
+            }
+        }
+        return getResolutionScalingFactorInternal(packageName, gameMode, userId);
+    }
+
+    float getResolutionScalingFactorInternal(String packageName, int gameMode, int userId) {
+        final GamePackageConfiguration packageConfig = getConfig(packageName);
+        if (packageConfig == null) {
+            return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+        }
+        final GamePackageConfiguration.GameModeConfiguration modeConfig =
+                packageConfig.getGameModeConfiguration(gameMode);
+        if (modeConfig != null) {
+            return modeConfig.getScaling();
+        }
+        return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+    }
+
     /**
      * Notified when boot is completed.
      */
@@ -1235,28 +1253,6 @@
     }
 
     /**
-     * @hide
-     */
-    @VisibleForTesting
-    public void disableCompatScale(String packageName) {
-        final long uid = Binder.clearCallingIdentity();
-        try {
-            Slog.i(TAG, "Disabling downscale for " + packageName);
-            final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
-            overrides.put(DOWNSCALED, COMPAT_DISABLED);
-            final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
-                    overrides);
-            try {
-                mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(uid);
-        }
-    }
-
-    /**
      * Remove frame rate override due to mode switch
      */
     private void resetFps(String packageName, @UserIdInt int userId) {
@@ -1269,60 +1265,6 @@
         }
     }
 
-    private void enableCompatScale(String packageName, long scaleId) {
-        final long uid = Binder.clearCallingIdentity();
-        try {
-            Slog.i(TAG, "Enabling downscale: " + scaleId + " for " + packageName);
-            final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
-            overrides.put(DOWNSCALED, COMPAT_ENABLED);
-            overrides.put(DOWNSCALE_30, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_35, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_40, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_45, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_50, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_55, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_60, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_65, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_70, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_75, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_80, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_85, COMPAT_DISABLED);
-            overrides.put(DOWNSCALE_90, COMPAT_DISABLED);
-            overrides.put(scaleId, COMPAT_ENABLED);
-            final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
-                    overrides);
-            try {
-                mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(uid);
-        }
-    }
-
-    private void updateCompatModeDownscale(GamePackageConfiguration packageConfig,
-            String packageName, @GameMode int gameMode) {
-
-        if (DEBUG) {
-            Slog.v(TAG, dumpDeviceConfigs());
-        }
-        final GamePackageConfiguration.GameModeConfiguration modeConfig =
-                packageConfig.getGameModeConfiguration(gameMode);
-        if (modeConfig == null) {
-            Slog.i(TAG, "Game mode " + gameMode + " not found for " + packageName);
-            return;
-        }
-        long scaleId = modeConfig.getCompatChangeId();
-        if (scaleId == 0) {
-            Slog.w(TAG, "Invalid downscaling change id " + scaleId + " for "
-                    + packageName);
-            return;
-        }
-
-        enableCompatScale(packageName, scaleId);
-    }
-
     private int modeToBitmask(@GameMode int gameMode) {
         return (1 << gameMode);
     }
@@ -1360,31 +1302,17 @@
             @GameMode int gameMode, @UserIdInt int userId) {
         if (gameMode == GameManager.GAME_MODE_STANDARD
                 || gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
-            disableCompatScale(packageName);
             resetFps(packageName, userId);
             return;
         }
-        GamePackageConfiguration packageConfig = null;
-
-        synchronized (mOverrideConfigLock) {
-            packageConfig = mOverrideConfigs.get(packageName);
-        }
-
+        final GamePackageConfiguration packageConfig = getConfig(packageName);
         if (packageConfig == null) {
-            synchronized (mDeviceConfigLock) {
-                packageConfig = mConfigs.get(packageName);
-            }
-        }
-
-        if (packageConfig == null) {
-            disableCompatScale(packageName);
             Slog.v(TAG, "Package configuration not found for " + packageName);
             return;
         }
         if (packageConfig.willGamePerformOptimizations(gameMode)) {
             return;
         }
-        updateCompatModeDownscale(packageConfig, packageName, gameMode);
         updateFps(packageConfig, packageName, gameMode, userId);
         updateUseAngle(packageName, gameMode);
     }
@@ -1404,34 +1332,31 @@
             }
         }
         // Adding override game mode configuration of the given package name
+        GamePackageConfiguration overrideConfig;
         synchronized (mOverrideConfigLock) {
             // look for the existing override GamePackageConfiguration
-            GamePackageConfiguration overrideConfig = mOverrideConfigs.get(packageName);
+            overrideConfig = mOverrideConfigs.get(packageName);
             if (overrideConfig == null) {
                 overrideConfig = new GamePackageConfiguration(packageName, userId);
                 mOverrideConfigs.put(packageName, overrideConfig);
             }
-
-            // modify GameModeConfiguration intervention settings
-            GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
-                    overrideConfig.getGameModeConfiguration(gameMode);
-
-            if (fpsStr != null) {
-                overrideModeConfig.setFpsStr(fpsStr);
-            } else {
-                overrideModeConfig.setFpsStr(
-                        GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
-            }
-            if (scaling != null) {
-                overrideModeConfig.setScaling(scaling);
-            } else {
-                overrideModeConfig.setScaling(
-                        GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING);
-            }
-            Slog.i(TAG, "Package Name: " + packageName
-                    + " FPS: " + String.valueOf(overrideModeConfig.getFps())
-                    + " Scaling: " + overrideModeConfig.getScaling());
         }
+        // modify GameModeConfiguration intervention settings
+        GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
+                overrideConfig.getOrAddDefaultGameModeConfiguration(gameMode);
+
+        if (fpsStr != null) {
+            overrideModeConfig.setFpsStr(fpsStr);
+        } else {
+            overrideModeConfig.setFpsStr(
+                    GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
+        }
+        if (scaling != null) {
+            overrideModeConfig.setScaling(Float.parseFloat(scaling));
+        }
+        Slog.i(TAG, "Package Name: " + packageName
+                + " FPS: " + String.valueOf(overrideModeConfig.getFps())
+                + " Scaling: " + overrideModeConfig.getScaling());
         setGameMode(packageName, gameMode, userId);
     }
 
@@ -1477,7 +1402,7 @@
             }
 
             // If the game mode to reset is the only mode other than standard mode,
-            // The override config is removed.
+            // the override config is removed.
             if (modes.length <= 2) {
                 synchronized (mOverrideConfigLock) {
                     mOverrideConfigs.remove(packageName);
@@ -1497,15 +1422,7 @@
         // If not, set the game mode to standard
         int gameMode = getGameMode(packageName, userId);
 
-        GamePackageConfiguration config = null;
-        synchronized (mOverrideConfigLock) {
-            config = mOverrideConfigs.get(packageName);
-        }
-        if (config == null) {
-            synchronized (mDeviceConfigLock) {
-                config = mConfigs.get(packageName);
-            }
-        }
+        final GamePackageConfiguration config = getConfig(packageName);
         final int newGameMode = getNewGameMode(gameMode, config);
         if (gameMode != newGameMode) {
             setGameMode(packageName, GameManager.GAME_MODE_STANDARD, userId);
@@ -1544,18 +1461,8 @@
      * Returns the string listing all the interventions currently set to a game.
      */
     public String getInterventionList(String packageName) {
-        GamePackageConfiguration packageConfig = null;
-        synchronized (mOverrideConfigLock) {
-            packageConfig = mOverrideConfigs.get(packageName);
-        }
-
-        if (packageConfig == null) {
-            synchronized (mDeviceConfigLock) {
-                packageConfig = mConfigs.get(packageName);
-            }
-        }
-
-        StringBuilder listStrSb = new StringBuilder();
+        final GamePackageConfiguration packageConfig = getConfig(packageName);
+        final StringBuilder listStrSb = new StringBuilder();
         if (packageConfig == null) {
             listStrSb.append("\n No intervention found for package ")
                     .append(packageName);
@@ -1570,20 +1477,27 @@
      * @hide
      */
     @VisibleForTesting
-    void updateConfigsForUser(@UserIdInt int userId, String... packageNames) {
+    void updateConfigsForUser(@UserIdInt int userId, boolean checkGamePackage,
+            String... packageNames) {
+        if (checkGamePackage) {
+            packageNames = Arrays.stream(packageNames).filter(
+                    p -> isPackageGame(p, userId)).toArray(String[]::new);
+        }
         try {
             synchronized (mDeviceConfigLock) {
                 for (final String packageName : packageNames) {
                     final GamePackageConfiguration config =
                             new GamePackageConfiguration(packageName, userId);
-                    if (config.isValid()) {
+                    if (config.isActive()) {
                         if (DEBUG) {
                             Slog.i(TAG, "Adding config: " + config.toString());
                         }
                         mConfigs.put(packageName, config);
                     } else {
-                        Slog.w(TAG, "Invalid package config for "
-                                + config.getPackageName() + ":" + config.toString());
+                        if (DEBUG) {
+                            Slog.w(TAG, "Inactive package config for "
+                                    + config.getPackageName() + ":" + config.toString());
+                        }
                         mConfigs.remove(packageName);
                     }
                 }
@@ -1613,7 +1527,7 @@
                 }
             }
         } catch (Exception e) {
-            Slog.e(TAG, "Failed to update compat modes for user " + userId + ": " + e);
+            Slog.e(TAG, "Failed to update configs for user " + userId + ": " + e);
         }
 
         final Message msg = mHandler.obtainMessage(WRITE_GAME_MODE_INTERVENTION_LIST_FILE);
@@ -1664,7 +1578,7 @@
                     final int useAngle = gameModeConfiguration.getUseAngle() ? 1 : 0;
                     sb.append(TextUtils.formatSimple("angle=%d", useAngle));
                     sb.append(",");
-                    final String scaling = gameModeConfiguration.getScaling();
+                    final float scaling = gameModeConfiguration.getScaling();
                     sb.append("scaling=");
                     sb.append(scaling);
                     sb.append(",");
@@ -1761,17 +1675,9 @@
                     }
                     switch (intent.getAction()) {
                         case ACTION_PACKAGE_ADDED:
-                            updateConfigsForUser(userId, packageName);
+                            updateConfigsForUser(userId, true /*checkGamePackage*/, packageName);
                             break;
                         case ACTION_PACKAGE_REMOVED:
-                            disableCompatScale(packageName);
-                            // If EXTRA_REPLACING is true, it means there will be an
-                            // ACTION_PACKAGE_ADDED triggered after this because this
-                            // is an updated package that gets installed. Hence, disable
-                            // resolution downscaling effort but avoid removing the server
-                            // or commandline overriding configurations because those will
-                            // not change but the package game mode configurations may change
-                            // which may opt in and/or opt out some game mode configurations.
                             if (!intent.getBooleanExtra(EXTRA_REPLACING, false)) {
                                 synchronized (mOverrideConfigLock) {
                                     mOverrideConfigs.remove(packageName);
@@ -1803,6 +1709,10 @@
         mDeviceConfigListener = new DeviceConfigListener();
     }
 
+    private void publishLocalService() {
+        LocalServices.addService(GameManagerInternal.class, new LocalService());
+    }
+
     private String dumpDeviceConfigs() {
         StringBuilder out = new StringBuilder();
         for (String key : mConfigs.keySet()) {
diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java
index 470c320..487d19a 100644
--- a/services/core/java/com/android/server/app/GameManagerShellCommand.java
+++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java
@@ -16,21 +16,6 @@
 
 package com.android.server.app;
 
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
-
 import android.app.ActivityManager;
 import android.app.GameManager;
 import android.app.IGameManagerService;
@@ -39,7 +24,6 @@
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.ShellCommand;
-import android.util.ArraySet;
 
 import java.io.PrintWriter;
 import java.util.Locale;
@@ -53,23 +37,6 @@
 
     public GameManagerShellCommand() {}
 
-    private static final ArraySet<Long> DOWNSCALE_CHANGE_IDS = new ArraySet<>(new Long[]{
-            DOWNSCALED,
-            DOWNSCALE_90,
-            DOWNSCALE_85,
-            DOWNSCALE_80,
-            DOWNSCALE_75,
-            DOWNSCALE_70,
-            DOWNSCALE_65,
-            DOWNSCALE_60,
-            DOWNSCALE_55,
-            DOWNSCALE_50,
-            DOWNSCALE_45,
-            DOWNSCALE_40,
-            DOWNSCALE_35,
-            DOWNSCALE_30,
-    });
-
     @Override
     public int onCommand(String cmd) {
         if (cmd == null) {
@@ -212,11 +179,15 @@
                 case "--downscale":
                     if (downscaleRatio == null) {
                         downscaleRatio = getNextArgRequired();
-                        if (downscaleRatio != null
-                                && GameManagerService.getCompatChangeId(downscaleRatio) == 0
-                                && !downscaleRatio.equals("disable")) {
-                            pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
-                            return -1;
+                        if ("disable".equals(downscaleRatio)) {
+                            downscaleRatio = "-1";
+                        } else {
+                            try {
+                                Float.parseFloat(downscaleRatio);
+                            } catch (NumberFormatException e) {
+                                pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
+                                return -1;
+                            }
                         }
                     } else {
                         pw.println("Duplicate option '" + option + "'");
@@ -249,40 +220,16 @@
         final GameManagerService gameManagerService = (GameManagerService)
                 ServiceManager.getService(Context.GAME_SERVICE);
 
-        boolean batteryModeSupported = false;
-        boolean perfModeSupported = false;
-        int [] modes = gameManagerService.getAvailableGameModes(packageName);
-
-        for (int mode : modes) {
-            if (mode == GameManager.GAME_MODE_PERFORMANCE) {
-                perfModeSupported = true;
-            } else if (mode == GameManager.GAME_MODE_BATTERY) {
-                batteryModeSupported = true;
-            }
-        }
-
         switch (gameMode.toLowerCase(Locale.getDefault())) {
             case "2":
             case "performance":
-                if (perfModeSupported) {
-                    gameManagerService.setGameModeConfigOverride(packageName, userId,
-                            GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
-                } else {
-                    pw.println("Game mode: " + gameMode + " not supported by "
-                            + packageName);
-                    return -1;
-                }
+                gameManagerService.setGameModeConfigOverride(packageName, userId,
+                        GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
                 break;
             case "3":
             case "battery":
-                if (batteryModeSupported) {
-                    gameManagerService.setGameModeConfigOverride(packageName, userId,
-                            GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
-                } else {
-                    pw.println("Game mode: " + gameMode + " not supported by "
-                            + packageName);
-                    return -1;
-                }
+                gameManagerService.setGameModeConfigOverride(packageName, userId,
+                        GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
                 break;
             default:
                 pw.println("Invalid game mode: " + gameMode);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7bef6d5..a5bcb05 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -217,7 +217,7 @@
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.function.Consumer;
 
-public class AppOpsService extends IAppOpsService.Stub {
+public class AppOpsService extends IAppOpsService.Stub implements PersistenceScheduler {
     static final String TAG = "AppOps";
     static final boolean DEBUG = false;
 
@@ -402,6 +402,9 @@
     /** Package Manager internal. Access via {@link #getPackageManagerInternal()} */
     private @Nullable PackageManagerInternal mPackageManagerInternal;
 
+    /** Interface for app-op modes.*/
+    @VisibleForTesting AppOpsServiceInterface mAppOpsServiceInterface;
+
     /**
      * An unsynchronized pool of {@link OpEventProxyInfo} objects.
      */
@@ -558,7 +561,6 @@
         public boolean pendingAppWidgetVisible;
 
         public ArrayMap<String, Ops> pkgOps;
-        public SparseIntArray opModes;
 
         // true indicates there is an interested observer, false there isn't but it has such an op
         public SparseBooleanArray foregroundOps;
@@ -569,15 +571,43 @@
         }
 
         public void clear() {
+            mAppOpsServiceInterface.removeUid(uid);
+            if (pkgOps != null) {
+                for (String packageName : pkgOps.keySet()) {
+                    mAppOpsServiceInterface.removePackage(packageName);
+                }
+            }
             pkgOps = null;
-            opModes = null;
         }
 
         public boolean isDefault() {
+            boolean areAllPackageModesDefault = true;
+            if (pkgOps != null) {
+                for (String packageName : pkgOps.keySet()) {
+                    if (!mAppOpsServiceInterface.arePackageModesDefault(packageName)) {
+                        areAllPackageModesDefault = false;
+                        break;
+                    }
+                }
+            }
             return (pkgOps == null || pkgOps.isEmpty())
-                    && (opModes == null || opModes.size() <= 0)
                     && (state == UID_STATE_CACHED
-                    && (pendingState == UID_STATE_CACHED));
+                    && (pendingState == UID_STATE_CACHED))
+                    && (mAppOpsServiceInterface.areUidModesDefault(uid)
+                    && areAllPackageModesDefault);
+        }
+
+        // Functions for uid mode access and manipulation.
+        public SparseIntArray getNonDefaultUidModes() {
+            return mAppOpsServiceInterface.getNonDefaultUidModes(uid);
+        }
+
+        public int getUidMode(int op) {
+            return mAppOpsServiceInterface.getUidMode(uid, op);
+        }
+
+        public boolean setUidMode(int op, int mode) {
+            return mAppOpsServiceInterface.setUidMode(uid, op, mode);
         }
 
         int evalMode(int op, int mode) {
@@ -647,21 +677,20 @@
         public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
             SparseBooleanArray which = null;
             hasForegroundWatchers = false;
-            if (opModes != null) {
-                for (int i = opModes.size() - 1; i >= 0; i--) {
-                    if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
-                        if (which == null) {
-                            which = new SparseBooleanArray();
-                        }
-                        evalForegroundWatchers(opModes.keyAt(i), watchers, which);
+            final SparseIntArray opModes = getNonDefaultUidModes();
+            for (int i = opModes.size() - 1; i >= 0; i--) {
+                if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
+                    if (which == null) {
+                        which = new SparseBooleanArray();
                     }
+                    evalForegroundWatchers(opModes.keyAt(i), watchers, which);
                 }
             }
             if (pkgOps != null) {
                 for (int i = pkgOps.size() - 1; i >= 0; i--) {
                     Ops ops = pkgOps.valueAt(i);
                     for (int j = ops.size() - 1; j >= 0; j--) {
-                        if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) {
+                        if (ops.valueAt(j).getMode() == AppOpsManager.MODE_FOREGROUND) {
                             if (which == null) {
                                 which = new SparseBooleanArray();
                             }
@@ -1451,8 +1480,6 @@
         final UidState uidState;
         final @NonNull String packageName;
 
-        private @Mode int mode;
-
         /** attributionTag -> AttributedOp */
         final ArrayMap<String, AttributedOp> mAttributions = new ArrayMap<>(1);
 
@@ -1461,15 +1488,17 @@
             this.uid = uid;
             this.uidState = uidState;
             this.packageName = packageName;
-            this.mode = AppOpsManager.opToDefaultMode(op);
         }
 
-        int getMode() {
-            return mode;
+        @Mode int getMode() {
+            return mAppOpsServiceInterface.getPackageMode(packageName, this.op);
+        }
+        void setMode(@Mode int mode) {
+            mAppOpsServiceInterface.setPackageMode(packageName, this.op, mode);
         }
 
         int evalMode() {
-            return uidState.evalMode(op, mode);
+            return uidState.evalMode(op, getMode());
         }
 
         void removeAttributionsWithNoTime() {
@@ -1503,7 +1532,7 @@
                         mAttributions.valueAt(i).createAttributedOpEntryLocked());
             }
 
-            return new OpEntry(op, mode, attributionEntries);
+            return new OpEntry(op, getMode(), attributionEntries);
         }
 
         @NonNull OpEntry createSingleAttributionEntryLocked(@Nullable String attributionTag) {
@@ -1518,7 +1547,7 @@
                 }
             }
 
-            return new OpEntry(op, mode, attributionEntries);
+            return new OpEntry(op, getMode(), attributionEntries);
         }
 
         boolean isRunning() {
@@ -1775,6 +1804,7 @@
 
     public AppOpsService(File storagePath, Handler handler, Context context) {
         mContext = context;
+        mAppOpsServiceInterface = new LegacyAppOpsServiceInterfaceImpl(this, this);
 
         LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
         mFile = new AtomicFile(storagePath, "appops");
@@ -1815,7 +1845,7 @@
                     if (uidState == null || uidState.pkgOps == null) {
                         return;
                     }
-
+                    mAppOpsServiceInterface.removePackage(pkgName);
                     Ops removedOps = uidState.pkgOps.remove(pkgName);
                     if (removedOps != null) {
                         scheduleFastWriteLocked();
@@ -2037,25 +2067,27 @@
                 return;
             }
 
-            Ops ops = null;
+            Ops removedOps = null;
 
             // Remove any package state if such.
             if (uidState.pkgOps != null) {
-                ops = uidState.pkgOps.remove(packageName);
+                removedOps = uidState.pkgOps.remove(packageName);
+                mAppOpsServiceInterface.removePackage(packageName);
             }
 
             // If we just nuked the last package state check if the UID is valid.
-            if (ops != null && uidState.pkgOps.isEmpty()
+            if (removedOps != null && uidState.pkgOps.isEmpty()
                     && getPackagesForUid(uid).length <= 0) {
+                uidState.clear();
                 mUidStates.remove(uid);
             }
 
-            if (ops != null) {
+            if (removedOps != null) {
                 scheduleFastWriteLocked();
 
-                final int numOps = ops.size();
+                final int numOps = removedOps.size();
                 for (int opNum = 0; opNum < numOps; opNum++) {
-                    final Op op = ops.valueAt(opNum);
+                    final Op op = removedOps.valueAt(opNum);
 
                     final int numAttributions = op.mAttributions.size();
                     for (int attributionNum = 0; attributionNum < numAttributions;
@@ -2080,6 +2112,7 @@
     public void uidRemoved(int uid) {
         synchronized (this) {
             if (mUidStates.indexOfKey(uid) >= 0) {
+                mUidStates.get(uid).clear();
                 mUidStates.remove(uid);
                 scheduleFastWriteLocked();
             }
@@ -2185,12 +2218,11 @@
 
     private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
         ArrayList<AppOpsManager.OpEntry> resOps = null;
-        final long elapsedNow = SystemClock.elapsedRealtime();
         if (ops == null) {
             resOps = new ArrayList<>();
             for (int j=0; j<pkgOps.size(); j++) {
                 Op curOp = pkgOps.valueAt(j);
-                resOps.add(getOpEntryForResult(curOp, elapsedNow));
+                resOps.add(getOpEntryForResult(curOp));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
@@ -2199,7 +2231,7 @@
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(getOpEntryForResult(curOp, elapsedNow));
+                    resOps.add(getOpEntryForResult(curOp));
                 }
             }
         }
@@ -2209,11 +2241,12 @@
     @Nullable
     private ArrayList<AppOpsManager.OpEntry> collectUidOps(@NonNull UidState uidState,
             @Nullable int[] ops) {
-        if (uidState.opModes == null) {
+        final SparseIntArray opModes = uidState.getNonDefaultUidModes();
+        if (opModes == null) {
             return null;
         }
 
-        int opModeCount = uidState.opModes.size();
+        int opModeCount = opModes.size();
         if (opModeCount == 0) {
             return null;
         }
@@ -2221,25 +2254,24 @@
         if (ops == null) {
             resOps = new ArrayList<>();
             for (int i = 0; i < opModeCount; i++) {
-                int code = uidState.opModes.keyAt(i);
-                resOps.add(new OpEntry(code, uidState.opModes.get(code), Collections.emptyMap()));
+                int code = opModes.keyAt(i);
+                resOps.add(new OpEntry(code, opModes.get(code), Collections.emptyMap()));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
                 int code = ops[j];
-                if (uidState.opModes.indexOfKey(code) >= 0) {
+                if (opModes.indexOfKey(code) >= 0) {
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(new OpEntry(code, uidState.opModes.get(code),
-                            Collections.emptyMap()));
+                    resOps.add(new OpEntry(code, opModes.get(code), Collections.emptyMap()));
                 }
             }
         }
         return resOps;
     }
 
-    private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
+    private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op) {
         return op.createEntryLocked();
     }
 
@@ -2484,15 +2516,18 @@
             Ops ops = getOpsLocked(uid, packageName, null, false, null, /* edit */ false);
             if (ops != null) {
                 ops.remove(op.op);
+                op.setMode(AppOpsManager.opToDefaultMode(op.op));
                 if (ops.size() <= 0) {
                     UidState uidState = ops.uidState;
                     ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
                     if (pkgOps != null) {
                         pkgOps.remove(ops.packageName);
+                        mAppOpsServiceInterface.removePackage(ops.packageName);
                         if (pkgOps.isEmpty()) {
                             uidState.pkgOps = null;
                         }
                         if (uidState.isDefault()) {
+                            uidState.clear();
                             mUidStates.remove(uid);
                         }
                     }
@@ -2548,33 +2583,18 @@
                 if (mode == defaultMode) {
                     return;
                 }
-                previousMode = MODE_DEFAULT;
                 uidState = new UidState(uid);
-                uidState.opModes = new SparseIntArray();
-                uidState.opModes.put(code, mode);
                 mUidStates.put(uid, uidState);
-                scheduleWriteLocked();
-            } else if (uidState.opModes == null) {
-                previousMode = MODE_DEFAULT;
-                if (mode != defaultMode) {
-                    uidState.opModes = new SparseIntArray();
-                    uidState.opModes.put(code, mode);
-                    scheduleWriteLocked();
-                }
+            }
+            if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)) {
+                previousMode = uidState.getUidMode(code);
             } else {
-                if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
-                    return;
-                }
-                previousMode = uidState.opModes.get(code);
-                if (mode == defaultMode) {
-                    uidState.opModes.delete(code);
-                    if (uidState.opModes.size() <= 0) {
-                        uidState.opModes = null;
-                    }
-                } else {
-                    uidState.opModes.put(code, mode);
-                }
-                scheduleWriteLocked();
+                // doesn't look right but is legacy behavior.
+                previousMode = MODE_DEFAULT;
+            }
+
+            if (!uidState.setUidMode(code, mode)) {
+                return;
             }
             uidState.evalForegroundOps(mOpModeWatchers);
             if (mode != MODE_ERRORED && mode != previousMode) {
@@ -2806,9 +2826,10 @@
             UidState uidState = getUidStateLocked(uid, false);
             Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ true);
             if (op != null) {
-                if (op.mode != mode) {
-                    previousMode = op.mode;
-                    op.mode = mode;
+                if (op.getMode() != mode) {
+                    previousMode = op.getMode();
+                    op.setMode(mode);
+
                     if (uidState != null) {
                         uidState.evalForegroundOps(mOpModeWatchers);
                     }
@@ -2976,17 +2997,14 @@
             for (int i = mUidStates.size() - 1; i >= 0; i--) {
                 UidState uidState = mUidStates.valueAt(i);
 
-                SparseIntArray opModes = uidState.opModes;
+                SparseIntArray opModes = uidState.getNonDefaultUidModes();
                 if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
                     final int uidOpCount = opModes.size();
                     for (int j = uidOpCount - 1; j >= 0; j--) {
                         final int code = opModes.keyAt(j);
                         if (AppOpsManager.opAllowsReset(code)) {
                             int previousMode = opModes.valueAt(j);
-                            opModes.removeAt(j);
-                            if (opModes.size() <= 0) {
-                                uidState.opModes = null;
-                            }
+                            uidState.setUidMode(code, AppOpsManager.opToDefaultMode(code));
                             for (String packageName : getPackagesForUid(uidState.uid)) {
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
                                         previousMode, mOpModeWatchers.get(code));
@@ -3028,9 +3046,9 @@
                             continue;
                         }
                         if (AppOpsManager.opAllowsReset(curOp.op)
-                                && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
-                            int previousMode = curOp.mode;
-                            curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
+                                && curOp.getMode() != AppOpsManager.opToDefaultMode(curOp.op)) {
+                            int previousMode = curOp.getMode();
+                            curOp.setMode(AppOpsManager.opToDefaultMode(curOp.op));
                             changed = true;
                             uidChanged = true;
                             final int uid = curOp.uidState.uid;
@@ -3049,9 +3067,11 @@
                     }
                     if (pkgOps.size() == 0) {
                         it.remove();
+                        mAppOpsServiceInterface.removePackage(packageName);
                     }
                 }
                 if (uidState.isDefault()) {
+                    uidState.clear();
                     mUidStates.remove(uidState.uid);
                 }
                 if (uidChanged) {
@@ -3267,16 +3287,16 @@
             }
             code = AppOpsManager.opToSwitch(code);
             UidState uidState = getUidStateLocked(uid, false);
-            if (uidState != null && uidState.opModes != null
-                    && uidState.opModes.indexOfKey(code) >= 0) {
-                final int rawMode = uidState.opModes.get(code);
+            if (uidState != null
+                    && uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)) {
+                final int rawMode = uidState.getUidMode(code);
                 return raw ? rawMode : uidState.evalMode(code, rawMode);
             }
             Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
-            return raw ? op.mode : op.evalMode();
+            return raw ? op.getMode() : op.evalMode();
         }
     }
 
@@ -3502,8 +3522,8 @@
             }
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
-            if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+            if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) {
+                final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
@@ -4018,8 +4038,8 @@
             final int switchCode = AppOpsManager.opToSwitch(code);
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
-            if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+            if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) {
+                final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode));
                 if (!shouldStartForMode(uidMode, startIfModeDefault)) {
                     if (DEBUG) {
                         Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
@@ -4516,9 +4536,8 @@
                     continue;
                 }
 
-                if (uidState.opModes != null
-                        && uidState.opModes.indexOfKey(code) >= 0
-                        && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND) {
+                if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)
+                        && uidState.getUidMode(code) == AppOpsManager.MODE_FOREGROUND) {
                     mHandler.sendMessage(PooledLambda.obtainMessage(
                             AppOpsService::notifyOpChangedForAllPkgsInUid,
                             this, code, uidState.uid, true, null));
@@ -4536,7 +4555,7 @@
                                 if (op == null) {
                                     continue;
                                 }
-                                if (op.mode == AppOpsManager.MODE_FOREGROUND) {
+                                if (op.getMode() == AppOpsManager.MODE_FOREGROUND) {
                                     mHandler.sendMessage(PooledLambda.obtainMessage(
                                             AppOpsService::notifyOpChanged,
                                             this, callback, code, uidState.uid,
@@ -4811,14 +4830,16 @@
         return ops;
     }
 
-    private void scheduleWriteLocked() {
+    @Override
+    public void scheduleWriteLocked() {
         if (!mWriteScheduled) {
             mWriteScheduled = true;
             mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
         }
     }
 
-    private void scheduleFastWriteLocked() {
+    @Override
+    public void scheduleFastWriteLocked() {
         if (!mFastWriteScheduled) {
             mWriteScheduled = true;
             mFastWriteScheduled = true;
@@ -4929,6 +4950,7 @@
                 }
                 boolean success = false;
                 mUidStates.clear();
+                mAppOpsServiceInterface.clearAllModes();
                 try {
                     TypedXmlPullParser parser = Xml.resolvePullParser(stream);
                     int type;
@@ -4977,6 +4999,7 @@
                 } finally {
                     if (!success) {
                         mUidStates.clear();
+                        mAppOpsServiceInterface.clearAllModes();
                     }
                     try {
                         stream.close();
@@ -4996,11 +5019,12 @@
             if (uidState == null) {
                 continue;
             }
-            if (uidState.opModes != null) {
-                final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
+            SparseIntArray opModes = uidState.getNonDefaultUidModes();
+            if (opModes != null) {
+                final int idx = opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
                 if (idx >= 0) {
-                    uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
-                        uidState.opModes.valueAt(idx));
+                    uidState.setUidMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
+                            opModes.valueAt(idx));
                 }
             }
             if (uidState.pkgOps == null) {
@@ -5011,10 +5035,10 @@
                 Ops ops = uidState.pkgOps.valueAt(j);
                 if (ops != null) {
                     final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
-                    if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
+                    if (op != null && op.getMode() != AppOpsManager.opToDefaultMode(op.op)) {
                         final Op copy = new Op(op.uidState, op.packageName,
                                 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.uid);
-                        copy.mode = op.mode;
+                        copy.setMode(op.getMode());
                         ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
                         changed = true;
                     }
@@ -5142,7 +5166,7 @@
         Op op = new Op(uidState, pkgName, opCode, uidState.uid);
 
         final int mode = parser.getAttributeInt(null, "m", AppOpsManager.opToDefaultMode(op.op));
-        op.mode = mode;
+        op.setMode(mode);
 
         int outerDepth = parser.getDepth();
         int type;
@@ -5199,16 +5223,9 @@
                         UidState uidState = mUidStates.valueAt(uidStateNum);
                         int uid = mUidStates.keyAt(uidStateNum);
 
-                        SparseIntArray opModes = uidState.opModes;
+                        SparseIntArray opModes = uidState.getNonDefaultUidModes();
                         if (opModes != null && opModes.size() > 0) {
-                            uidStatesClone.put(uid, new SparseIntArray(opModes.size()));
-
-                            final int opCount = opModes.size();
-                            for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
-                                uidStatesClone.get(uid).put(
-                                        opModes.keyAt(opCountNum),
-                                        opModes.valueAt(opCountNum));
-                            }
+                            uidStatesClone.put(uid, opModes);
                         }
                     }
                 }
@@ -6314,15 +6331,15 @@
             }
             for (int i=0; i<mUidStates.size(); i++) {
                 UidState uidState = mUidStates.valueAt(i);
-                final SparseIntArray opModes = uidState.opModes;
+                final SparseIntArray opModes = uidState.getNonDefaultUidModes();
                 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
 
                 if (dumpWatchers || dumpHistory) {
                     continue;
                 }
                 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
-                    boolean hasOp = dumpOp < 0 || (uidState.opModes != null
-                            && uidState.opModes.indexOfKey(dumpOp) >= 0);
+                    boolean hasOp = dumpOp < 0 || (opModes != null
+                            && opModes.indexOfKey(dumpOp) >= 0);
                     boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i);
                     boolean hasMode = dumpMode < 0;
                     if (!hasMode && opModes != null) {
@@ -6342,7 +6359,7 @@
                             }
                             if (!hasMode) {
                                 for (int opi = 0; !hasMode && opi < ops.size(); opi++) {
-                                    if (ops.valueAt(opi).mode == dumpMode) {
+                                    if (ops.valueAt(opi).getMode() == dumpMode) {
                                         hasMode = true;
                                     }
                                 }
@@ -6437,7 +6454,7 @@
                         if (dumpOp >= 0 && dumpOp != opCode) {
                             continue;
                         }
-                        if (dumpMode >= 0 && dumpMode != op.mode) {
+                        if (dumpMode >= 0 && dumpMode != op.getMode()) {
                             continue;
                         }
                         if (!printedPackage) {
@@ -6445,14 +6462,14 @@
                             printedPackage = true;
                         }
                         pw.print("      "); pw.print(AppOpsManager.opToName(opCode));
-                        pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
+                        pw.print(" ("); pw.print(AppOpsManager.modeToName(op.getMode()));
                         final int switchOp = AppOpsManager.opToSwitch(opCode);
                         if (switchOp != opCode) {
                             pw.print(" / switch ");
                             pw.print(AppOpsManager.opToName(switchOp));
                             final Op switchObj = ops.get(switchOp);
-                            int mode = switchObj != null ? switchObj.mode
-                                    : AppOpsManager.opToDefaultMode(switchOp);
+                            int mode = switchObj == null
+                                    ? AppOpsManager.opToDefaultMode(switchOp) : switchObj.getMode();
                             pw.print("="); pw.print(AppOpsManager.modeToName(mode));
                         }
                         pw.println("): ");
@@ -6696,7 +6713,7 @@
         for (int pkgNum = 0; pkgNum < numPkgOps; pkgNum++) {
             Ops ops = uidState.pkgOps.valueAt(pkgNum);
             Op op = ops != null ? ops.get(code) : null;
-            if (op == null || (op.mode != MODE_ALLOWED && op.mode != MODE_FOREGROUND)) {
+            if (op == null || (op.getMode() != MODE_ALLOWED && op.getMode() != MODE_FOREGROUND)) {
                 continue;
             }
             int numAttrTags = op.mAttributions.size();
@@ -6817,6 +6834,7 @@
                 return;
             }
             Ops removedOps = uidState.pkgOps.remove(packageName);
+            mAppOpsServiceInterface.removePackage(packageName);
             if (removedOps != null) {
                 scheduleFastWriteLocked();
             }
@@ -7136,10 +7154,12 @@
         return false;
     }
 
+    @GuardedBy("this")
     private void removeUidsForUserLocked(int userHandle) {
         for (int i = mUidStates.size() - 1; i >= 0; --i) {
             final int uid = mUidStates.keyAt(i);
             if (UserHandle.getUserId(uid) == userHandle) {
+                mUidStates.valueAt(i).clear();
                 mUidStates.removeAt(i);
             }
         }
diff --git a/services/core/java/com/android/server/appop/AppOpsServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
new file mode 100644
index 0000000..cd5ea12
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.appop;
+import android.annotation.NonNull;
+import android.app.AppOpsManager.Mode;
+import android.util.SparseIntArray;
+/**
+ * Interface for accessing and modifying modes for app-ops i.e. package and uid modes.
+ * In the future this interface will also include mode callbacks and op restrictions.
+ */
+public interface AppOpsServiceInterface {
+    /**
+     * Returns a copy of non-default app-ops with op as keys and their modes as values for a uid.
+     * Returns an empty SparseIntArray if nothing is set.
+     * @param uid for which we need the app-ops and their modes.
+     */
+    SparseIntArray getNonDefaultUidModes(int uid);
+
+    /**
+     * Returns the app-op mode for a particular app-op of a uid.
+     * Returns default op mode if the op mode for particular uid and op is not set.
+     * @param uid user id for which we need the mode.
+     * @param op app-op for which we need the mode.
+     * @return mode of the app-op.
+     */
+    int getUidMode(int uid, int op);
+
+    /**
+     * Set the app-op mode for a particular uid and op.
+     * The mode is not set if the mode is the same as the default mode for the op.
+     * @param uid user id for which we want to set the mode.
+     * @param op app-op for which we want to set the mode.
+     * @param mode mode for the app-op.
+     * @return true if op mode is changed.
+     */
+    boolean setUidMode(int uid, int op, @Mode int mode);
+
+    /**
+     * Gets the app-op mode for a particular package.
+     * Returns default op mode if the op mode for the particular package is not set.
+     * @param packageName package name for which we need the op mode.
+     * @param op app-op for which we need the mode.
+     * @return the mode of the app-op.
+     */
+    int getPackageMode(@NonNull String packageName, int op);
+
+    /**
+     * Sets the app-op mode for a particular package.
+     * @param packageName package name for which we need to set the op mode.
+     * @param op app-op for which we need to set the mode.
+     * @param mode the mode of the app-op.
+     */
+    void setPackageMode(@NonNull String packageName, int op, @Mode int mode);
+
+    /**
+     * Stop tracking any app-op modes for a package.
+     * @param packageName Name of the package for which we want to remove all mode tracking.
+     */
+    boolean removePackage(@NonNull String packageName);
+
+    /**
+     * Stop tracking any app-op modes for this uid.
+     * @param uid user id for which we want to remove all tracking.
+     */
+    void removeUid(int uid);
+
+    /**
+     * Returns true if all uid modes for this uid are
+     * in default state.
+     * @param uid user id
+     */
+    boolean areUidModesDefault(int uid);
+
+    /**
+     * Returns true if all package modes for this package name are
+     * in default state.
+     * @param packageName package name.
+     */
+    boolean arePackageModesDefault(String packageName);
+
+    /**
+     * Stop tracking app-op modes for all uid and packages.
+     */
+    void clearAllModes();
+}
diff --git a/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
new file mode 100644
index 0000000..c27c0d3
--- /dev/null
+++ b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.appop;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.Mode;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+
+/**
+ * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access.
+ * In the future this class will also include mode callbacks and op restrictions.
+ */
+public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface {
+
+    // Should be the same object that the AppOpsService is using for locking.
+    final Object mLock;
+
+    @GuardedBy("mLock")
+    @VisibleForTesting
+    final SparseArray<SparseIntArray> mUidModes = new SparseArray<>();
+
+    @GuardedBy("mLock")
+    final ArrayMap<String, SparseIntArray> mPackageModes = new ArrayMap<>();
+
+    final PersistenceScheduler mPersistenceScheduler;
+
+
+    LegacyAppOpsServiceInterfaceImpl(PersistenceScheduler persistenceScheduler,
+            @NonNull Object lock) {
+        this.mPersistenceScheduler = persistenceScheduler;
+        this.mLock = lock;
+    }
+
+    @Override
+    public SparseIntArray getNonDefaultUidModes(int uid) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mUidModes.get(uid, null);
+            if (opModes == null) {
+                return new SparseIntArray();
+            }
+            return opModes.clone();
+        }
+    }
+
+    @Override
+    public int getUidMode(int uid, int op) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mUidModes.get(uid, null);
+            if (opModes == null) {
+                return AppOpsManager.opToDefaultMode(op);
+            }
+            return opModes.get(op, AppOpsManager.opToDefaultMode(op));
+        }
+    }
+
+    @Override
+    public boolean setUidMode(int uid, int op, int mode) {
+        final int defaultMode = AppOpsManager.opToDefaultMode(op);
+        synchronized (mLock) {
+            SparseIntArray opModes = mUidModes.get(uid, null);
+            if (opModes == null) {
+                if (mode != defaultMode) {
+                    opModes = new SparseIntArray();
+                    mUidModes.put(uid, opModes);
+                    opModes.put(op, mode);
+                    mPersistenceScheduler.scheduleWriteLocked();
+                }
+            } else {
+                if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
+                    return false;
+                }
+                if (mode == defaultMode) {
+                    opModes.delete(op);
+                    if (opModes.size() <= 0) {
+                        opModes = null;
+                        mUidModes.delete(uid);
+                    }
+                } else {
+                    opModes.put(op, mode);
+                }
+                mPersistenceScheduler.scheduleWriteLocked();
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int getPackageMode(String packageName, int op) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mPackageModes.getOrDefault(packageName, null);
+            if (opModes == null) {
+                return AppOpsManager.opToDefaultMode(op);
+            }
+            return opModes.get(op, AppOpsManager.opToDefaultMode(op));
+        }
+    }
+
+    @Override
+    public void setPackageMode(String packageName, int op, @Mode int mode) {
+        final int defaultMode = AppOpsManager.opToDefaultMode(op);
+        synchronized (mLock) {
+            SparseIntArray opModes = mPackageModes.get(packageName);
+            if (opModes == null) {
+                if (mode != defaultMode) {
+                    opModes = new SparseIntArray();
+                    mPackageModes.put(packageName, opModes);
+                    opModes.put(op, mode);
+                    mPersistenceScheduler.scheduleWriteLocked();
+                }
+            } else {
+                if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
+                    return;
+                }
+                if (mode == defaultMode) {
+                    opModes.delete(op);
+                    if (opModes.size() <= 0) {
+                        opModes = null;
+                        mPackageModes.remove(packageName);
+                    }
+                } else {
+                    opModes.put(op, mode);
+                }
+                mPersistenceScheduler.scheduleWriteLocked();
+            }
+        }
+    }
+
+    @Override
+    public void removeUid(int uid) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mUidModes.get(uid);
+            if (opModes == null) {
+                return;
+            }
+            mUidModes.remove(uid);
+            mPersistenceScheduler.scheduleFastWriteLocked();
+        }
+    }
+
+
+    @Override
+    public boolean areUidModesDefault(int uid) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mUidModes.get(uid);
+            return (opModes == null || opModes.size() <= 0);
+        }
+    }
+
+    @Override
+    public boolean arePackageModesDefault(String packageMode) {
+        synchronized (mLock) {
+            SparseIntArray opModes = mPackageModes.get(packageMode);
+            return (opModes == null || opModes.size() <= 0);
+        }
+    }
+
+    @Override
+    public boolean removePackage(String packageName) {
+        synchronized (mLock) {
+            SparseIntArray ops = mPackageModes.remove(packageName);
+            if (ops != null) {
+                mPersistenceScheduler.scheduleFastWriteLocked();
+                return true;
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public void clearAllModes() {
+        synchronized (mLock) {
+            mUidModes.clear();
+            mPackageModes.clear();
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/appop/PersistenceScheduler.java b/services/core/java/com/android/server/appop/PersistenceScheduler.java
new file mode 100644
index 0000000..e50b658
--- /dev/null
+++ b/services/core/java/com/android/server/appop/PersistenceScheduler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.appop;
+
+/**
+ * Interface that allows callers to persist AppOpsService's internal state
+ * to disk.
+ */
+public interface PersistenceScheduler {
+
+    /**
+     * Schedules disk writes for appOpsService and it's internal states.
+     */
+    void scheduleWriteLocked();
+
+    /**
+     * Schedules fast disk writes for appOpsService and it's internal states.
+     */
+    void scheduleFastWriteLocked();
+
+}
diff --git a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
index 351a1e9..23183f9 100644
--- a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
@@ -26,11 +26,14 @@
 import android.hardware.radio.ITunerCallback;
 import android.hardware.radio.RadioManager;
 import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
 import com.android.server.SystemService;
 import com.android.server.broadcastradio.hal2.AnnouncementAggregator;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -46,7 +49,7 @@
     private final com.android.server.broadcastradio.hal2.BroadcastRadioService mHal2;
 
     private final Object mLock = new Object();
-    private List<RadioManager.ModuleProperties> mV1Modules = null;
+    private final List<RadioManager.ModuleProperties> mV1Modules;
 
     public BroadcastRadioService(Context context) {
         super(context);
@@ -115,5 +118,21 @@
                 return mHal2.addAnnouncementListener(enabledTypes, listener);
             }
         }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            IndentingPrintWriter radioPw = new IndentingPrintWriter(pw);
+            radioPw.printf("BroadcastRadioService\n");
+            radioPw.increaseIndent();
+            radioPw.printf("HAL1: %s\n", mHal1);
+            radioPw.increaseIndent();
+            radioPw.printf("Modules of HAL1: %s\n", mV1Modules);
+            radioPw.decreaseIndent();
+            radioPw.printf("HAL2:\n");
+            radioPw.increaseIndent();
+            mHal2.dumpInfo(radioPw);
+            radioPw.decreaseIndent();
+            radioPw.decreaseIndent();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 534e828..5605737 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -29,6 +29,7 @@
 import android.hidl.manager.V1_0.IServiceNotification;
 import android.os.IHwBinder.DeathRecipient;
 import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -195,4 +196,30 @@
         }
         return aggregator;
     }
+
+    /**
+     * Dump state of broadcastradio service for HIDL HAL 2.0.
+     *
+     * @param pw The file to which BroadcastRadioService state is dumped.
+     */
+    public void dumpInfo(IndentingPrintWriter pw) {
+        synchronized (mLock) {
+            pw.printf("Next module id available: %d\n", mNextModuleId);
+            pw.printf("ServiceName to module id map:\n");
+            pw.increaseIndent();
+            for (Map.Entry<String, Integer> entry : mServiceNameToModuleIdMap.entrySet()) {
+                pw.printf("Service name: %s, module id: %d\n", entry.getKey(), entry.getValue());
+            }
+            pw.decreaseIndent();
+            pw.printf("Radio modules:\n");
+            pw.increaseIndent();
+            for (Map.Entry<Integer, RadioModule> moduleEntry : mModules.entrySet()) {
+                pw.printf("Module id=%d:\n", moduleEntry.getKey());
+                pw.increaseIndent();
+                moduleEntry.getValue().dumpInfo(pw);
+                pw.decreaseIndent();
+            }
+            pw.decreaseIndent();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index aeaa678..852aa66 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -38,6 +38,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
 import android.util.MutableInt;
 import android.util.Slog;
 
@@ -424,4 +425,30 @@
 
         return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
     }
+
+    void dumpInfo(IndentingPrintWriter pw) {
+        pw.printf("RadioModule\n");
+        pw.increaseIndent();
+        synchronized (mLock) {
+            pw.printf("BroadcastRadioService: %s\n", mService);
+            pw.printf("Properties: %s\n", mProperties);
+            pw.printf("HIDL2.0 HAL TunerSession: %s\n", mHalTunerSession);
+            pw.printf("Is antenna connected? ");
+            if (mAntennaConnected == null) {
+                pw.printf("null\n");
+            } else {
+                pw.printf("%s\n", mAntennaConnected ? "Yes" : "No");
+            }
+            pw.printf("current ProgramInfo: %s\n", mCurrentProgramInfo);
+            pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
+            pw.printf("Union of AIDL ProgramFilters: %s\n", mUnionOfAidlProgramFilters);
+            pw.printf("AIDL TunerSessions:\n");
+            pw.increaseIndent();
+            for (TunerSession aidlTunerSession : mAidlTunerSessions) {
+                aidlTunerSession.dumpInfo(pw);
+            }
+            pw.decreaseIndent();
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index c13216b..41f753c 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -27,6 +27,7 @@
 import android.hardware.radio.ProgramSelector;
 import android.hardware.radio.RadioManager;
 import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.MutableBoolean;
 import android.util.MutableInt;
@@ -339,4 +340,17 @@
                     () -> mHwSession.getParameters(Convert.listToArrayList(keys))));
         }
     }
+
+    void dumpInfo(IndentingPrintWriter pw) {
+        pw.printf("TunerSession\n");
+        pw.increaseIndent();
+        synchronized (mLock) {
+            pw.printf("HIDL HAL Session: %s\n", mHwSession);
+            pw.printf("Is session closed? %s\n", mIsClosed ? "Yes" : "No");
+            pw.printf("Is muted? %s\n", mIsMuted ? "Yes" : "No");
+            pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
+            pw.printf("Config: %s\n", mDummyConfig);
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 690ec3f..52b92c4 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -29,7 +29,6 @@
 class RampAnimator<T> {
     private final T mObject;
     private final FloatProperty<T> mProperty;
-    private final Choreographer mChoreographer;
 
     private float mCurrentValue;
     private float mTargetValue;
@@ -43,18 +42,16 @@
 
     private boolean mFirstTime = true;
 
-    private Listener mListener;
 
     RampAnimator(T object, FloatProperty<T> property) {
         mObject = object;
         mProperty = property;
-        mChoreographer = Choreographer.getInstance();
     }
 
     /**
      * Sets the maximum time that a brightness animation can take.
      */
-    public void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
+    void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
             long animationRampDecreaseMaxTimeMillis) {
         mAnimationIncreaseMaxTimeSecs = (animationRampIncreaseMaxTimeMillis > 0)
                 ? (animationRampIncreaseMaxTimeMillis / 1000.0f) : 0.0f;
@@ -63,7 +60,7 @@
     }
 
     /**
-     * Starts animating towards the specified value.
+     * Sets the animation target and the rate of this ramp animator.
      *
      * If this is the first time the property is being set or if the rate is 0,
      * the value jumps directly to the target.
@@ -72,7 +69,7 @@
      * @param rate The convergence rate in units per second, or 0 to set the value immediately.
      * @return True if the target differs from the previous target.
      */
-    public boolean animateTo(float targetLinear, float rate) {
+    boolean setAnimationTarget(float targetLinear, float rate) {
         // Convert the target from the linear into the HLG space.
         final float target = BrightnessUtils.convertLinearToGamma(targetLinear);
 
@@ -84,13 +81,7 @@
                 mTargetValue = target;
                 mCurrentValue = target;
                 setPropertyValue(target);
-                if (mAnimating) {
-                    mAnimating = false;
-                    cancelAnimationCallback();
-                }
-                if (mListener != null) {
-                    mListener.onAnimationEnd();
-                }
+                mAnimating = false;
                 return true;
             }
             return false;
@@ -127,7 +118,6 @@
             mAnimating = true;
             mAnimatedValue = mCurrentValue;
             mLastFrameTimeNanos = System.nanoTime();
-            postAnimationCallback();
         }
 
         return changed;
@@ -136,18 +126,11 @@
     /**
      * Returns true if the animation is running.
      */
-    public boolean isAnimating() {
+    boolean isAnimating() {
         return mAnimating;
     }
 
     /**
-     * Sets a listener to watch for animation events.
-     */
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
-    /**
      * Sets the brightness property by converting the given value from HLG space
      * into linear space.
      */
@@ -156,78 +139,53 @@
         mProperty.setValue(mObject, linearVal);
     }
 
-    private void postAnimationCallback() {
-        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
-    }
+    void performNextAnimationStep(long frameTimeNanos) {
+        final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos) * 0.000000001f;
+        mLastFrameTimeNanos = frameTimeNanos;
 
-    private void cancelAnimationCallback() {
-        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
-    }
-
-    private final Runnable mAnimationCallback = new Runnable() {
-        @Override // Choreographer callback
-        public void run() {
-            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
-            final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
-                    * 0.000000001f;
-            mLastFrameTimeNanos = frameTimeNanos;
-
-            // Advance the animated value towards the target at the specified rate
-            // and clamp to the target. This gives us the new current value but
-            // we keep the animated value around to allow for fractional increments
-            // towards the target.
-            final float scale = ValueAnimator.getDurationScale();
-            if (scale == 0) {
-                // Animation off.
-                mAnimatedValue = mTargetValue;
+        // Advance the animated value towards the target at the specified rate
+        // and clamp to the target. This gives us the new current value but
+        // we keep the animated value around to allow for fractional increments
+        // towards the target.
+        final float scale = ValueAnimator.getDurationScale();
+        if (scale == 0) {
+            // Animation off.
+            mAnimatedValue = mTargetValue;
+        } else {
+            final float amount = timeDelta * mRate / scale;
+            if (mTargetValue > mCurrentValue) {
+                mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
             } else {
-                final float amount = timeDelta * mRate / scale;
-                if (mTargetValue > mCurrentValue) {
-                    mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
-                } else {
-                    mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
-                }
-            }
-            final float oldCurrentValue = mCurrentValue;
-            mCurrentValue = mAnimatedValue;
-            if (oldCurrentValue != mCurrentValue) {
-                setPropertyValue(mCurrentValue);
-            }
-            if (mTargetValue != mCurrentValue) {
-                postAnimationCallback();
-            } else {
-                mAnimating = false;
-                if (mListener != null) {
-                    mListener.onAnimationEnd();
-                }
+                mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
             }
         }
-    };
+        final float oldCurrentValue = mCurrentValue;
+        mCurrentValue = mAnimatedValue;
+        if (oldCurrentValue != mCurrentValue) {
+            setPropertyValue(mCurrentValue);
+        }
+        if (mTargetValue == mCurrentValue) {
+            mAnimating = false;
+        }
+    }
 
     public interface Listener {
         void onAnimationEnd();
     }
 
     static class DualRampAnimator<T> {
+        private final Choreographer mChoreographer;
         private final RampAnimator<T> mFirst;
         private final RampAnimator<T> mSecond;
-        private final Listener mInternalListener = new Listener() {
-            @Override
-            public void onAnimationEnd() {
-                if (mListener != null && !isAnimating()) {
-                    mListener.onAnimationEnd();
-                }
-            }
-        };
 
         private Listener mListener;
+        private boolean mAwaitingCallback;
 
         DualRampAnimator(T object, FloatProperty<T> firstProperty,
                 FloatProperty<T> secondProperty) {
-            mFirst = new RampAnimator(object, firstProperty);
-            mFirst.setListener(mInternalListener);
-            mSecond = new RampAnimator(object, secondProperty);
-            mSecond.setListener(mInternalListener);
+            mChoreographer = Choreographer.getInstance();
+            mFirst = new RampAnimator<>(object, firstProperty);
+            mSecond = new RampAnimator<>(object, secondProperty);
         }
 
         /**
@@ -253,17 +211,56 @@
          * @return True if either target differs from the previous target.
          */
         public boolean animateTo(float linearFirstTarget, float linearSecondTarget, float rate) {
-            final boolean firstRetval = mFirst.animateTo(linearFirstTarget, rate);
-            final boolean secondRetval = mSecond.animateTo(linearSecondTarget, rate);
-            return firstRetval && secondRetval;
+            boolean animationTargetChanged = mFirst.setAnimationTarget(linearFirstTarget, rate);
+            animationTargetChanged |= mSecond.setAnimationTarget(linearSecondTarget, rate);
+            boolean shouldBeAnimating = isAnimating();
+
+            if (shouldBeAnimating != mAwaitingCallback) {
+                if (shouldBeAnimating) {
+                    mAwaitingCallback = true;
+                    postAnimationCallback();
+                } else if (mAwaitingCallback) {
+                    mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+                            mAnimationCallback, null);
+                    mAwaitingCallback = false;
+                }
+            }
+            return animationTargetChanged;
         }
 
+        /**
+        * Sets a listener to watch for animation events.
+        */
         public void setListener(Listener listener) {
             mListener = listener;
         }
 
+        /**
+        * Returns true if the animation is running.
+        */
         public boolean isAnimating() {
-            return mFirst.isAnimating() && mSecond.isAnimating();
+            return mFirst.isAnimating() || mSecond.isAnimating();
         }
+
+        private void postAnimationCallback() {
+            mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
+        }
+
+        private final Runnable mAnimationCallback = new Runnable() {
+            @Override // Choreographer callback
+            public void run() {
+                long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+                mFirst.performNextAnimationStep(frameTimeNanos);
+                mSecond.performNextAnimationStep(frameTimeNanos);
+                if (isAnimating()) {
+                    postAnimationCallback();
+                } else {
+                    if (mListener != null) {
+                        mListener.onAnimationEnd();
+                    }
+                    mAwaitingCallback = false;
+                }
+            }
+        };
     }
 }
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 9f44765..479629e 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -35,6 +35,7 @@
 import static com.android.server.display.DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED;
 import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Point;
 import android.hardware.display.IVirtualDisplayCallback;
@@ -110,15 +111,20 @@
         } else {
             uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
         }
+        MediaProjectionCallback mediaProjectionCallback =  null;
+        if (projection != null) {
+            mediaProjectionCallback = new MediaProjectionCallback(appToken);
+        }
         VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
-                ownerUid, ownerPackageName, surface, flags, new Callback(callback, mHandler),
+                ownerUid, ownerPackageName, surface, flags,
+                new Callback(callback, mHandler), projection, mediaProjectionCallback,
                 uniqueId, uniqueIndex, virtualDisplayConfig);
 
         mVirtualDisplayDevices.put(appToken, device);
 
         try {
             if (projection != null) {
-                projection.registerCallback(new MediaProjectionCallback(appToken));
+                projection.registerCallback(mediaProjectionCallback);
             }
             appToken.linkToDeath(device, 0);
         } catch (RemoteException ex) {
@@ -223,6 +229,8 @@
         final String mName;
         private final int mFlags;
         private final Callback mCallback;
+        @Nullable private final IMediaProjection mProjection;
+        @Nullable private final IMediaProjectionCallback mMediaProjectionCallback;
 
         private int mWidth;
         private int mHeight;
@@ -240,7 +248,8 @@
 
         public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
                 int ownerUid, String ownerPackageName, Surface surface, int flags,
-                Callback callback, String uniqueId, int uniqueIndex,
+                Callback callback, IMediaProjection projection,
+                IMediaProjectionCallback mediaProjectionCallback, String uniqueId, int uniqueIndex,
                 VirtualDisplayConfig virtualDisplayConfig) {
             super(VirtualDisplayAdapter.this, displayToken, uniqueId, getContext());
             mAppToken = appToken;
@@ -254,6 +263,8 @@
             mSurface = surface;
             mFlags = flags;
             mCallback = callback;
+            mProjection = projection;
+            mMediaProjectionCallback = mediaProjectionCallback;
             mDisplayState = Display.STATE_UNKNOWN;
             mPendingChanges |= PENDING_SURFACE_CHANGE;
             mUniqueIndex = uniqueIndex;
@@ -269,6 +280,13 @@
                 Slog.i(TAG, "Virtual display device released because application token died: "
                     + mOwnerPackageName);
                 destroyLocked(false);
+                if (mProjection != null && mMediaProjectionCallback != null) {
+                    try {
+                        mProjection.unregisterCallback(mMediaProjectionCallback);
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Failed to unregister callback in binderDied", e);
+                    }
+                }
                 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_REMOVED);
             }
         }
@@ -279,6 +297,13 @@
                 mSurface = null;
             }
             SurfaceControl.destroyDisplay(getDisplayTokenLocked());
+            if (mProjection != null && mMediaProjectionCallback != null) {
+                try {
+                    mProjection.unregisterCallback(mMediaProjectionCallback);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to unregister callback in destroy", e);
+                }
+            }
             if (binderAlive) {
                 mCallback.dispatchDisplayStopped();
             }
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
index 8180e66..0c889c2 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
@@ -32,11 +32,10 @@
     public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName();
     static final boolean DEBUG = HandwritingModeController.DEBUG;
 
-    // Place the layer below the highest layer to place it under gesture monitors. If the surface
-    // is above gesture monitors, then edge-back and swipe-up gestures won't work when this surface
-    // is intercepting.
+    // Place the layer at the highest layer so stylus cannot trigger gesture monitors
+    // (e.g. navigation bar, edge-back, etc) while handwriting is ongoing.
     // TODO(b/217538817): Specify the ordering in WM by usage.
-    private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1;
+    private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE;
 
     private final InputWindowHandle mWindowHandle;
     private final InputChannel mClientChannel;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index b86fa7a..f4ad750 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1627,7 +1627,7 @@
             }
 
             onSyntheticPasswordKnown(userId, sp);
-            setLockCredentialWithSpLocked(credential, sp, userId, isLockTiedToParent);
+            setLockCredentialWithSpLocked(credential, sp, userId);
             sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
             return true;
         }
@@ -1641,15 +1641,18 @@
         if (newCredential.isPattern()) {
             setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
         }
+        updatePasswordHistory(newCredential, userHandle);
         mContext.getSystemService(TrustManager.class).reportEnabledTrustAgentsChanged(userHandle);
     }
 
     /**
      * Store the hash of the new password in the password history list, if device policy enforces
      * a password history requirement.
+     *
+     * This must not be called while the mSpManager lock is held, as this calls into
+     * DevicePolicyManagerService to get the requested password history length.
      */
-    private void updatePasswordHistory(SyntheticPassword sp, LockscreenCredential password,
-            int userHandle, boolean isLockTiedToParent) {
+    private void updatePasswordHistory(LockscreenCredential password, int userHandle) {
         if (password.isNone()) {
             return;
         }
@@ -1657,10 +1660,6 @@
             // Do not keep track of historical patterns
             return;
         }
-        if (isLockTiedToParent) {
-            // Do not keep track of historical auto-generated profile passwords
-            return;
-        }
         // Add the password to the password history.
         String passwordHistory = getString(
                 LockPatternUtils.PASSWORD_HISTORY_KEY, /* defaultValue= */ null, userHandle);
@@ -1671,9 +1670,16 @@
         if (passwordHistoryLength == 0) {
             passwordHistory = "";
         } else {
-            final byte[] hashFactor = sp.derivePasswordHashFactor();
+            final byte[] hashFactor = getHashFactor(password, userHandle);
             final byte[] salt = getSalt(userHandle).getBytes();
             String hash = password.passwordToHistoryHash(salt, hashFactor);
+            if (hash == null) {
+                // This should never happen, as all information needed to compute the hash should be
+                // available.  In particular, unwrapping the SP in getHashFactor() should always
+                // succeed, as we're using the LSKF that was just set.
+                Slog.e(TAG, "Failed to compute password hash; password history won't be updated");
+                return;
+            }
             if (TextUtils.isEmpty(passwordHistory)) {
                 passwordHistory = hash;
             } else {
@@ -2644,7 +2650,7 @@
      */
     @GuardedBy("mSpManager")
     private long setLockCredentialWithSpLocked(LockscreenCredential credential,
-            SyntheticPassword sp, int userId, boolean isLockTiedToParent) {
+            SyntheticPassword sp, int userId) {
         if (DEBUG) Slog.d(TAG, "setLockCredentialWithSpLocked: user=" + userId);
         final int savedCredentialType = getCredentialTypeInternal(userId);
         final long oldProtectorId = getCurrentLskfBasedProtectorId(userId);
@@ -2682,7 +2688,6 @@
         LockPatternUtils.invalidateCredentialTypeCache();
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
 
-        updatePasswordHistory(sp, credential, userId, isLockTiedToParent);
         setUserPasswordMetrics(credential, userId);
         mManagedProfilePasswordCache.removePassword(userId);
         if (savedCredentialType != CREDENTIAL_TYPE_NONE) {
@@ -2928,8 +2933,7 @@
             return false;
         }
         onSyntheticPasswordKnown(userId, result.syntheticPassword);
-        setLockCredentialWithSpLocked(credential, result.syntheticPassword, userId,
-                /* isLockTiedToParent= */ false);
+        setLockCredentialWithSpLocked(credential, result.syntheticPassword, userId);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 48ec436..bda7b82 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -816,9 +816,10 @@
         }
 
         // Allow package verifier to silently uninstall.
-        if (mPm.mRequiredVerifierPackage != null && callingUid == snapshot
-                .getPackageUid(mPm.mRequiredVerifierPackage, 0, callingUserId)) {
-            return true;
+        for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+            if (callingUid == snapshot.getPackageUid(verifierPackageName, 0, callingUserId)) {
+                return true;
+            }
         }
 
         // Allow package uninstaller to silently uninstall.
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index 7352018..d2a5e32 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -54,7 +54,7 @@
     private final StorageEventHelper mStorageEventHelper;
     private final DomainVerificationManagerInternal mDomainVerificationManager;
     private final PackageInstallerService mInstallerService;
-    private final String mRequiredVerifierPackage;
+    private final String[] mRequiredVerifierPackages;
     private final KnownPackages mKnownPackages;
     private final ChangedPackagesTracker mChangedPackagesTracker;
     private final ArrayMap<String, FeatureInfo> mAvailableFeatures;
@@ -65,7 +65,7 @@
             PermissionManagerServiceInternal permissionManager,
             StorageEventHelper storageEventHelper,
             DomainVerificationManagerInternal domainVerificationManager,
-            PackageInstallerService installerService, String requiredVerifierPackage,
+            PackageInstallerService installerService, String[] requiredVerifierPackages,
             KnownPackages knownPackages,
             ChangedPackagesTracker changedPackagesTracker,
             ArrayMap<String, FeatureInfo> availableFeatures,
@@ -75,7 +75,7 @@
         mStorageEventHelper = storageEventHelper;
         mDomainVerificationManager = domainVerificationManager;
         mInstallerService = installerService;
-        mRequiredVerifierPackage = requiredVerifierPackage;
+        mRequiredVerifierPackages = requiredVerifierPackages;
         mKnownPackages = knownPackages;
         mChangedPackagesTracker = changedPackagesTracker;
         mAvailableFeatures = availableFeatures;
@@ -313,26 +313,28 @@
             ipw.decreaseIndent();
         }
 
-        if (dumpState.isDumping(DumpState.DUMP_VERIFIERS)
-                && packageName == null) {
-            final String requiredVerifierPackage = mRequiredVerifierPackage;
-            if (!checkin) {
+        if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+            if (!checkin && mRequiredVerifierPackages.length > 0) {
                 if (dumpState.onTitlePrinted()) {
                     pw.println();
                 }
                 pw.println("Verifiers:");
-                pw.print("  Required: ");
-                pw.print(requiredVerifierPackage);
-                pw.print(" (uid=");
-                pw.print(snapshot.getPackageUid(requiredVerifierPackage,
-                        MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
-                pw.println(")");
-            } else if (requiredVerifierPackage != null) {
-                pw.print("vrfy,");
-                pw.print(requiredVerifierPackage);
-                pw.print(",");
-                pw.println(snapshot.getPackageUid(requiredVerifierPackage,
-                        MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+            }
+            for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+                if (!checkin) {
+                    pw.print("  Required: ");
+                    pw.print(requiredVerifierPackage);
+                    pw.print(" (uid=");
+                    pw.print(snapshot.getPackageUid(requiredVerifierPackage,
+                            MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+                    pw.println(")");
+                } else {
+                    pw.print("vrfy,");
+                    pw.print(requiredVerifierPackage);
+                    pw.print(",");
+                    pw.println(snapshot.getPackageUid(requiredVerifierPackage,
+                            MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+                }
             }
         }
 
@@ -642,17 +644,19 @@
     private void dumpProto(Computer snapshot, FileDescriptor fd) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
 
-        final long requiredVerifierPackageToken =
-                proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
-        proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
-                mRequiredVerifierPackage);
-        proto.write(
-                PackageServiceDumpProto.PackageShortProto.UID,
-                snapshot.getPackageUid(
-                        mRequiredVerifierPackage,
-                        MATCH_DEBUG_TRIAGED_MISSING,
-                        UserHandle.USER_SYSTEM));
-        proto.end(requiredVerifierPackageToken);
+        for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+            final long requiredVerifierPackageToken =
+                    proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+            proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
+                    requiredVerifierPackage);
+            proto.write(
+                    PackageServiceDumpProto.PackageShortProto.UID,
+                    snapshot.getPackageUid(
+                            requiredVerifierPackage,
+                            MATCH_DEBUG_TRIAGED_MISSING,
+                            UserHandle.USER_SYSTEM));
+            proto.end(requiredVerifierPackageToken);
+        }
 
         DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
         ComponentName verifierComponent = proxy.getComponentName();
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 122ab10..52e3fd9 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -46,6 +46,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.om.OverlayConfig;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.EventLogTags;
@@ -401,4 +402,9 @@
     public List<ScanPartition> getDirsToScanAsSystem() {
         return mDirsToScanAsSystem;
     }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public int getSystemScanFlags() {
+        return mSystemScanFlags;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8bb9b84..728d2d1 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2719,15 +2719,16 @@
                             installerPackageName, null /*finishedReceiver*/,
                             updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
                 }
-                // if the required verifier is defined, but, is not the installer of record
-                // for the package, it gets notified
-                final boolean notifyVerifier = mPm.mRequiredVerifierPackage != null
-                        && !mPm.mRequiredVerifierPackage.equals(installerPackageName);
-                if (notifyVerifier) {
-                    mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
-                            extras, 0 /*flags*/,
-                            mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
-                            updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+                // Notify required verifier(s) that are not the installer of record for the package.
+                for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+                    if (verifierPackageName != null && !verifierPackageName.equals(
+                            installerPackageName)) {
+                        mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+                                extras, 0 /*flags*/,
+                                verifierPackageName, null /*finishedReceiver*/,
+                                updateUserIds, instantUserIds, null /* broadcastAllowList */,
+                                null);
+                    }
                 }
                 // If package installer is defined, notify package installer about new
                 // app installed
@@ -2752,12 +2753,14 @@
                                 updateUserIds, instantUserIds, null /*broadcastAllowList*/,
                                 null);
                     }
-                    if (notifyVerifier) {
-                        mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
-                                extras, 0 /*flags*/,
-                                mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
-                                updateUserIds, instantUserIds, null /*broadcastAllowList*/,
-                                null);
+                    for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+                        if (verifierPackageName != null && !verifierPackageName.equals(
+                                installerPackageName)) {
+                            mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
+                                    packageName, extras, 0 /*flags*/, verifierPackageName,
+                                    null /*finishedReceiver*/, updateUserIds, instantUserIds,
+                                    null /*broadcastAllowList*/, null);
+                        }
                     }
                     mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
                             null /*package*/, null /*extras*/, 0 /*flags*/,
diff --git a/services/core/java/com/android/server/pm/KnownPackages.java b/services/core/java/com/android/server/pm/KnownPackages.java
index 04376b4..dcf7152 100644
--- a/services/core/java/com/android/server/pm/KnownPackages.java
+++ b/services/core/java/com/android/server/pm/KnownPackages.java
@@ -79,7 +79,7 @@
     private final String mRequiredInstallerPackage;
     private final String mRequiredUninstallerPackage;
     private final String mSetupWizardPackage;
-    private final String mRequiredVerifierPackage;
+    private final String[] mRequiredVerifierPackages;
     private final String mDefaultTextClassifierPackage;
     private final String mSystemTextClassifierPackageName;
     private final String mRequiredPermissionControllerPackage;
@@ -94,7 +94,7 @@
 
     KnownPackages(DefaultAppProvider defaultAppProvider, String requiredInstallerPackage,
             String requiredUninstallerPackage, String setupWizardPackage,
-            String requiredVerifierPackage, String defaultTextClassifierPackage,
+            String[] requiredVerifierPackages, String defaultTextClassifierPackage,
             String systemTextClassifierPackageName, String requiredPermissionControllerPackage,
             String configuratorPackage, String incidentReportApproverPackage,
             String ambientContextDetectionPackage, String appPredictionServicePackage,
@@ -104,7 +104,7 @@
         mRequiredInstallerPackage = requiredInstallerPackage;
         mRequiredUninstallerPackage = requiredUninstallerPackage;
         mSetupWizardPackage = setupWizardPackage;
-        mRequiredVerifierPackage = requiredVerifierPackage;
+        mRequiredVerifierPackages = requiredVerifierPackages;
         mDefaultTextClassifierPackage = defaultTextClassifierPackage;
         mSystemTextClassifierPackageName = systemTextClassifierPackageName;
         mRequiredPermissionControllerPackage = requiredPermissionControllerPackage;
@@ -182,7 +182,7 @@
             case PACKAGE_SYSTEM:
                 return new String[]{"android"};
             case PACKAGE_VERIFIER:
-                return snapshot.filterOnlySystemPackages(mRequiredVerifierPackage);
+                return snapshot.filterOnlySystemPackages(mRequiredVerifierPackages);
             case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
                 return snapshot.filterOnlySystemPackages(
                         mDefaultTextClassifierPackage, mSystemTextClassifierPackageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 32b3e6a..8b40f65 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -238,6 +238,7 @@
 
 import dalvik.system.VMRuntime;
 
+import libcore.util.EmptyArray;
 import libcore.util.HexEncoding;
 
 import java.io.ByteArrayInputStream;
@@ -521,6 +522,9 @@
 
     private static final String COMPANION_PACKAGE_NAME = "com.android.companiondevicemanager";
 
+    // How many required verifiers can be on the system.
+    private static final int REQUIRED_VERIFIERS_MAX_COUNT = 2;
+
     // Compilation reasons.
     public static final int REASON_FIRST_BOOT = 0;
     public static final int REASON_BOOT_AFTER_OTA = 1;
@@ -906,7 +910,7 @@
     final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<>();
     int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
 
-    final @Nullable String mRequiredVerifierPackage;
+    final @NonNull String[] mRequiredVerifierPackages;
     final @NonNull String mRequiredInstallerPackage;
     final @NonNull String mRequiredUninstallerPackage;
     final @NonNull String mRequiredPermissionControllerPackage;
@@ -1642,7 +1646,7 @@
         mProtectedPackages = testParams.protectedPackages;
         mSeparateProcesses = testParams.separateProcesses;
         mViewCompiler = testParams.viewCompiler;
-        mRequiredVerifierPackage = testParams.requiredVerifierPackage;
+        mRequiredVerifierPackages = testParams.requiredVerifierPackages;
         mRequiredInstallerPackage = testParams.requiredInstallerPackage;
         mRequiredUninstallerPackage = testParams.requiredUninstallerPackage;
         mRequiredPermissionControllerPackage = testParams.requiredPermissionControllerPackage;
@@ -2126,7 +2130,7 @@
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                     SystemClock.uptimeMillis());
 
-            mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(computer);
+            mRequiredVerifierPackages = getRequiredButNotReallyRequiredVerifiersLPr(computer);
             mRequiredInstallerPackage = getRequiredInstallerLPr(computer);
             mRequiredUninstallerPackage = getRequiredUninstallerLPr(computer);
             ComponentName intentFilterVerifierComponent =
@@ -2265,8 +2269,8 @@
                 "persist.pm.mock-upgrade", false /* default */);
     }
 
-    @Nullable
-    private String getRequiredButNotReallyRequiredVerifierLPr(@NonNull Computer computer) {
+    @NonNull
+    private String[] getRequiredButNotReallyRequiredVerifiersLPr(@NonNull Computer computer) {
         final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches =
@@ -2274,13 +2278,23 @@
                         PACKAGE_MIME_TYPE,
                         MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.USER_SYSTEM, Binder.getCallingUid());
-        if (matches.size() == 1) {
-            return matches.get(0).getComponentInfo().packageName;
-        } else if (matches.size() == 0) {
+        final int size = matches.size();
+        if (size == 0) {
             Log.w(TAG, "There should probably be a verifier, but, none were found");
-            return null;
+            return EmptyArray.STRING;
+        } else if (size <= REQUIRED_VERIFIERS_MAX_COUNT) {
+            String[] verifiers = new String[size];
+            for (int i = 0; i < size; ++i) {
+                verifiers[i] = matches.get(i).getComponentInfo().packageName;
+                if (TextUtils.isEmpty(verifiers[i])) {
+                    throw new RuntimeException("Invalid verifier: " + matches);
+                }
+            }
+            return verifiers;
         }
-        throw new RuntimeException("There must be exactly one verifier; found " + matches);
+        throw new RuntimeException(
+                "There must be no more than " + REQUIRED_VERIFIERS_MAX_COUNT + " verifiers; found "
+                        + matches);
     }
 
     @NonNull
@@ -3153,8 +3167,12 @@
 
     boolean isCallerVerifier(@NonNull Computer snapshot, int callingUid) {
         final int callingUserId = UserHandle.getUserId(callingUid);
-        return mRequiredVerifierPackage != null && callingUid == snapshot.getPackageUid(
-                mRequiredVerifierPackage, 0, callingUserId);
+        for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+            if (callingUid == snapshot.getPackageUid(requiredVerifierPackage, 0, callingUserId)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     public boolean isPackageDeviceAdminOnAnyUser(@NonNull Computer snapshot, String packageName) {
@@ -4665,15 +4683,28 @@
         }
 
         @Override
-        public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+        public void extendVerificationTimeout(int verificationId, int verificationCodeAtTimeout,
                 long millisecondsToDelay) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                    "Only package verification agents can extend verification timeouts");
+            // Negative ids correspond to testing verifiers and will be silently enforced in
+            // the handler thread.
+            if (verificationId >= 0) {
+                mContext.enforceCallingOrSelfPermission(
+                        Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+                        "Only package verification agents can extend verification timeouts");
+            }
             final int callingUid = Binder.getCallingUid();
 
             mHandler.post(() -> {
+                final int id = verificationId >= 0 ? verificationId : -verificationId;
                 final PackageVerificationState state = mPendingVerification.get(id);
+                if (state == null || state.timeoutExtended() || !state.checkRequiredVerifierUid(
+                        callingUid)) {
+                    // Only allow calls from required verifiers.
+                    return;
+                }
+
+                state.extendTimeout();
+
                 final PackageVerificationResponse response = new PackageVerificationResponse(
                         verificationCodeAtTimeout, callingUid);
 
@@ -4685,14 +4716,10 @@
                     delay = 0;
                 }
 
-                if ((state != null) && !state.timeoutExtended()) {
-                    state.extendTimeout();
-
-                    final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
-                    msg.arg1 = id;
-                    msg.obj = response;
-                    mHandler.sendMessageDelayed(msg, delay);
-                }
+                final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
+                msg.arg1 = id;
+                msg.obj = response;
+                mHandler.sendMessageDelayed(msg, delay);
             });
         }
 
@@ -5434,13 +5461,19 @@
 
             final long callingId = Binder.clearCallingIdentity();
             try {
-                final PackageStateInternal packageState =
-                        snapshot.getPackageStateForInstalledAndFiltered(
-                                packageName, callingUid, userId);
+                final PackageStateInternal packageState = snapshot.getPackageStateInternal(
+                        packageName);
                 if (packageState == null) {
                     return false;
                 }
 
+                final PackageUserStateInternal userState = packageState.getUserStateOrDefault(
+                        userId);
+                if (userState.isHidden() == hidden || !userState.isInstalled()
+                        || snapshot.shouldFilterApplication(packageState, callingUid, userId)) {
+                    return false;
+                }
+
                 // Cannot hide static shared libs as they are considered
                 // a part of the using app (emulating static linking). Also
                 // static libs are installed always on internal storage.
@@ -5470,10 +5503,6 @@
                     return false;
                 }
 
-                if (packageState.getUserStateOrDefault(userId).isHidden() == hidden) {
-                    return false;
-                }
-
                 commitPackageStateMutation(null, packageName, packageState1 ->
                         packageState1.userState(userId).setHidden(hidden));
 
@@ -5862,18 +5891,32 @@
         }
 
         @Override
-        public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                    "Only package verification agents can verify applications");
+        public void verifyPendingInstall(int verificationId, int verificationCode)
+                throws RemoteException {
+            // Negative ids correspond to testing verifiers and will be silently enforced in
+            // the handler thread.
+            if (verificationId >= 0) {
+                mContext.enforceCallingOrSelfPermission(
+                        Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+                        "Only package verification agents can verify applications");
+            }
             final int callingUid = Binder.getCallingUid();
 
-            final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
-            final PackageVerificationResponse response = new PackageVerificationResponse(
-                    verificationCode, callingUid);
-            msg.arg1 = id;
-            msg.obj = response;
-            mHandler.sendMessage(msg);
+            mHandler.post(() -> {
+                final int id = verificationId >= 0 ? verificationId : -verificationId;
+                final PackageVerificationState state = mPendingVerification.get(id);
+                if (state == null || !state.checkRequiredVerifierUid(callingUid)) {
+                    // Only allow calls from required verifiers.
+                    return;
+                }
+
+                final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
+                final PackageVerificationResponse response = new PackageVerificationResponse(
+                        verificationCode, callingUid);
+                msg.arg1 = id;
+                msg.obj = response;
+                mHandler.sendMessage(msg);
+            });
         }
 
         @Override
@@ -5928,7 +5971,7 @@
                     mRequiredInstallerPackage,
                     mRequiredUninstallerPackage,
                     mSetupWizardPackage,
-                    mRequiredVerifierPackage,
+                    mRequiredVerifierPackages,
                     mDefaultTextClassifierPackage,
                     mSystemTextClassifierPackageName,
                     mRequiredPermissionControllerPackage,
@@ -5949,7 +5992,7 @@
                 protectedBroadcasts = new ArraySet<>(mProtectedBroadcasts);
             }
             new DumpHelper(mPermissionManager, mStorageEventHelper,
-                    mDomainVerificationManager, mInstallerService, mRequiredVerifierPackage,
+                    mDomainVerificationManager, mInstallerService, mRequiredVerifierPackages,
                     knownPackages, mChangedPackagesTracker, availableFeatures, protectedBroadcasts,
                     getPerUidReadTimeouts(snapshot)
             ).doDump(snapshot, fd, pw, args);
@@ -6956,7 +6999,7 @@
                 mRequiredInstallerPackage,
                 mRequiredUninstallerPackage,
                 mSetupWizardPackage,
-                mRequiredVerifierPackage,
+                mRequiredVerifierPackages,
                 mDefaultTextClassifierPackage,
                 mSystemTextClassifierPackageName,
                 mRequiredPermissionControllerPackage,
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index f44d922..ec1b29e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -80,7 +80,7 @@
     public @NonNull String requiredInstallerPackage;
     public @NonNull String requiredPermissionControllerPackage;
     public @NonNull String requiredUninstallerPackage;
-    public @Nullable String requiredVerifierPackage;
+    public @NonNull String[] requiredVerifierPackages;
     public String[] separateProcesses;
     public @NonNull String servicesExtensionPackageName;
     public @Nullable String setupWizardPackage;
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index d105fc4..a574fc9 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -30,7 +30,7 @@
 
     private final SparseBooleanArray mSufficientVerifierUids;
 
-    private int mRequiredVerifierUid;
+    private final SparseBooleanArray mRequiredVerifierUids;
 
     private boolean mSufficientVerificationComplete;
 
@@ -51,6 +51,9 @@
     PackageVerificationState(VerifyingSession verifyingSession) {
         mVerifyingSession = verifyingSession;
         mSufficientVerifierUids = new SparseBooleanArray();
+        mRequiredVerifierUids = new SparseBooleanArray();
+        mRequiredVerificationComplete = false;
+        mRequiredVerificationPassed = true;
         mExtendedTimeout = false;
     }
 
@@ -58,9 +61,14 @@
         return mVerifyingSession;
     }
 
-    /** Sets the user ID of the required package verifier. */
-    void setRequiredVerifierUid(int uid) {
-        mRequiredVerifierUid = uid;
+    /** Add the user ID of the required package verifier. */
+    void addRequiredVerifierUid(int uid) {
+        mRequiredVerifierUids.put(uid, true);
+    }
+
+    /** Returns true if the uid a required verifier. */
+    boolean checkRequiredVerifierUid(int uid) {
+        return mRequiredVerifierUids.get(uid, false);
     }
 
     /**
@@ -80,39 +88,55 @@
      * @return {@code true} if the verifying agent actually exists in our list
      */
     boolean setVerifierResponse(int uid, int code) {
-        if (uid == mRequiredVerifierUid) {
-            mRequiredVerificationComplete = true;
+        if (mRequiredVerifierUids.get(uid)) {
             switch (code) {
                 case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT:
                     mSufficientVerifierUids.clear();
                     // fall through
                 case PackageManager.VERIFICATION_ALLOW:
-                    mRequiredVerificationPassed = true;
+                    // Two possible options:
+                    // - verification result is true,
+                    // - another verifier set it to false.
+                    // In both cases we don't need to assign anything, just exit.
                     break;
                 default:
                     mRequiredVerificationPassed = false;
             }
-            return true;
-        } else {
-            if (mSufficientVerifierUids.get(uid)) {
-                if (code == PackageManager.VERIFICATION_ALLOW) {
-                    mSufficientVerificationComplete = true;
-                    mSufficientVerificationPassed = true;
-                }
 
-                mSufficientVerifierUids.delete(uid);
-                if (mSufficientVerifierUids.size() == 0) {
-                    mSufficientVerificationComplete = true;
-                }
-
-                return true;
+            mRequiredVerifierUids.delete(uid);
+            if (mRequiredVerifierUids.size() == 0) {
+                mRequiredVerificationComplete = true;
             }
+            return true;
+        } else if (mSufficientVerifierUids.get(uid)) {
+            if (code == PackageManager.VERIFICATION_ALLOW) {
+                mSufficientVerificationPassed = true;
+                mSufficientVerificationComplete = true;
+            }
+
+            mSufficientVerifierUids.delete(uid);
+            if (mSufficientVerifierUids.size() == 0) {
+                mSufficientVerificationComplete = true;
+            }
+
+            return true;
         }
 
         return false;
     }
 
     /**
+     * Mark the session as passed required verification.
+     */
+    void passRequiredVerification() {
+        if (mRequiredVerifierUids.size() > 0) {
+            throw new RuntimeException("Required verifiers still present.");
+        }
+        mRequiredVerificationPassed = true;
+        mRequiredVerificationComplete = true;
+    }
+
+    /**
      * Returns whether verification is considered complete. This means that the required verifier
      * and at least one of the sufficient verifiers has returned a positive verification.
      *
@@ -137,15 +161,15 @@
      * @return {@code true} if installation should be allowed
      */
     boolean isInstallAllowed() {
-        if (!mRequiredVerificationComplete) {
+        if (!mRequiredVerificationComplete || !mRequiredVerificationPassed) {
             return false;
         }
 
         if (mSufficientVerificationComplete) {
-            return mRequiredVerificationPassed && mSufficientVerificationPassed;
+            return mSufficientVerificationPassed;
         }
 
-        return mRequiredVerificationPassed;
+        return true;
     }
 
     /** Extend the timeout for this Package to be verified. */
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index f931ba8..01aecd9 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -126,10 +126,9 @@
                 unmodifiablePackages.add(packageName);
                 continue;
             }
-            final PackageStateInternal packageState =
-                    snapshot.getPackageStateForInstalledAndFiltered(
-                            packageName, callingUid, userId);
-            if (packageState == null) {
+            final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
+            if (packageState == null || !packageState.getUserStateOrDefault(userId).isInstalled()
+                    || snapshot.shouldFilterApplication(packageState, callingUid, userId)) {
                 Slog.w(TAG, "Could not find package setting for package: " + packageName
                         + ". Skipping suspending/un-suspending.");
                 unmodifiablePackages.add(packageName);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e022f15..0c1c265 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -6010,6 +6010,10 @@
 
         } // synchronized (mPackagesLock)
 
+        // Multiple Users on Multiple Display info
+        pw.println("  Supports users on secondary displays: "
+                + UserManager.isUsersOnSecondaryDisplaysEnabled());
+
         // Dump some capabilities
         pw.println();
         pw.print("  Max users: " + UserManager.getMaxSupportedUsers());
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 9bad4a8..0a39e64 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -353,45 +353,54 @@
         }
         final int verifierUserId = verifierUser.getIdentifier();
 
-        String requiredVerifierPackage = mPm.mRequiredVerifierPackage;
-        boolean requiredVerifierPackageOverridden = false;
+        String[] requiredVerifierPackages = mPm.mRequiredVerifierPackages;
+        boolean requiredVerifierPackagesOverridden = false;
 
         // Allow verifier override for ADB installations which could already be unverified using
         // PackageManager.INSTALL_DISABLE_VERIFICATION flag.
         if ((mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0
                 && (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) == 0) {
-            final String adbVerifierOverridePackage = SystemProperties.get(
-                    "debug.pm.adb_verifier_override_package", "");
-            // Check if the package installed.
-            if (!TextUtils.isEmpty(adbVerifierOverridePackage)
-                    && packageExists(adbVerifierOverridePackage)) {
-                // Pretend we requested to disable verification from command line.
-                boolean requestedDisableVerification = true;
-                // If this returns false then the caller can already skip verification, so we are
-                // not adding a new way to disable verifications.
-                if (!isAdbVerificationEnabled(pkgLite, verifierUserId,
-                        requestedDisableVerification)) {
-                    requiredVerifierPackage = adbVerifierOverridePackage;
-                    requiredVerifierPackageOverridden = true;
+            String property = SystemProperties.get("debug.pm.adb_verifier_override_packages", "");
+            if (!TextUtils.isEmpty(property)) {
+                String[] verifierPackages = property.split(";");
+                List<String> adbVerifierOverridePackages = new ArrayList<>();
+                for (String verifierPackage : verifierPackages) {
+                    if (!TextUtils.isEmpty(verifierPackage) && packageExists(verifierPackage)) {
+                        adbVerifierOverridePackages.add(verifierPackage);
+                    }
+                }
+                // Check if the package installed.
+                if (adbVerifierOverridePackages.size() > 0) {
+                    // Pretend we requested to disable verification from command line.
+                    boolean requestedDisableVerification = true;
+                    // If this returns false then the caller can already skip verification, so we
+                    // are not adding a new way to disable verifications.
+                    if (!isAdbVerificationEnabled(pkgLite, verifierUserId,
+                            requestedDisableVerification)) {
+                        requiredVerifierPackages = adbVerifierOverridePackages.toArray(
+                                new String[adbVerifierOverridePackages.size()]);
+                        requiredVerifierPackagesOverridden = true;
+                    }
                 }
             }
         }
 
+        if (mOriginInfo.mExisting || !isVerificationEnabled(pkgLite, verifierUserId,
+                requiredVerifierPackages)) {
+            verificationState.passRequiredVerification();
+            return;
+        }
+
         /*
          * Determine if we have any installed package verifiers. If we
          * do, then we'll defer to them to verify the packages.
          */
         final Computer snapshot = mPm.snapshotComputer();
-        final int requiredUid = requiredVerifierPackage == null ? -1
-                : snapshot.getPackageUid(requiredVerifierPackage,
-                        MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
-        verificationState.setRequiredVerifierUid(requiredUid);
-        final boolean isVerificationEnabled = isVerificationEnabled(pkgLite,
-                verifierUserId);
 
-        if (mOriginInfo.mExisting || !isVerificationEnabled) {
-            verificationState.setVerifierResponse(requiredUid, PackageManager.VERIFICATION_ALLOW);
-            return;
+        for (String requiredVerifierPackage : requiredVerifierPackages) {
+            final int requiredUid = snapshot.getPackageUid(requiredVerifierPackage,
+                    MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
+            verificationState.addRequiredVerifierUid(requiredUid);
         }
 
         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
@@ -428,11 +437,13 @@
         final String baseCodePath = mPackageLite.getBaseApkPath();
         final String[] splitCodePaths = mPackageLite.getSplitApkPaths();
 
+        final String rootHashString;
         if (IncrementalManager.isIncrementalPath(baseCodePath)) {
-            final String rootHashString =
-                    PackageManagerServiceUtils.buildVerificationRootHashString(
-                            baseCodePath, splitCodePaths);
+            rootHashString = PackageManagerServiceUtils.buildVerificationRootHashString(
+                    baseCodePath, splitCodePaths);
             verification.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
+        } else {
+            rootHashString = null;
         }
 
         verification.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
@@ -503,8 +514,8 @@
             }
         }
 
-        if (requiredVerifierPackage == null) {
-            Slog.e(TAG, "Required verifier is null");
+        if (requiredVerifierPackages.length == 0) {
+            Slog.e(TAG, "No required verifiers");
             return;
         }
 
@@ -514,47 +525,75 @@
         } else {
             verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
         }
-        final PackageVerificationResponse response = new PackageVerificationResponse(
-                verificationCodeAtTimeout, requiredUid);
 
-        /*
-         * Send the intent to the required verification agent,
-         * but only start the verification timeout after the
-         * target BroadcastReceivers have run.
-         */
-        if (!requiredVerifierPackageOverridden) {
-            final ComponentName requiredVerifierComponent = matchComponentForVerifier(
-                    requiredVerifierPackage, receivers.getList());
-            verification.setComponent(requiredVerifierComponent);
-        } else {
-            verification.setPackage(requiredVerifierPackage);
-        }
-        idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
-                requiredVerifierPackage, verificationTimeout,
-                verifierUserId, false,
-                REASON_PACKAGE_VERIFIER, "package verifier");
+        for (String requiredVerifierPackage : requiredVerifierPackages) {
+            final int requiredUid = snapshot.getPackageUid(requiredVerifierPackage,
+                    MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
 
-        if (streaming) {
-            // For streaming installations, count verification timeout from the broadcast.
-            startVerificationTimeoutCountdown(verificationId, streaming, response,
-                    verificationTimeout);
-        }
+            final Intent requiredIntent;
+            final String receiverPermission;
+            if (!requiredVerifierPackagesOverridden || requiredVerifierPackages.length == 1) {
+                // Prod code OR test code+single verifier.
+                requiredIntent = new Intent(verification);
+                if (!requiredVerifierPackagesOverridden) {
+                    ComponentName requiredVerifierComponent = matchComponentForVerifier(
+                            requiredVerifierPackage, receivers.getList());
+                    requiredIntent.setComponent(requiredVerifierComponent);
+                } else {
+                    requiredIntent.setPackage(requiredVerifierPackage);
+                }
+                receiverPermission = android.Manifest.permission.PACKAGE_VERIFICATION_AGENT;
+            } else {
+                // Test code+multiple verifiers.
+                // Recreate the intent to contain test-only information.
+                requiredIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+                requiredIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                requiredIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                requiredIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+                requiredIntent.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
+                        PACKAGE_MIME_TYPE);
+                requiredIntent.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
+                requiredIntent.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
+                if (rootHashString != null) {
+                    requiredIntent.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH,
+                            rootHashString);
+                }
+                requiredIntent.setPackage(requiredVerifierPackage);
+                // Negative verification id.
+                requiredIntent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, -verificationId);
+                // OK not to have permission.
+                receiverPermission = null;
+            }
 
-        mPm.mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
-                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                /* appOp= */ AppOpsManager.OP_NONE,
-                /* options= */ options.toBundle(),
-                new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        if (!streaming) {
-                            // For NON-streaming installations, count verification timeout from
-                            // the broadcast was processed by all receivers.
-                            startVerificationTimeoutCountdown(verificationId, streaming, response,
-                                    verificationTimeout);
+            idleController.addPowerSaveTempWhitelistApp(Process.myUid(), requiredVerifierPackage,
+                    verificationTimeout, verifierUserId, false, REASON_PACKAGE_VERIFIER,
+                    "package verifier");
+
+            final PackageVerificationResponse response = new PackageVerificationResponse(
+                    verificationCodeAtTimeout, requiredUid);
+
+            if (streaming) {
+                // For streaming installations, count verification timeout from the broadcast.
+                startVerificationTimeoutCountdown(verificationId, streaming, response,
+                        verificationTimeout);
+            }
+
+            // Send the intent to the required verification agent, but only start the
+            // verification timeout after the target BroadcastReceivers have run.
+            mPm.mContext.sendOrderedBroadcastAsUser(requiredIntent, verifierUser,
+                    receiverPermission, AppOpsManager.OP_NONE, options.toBundle(),
+                    new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            if (!streaming) {
+                                // For NON-streaming installations, count verification timeout from
+                                // the broadcast was processed by all receivers.
+                                startVerificationTimeoutCountdown(verificationId, streaming,
+                                        response, verificationTimeout);
+                            }
                         }
-                    }
-                }, null, 0, null, null);
+                    }, null, 0, null, null);
+        }
 
         Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
 
@@ -617,7 +656,8 @@
      *
      * @return true if verification should be performed
      */
-    private boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId) {
+    private boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId,
+            String[] requiredVerifierPackages) {
         if (!DEFAULT_VERIFY_ENABLE) {
             return false;
         }
@@ -634,18 +674,21 @@
 
         // only when not installed from ADB, skip verification for instant apps when
         // the installer and verifier are the same.
-        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
-            if (mPm.mInstantAppInstallerActivity != null
-                    && mPm.mInstantAppInstallerActivity.packageName.equals(
-                    mPm.mRequiredVerifierPackage)) {
-                try {
-                    mPm.mInjector.getSystemService(AppOpsManager.class)
-                            .checkPackage(installerUid, mPm.mRequiredVerifierPackage);
-                    if (DEBUG_VERIFY) {
-                        Slog.i(TAG, "disable verification for instant app");
+        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
+                && mPm.mInstantAppInstallerActivity != null) {
+            String installerPackage = mPm.mInstantAppInstallerActivity.packageName;
+            for (String requiredVerifierPackage : requiredVerifierPackages) {
+                if (installerPackage.equals(requiredVerifierPackage)) {
+                    try {
+                        mPm.mInjector.getSystemService(AppOpsManager.class)
+                                .checkPackage(installerUid, requiredVerifierPackage);
+                        if (DEBUG_VERIFY) {
+                            Slog.i(TAG, "disable verification for instant app");
+                        }
+                        return false;
+                    } catch (SecurityException ignore) {
                     }
-                    return false;
-                } catch (SecurityException ignore) { }
+                }
             }
         }
         return true;
diff --git a/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java b/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
new file mode 100644
index 0000000..1497684
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.pm.pkg.component;
+
+
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.server.SystemConfig;
+import com.android.server.pm.pkg.parsing.ParsingPackage;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Utility methods for handling the tag {@code <install-constraints/>}
+ *
+ * @hide
+ */
+public class InstallConstraintsTagParser {
+
+    private static final String TAG_FINGERPRINT_PREFIX = "fingerprint-prefix";
+
+    /**
+     * @hide
+     */
+    public static ParseResult<ParsingPackage> parseInstallConstraints(
+            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        Set<String> allowlist = SystemConfig.getInstance().getInstallConstraintsAllowlist();
+        if (!allowlist.contains(pkg.getPackageName())) {
+            return input.skip("install-constraints cannot be used by this package");
+        }
+
+        ParseResult<Set<String>> prefixes = parseFingerprintPrefixes(input, res, parser);
+        if (prefixes.isSuccess()) {
+            if (validateFingerprintPrefixes(prefixes.getResult())) {
+                return input.success(pkg);
+            } else {
+                return input.skip(
+                        "Install of this package is restricted on this device; device fingerprint"
+                                + " does not start with one of the allowed prefixes");
+            }
+        }
+        return input.skip(prefixes.getErrorMessage());
+    }
+
+    private static ParseResult<Set<String>> parseFingerprintPrefixes(
+            ParseInput input, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        Set<String> prefixes = new ArraySet<>();
+        int type;
+        while (true) {
+            // move to the tag that contains the next prefix
+            type = parser.next();
+            if (type == XmlPullParser.END_TAG) {
+                if (prefixes.size() == 0) {
+                    return input.error("install-constraints must contain at least one constraint");
+                }
+                return input.success(prefixes);
+            } else if (type == XmlPullParser.START_TAG) {
+                if (parser.getName().equals(TAG_FINGERPRINT_PREFIX)) {
+                    ParseResult<String> parsedPrefix =
+                            readFingerprintPrefixValue(input, res, parser);
+                    if (parsedPrefix.isSuccess()) {
+                        prefixes.add(parsedPrefix.getResult());
+                    } else {
+                        return input.error(parsedPrefix.getErrorMessage());
+                    }
+                } else {
+                    return input.error("Unexpected tag: " + parser.getName());
+                }
+
+                // consume the end tag of this attribute
+                type = parser.next();
+                if (type != XmlPullParser.END_TAG) {
+                    return input.error("Expected end tag; instead got " + type);
+                }
+            }
+        }
+    }
+
+    private static ParseResult<String> readFingerprintPrefixValue(ParseInput input, Resources res,
+            XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser,
+                R.styleable.AndroidManifestInstallConstraintsFingerprintPrefix);
+        try {
+            String value = sa.getString(
+                    R.styleable.AndroidManifestInstallConstraintsFingerprintPrefix_value);
+            if (value == null) {
+                return input.error("Failed to specify prefix value");
+            }
+            return input.success(value);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static boolean validateFingerprintPrefixes(Set<String> prefixes) {
+        String fingerprint = Build.FINGERPRINT;
+        for (String prefix : prefixes) {
+            if (fingerprint.startsWith(prefix)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
index ee59810..8f953e7 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
@@ -293,6 +293,10 @@
                         pi.requestedPermissionsFlags[i] |=
                                 PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
                     }
+                    if (pkg.getImplicitPermissions().contains(pi.requestedPermissions[i])) {
+                        pi.requestedPermissionsFlags[i] |=
+                                PackageInfo.REQUESTED_PERMISSION_IMPLICIT;
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index b60b9a0..5b8f473 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -94,6 +94,7 @@
 import com.android.server.pm.permission.CompatibilityPermissionInfo;
 import com.android.server.pm.pkg.component.ComponentMutateUtils;
 import com.android.server.pm.pkg.component.ComponentParseUtils;
+import com.android.server.pm.pkg.component.InstallConstraintsTagParser;
 import com.android.server.pm.pkg.component.ParsedActivity;
 import com.android.server.pm.pkg.component.ParsedActivityUtils;
 import com.android.server.pm.pkg.component.ParsedApexSystemService;
@@ -168,9 +169,11 @@
 
     public static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
     public static final String TAG_APPLICATION = "application";
+    public static final String TAG_ATTRIBUTION = "attribution";
     public static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
     public static final String TAG_EAT_COMMENT = "eat-comment";
     public static final String TAG_FEATURE_GROUP = "feature-group";
+    public static final String TAG_INSTALL_CONSTRAINTS = "install-constraints";
     public static final String TAG_INSTRUMENTATION = "instrumentation";
     public static final String TAG_KEY_SETS = "key-sets";
     public static final String TAG_MANIFEST = "manifest";
@@ -178,15 +181,16 @@
     public static final String TAG_OVERLAY = "overlay";
     public static final String TAG_PACKAGE = "package";
     public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
-    public static final String TAG_ATTRIBUTION = "attribution";
     public static final String TAG_PERMISSION = "permission";
     public static final String TAG_PERMISSION_GROUP = "permission-group";
     public static final String TAG_PERMISSION_TREE = "permission-tree";
+    public static final String TAG_PROFILEABLE = "profileable";
     public static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
     public static final String TAG_QUERIES = "queries";
+    public static final String TAG_RECEIVER = "receiver";
     public static final String TAG_RESTRICT_UPDATE = "restrict-update";
-    public static final String TAG_SUPPORT_SCREENS = "supports-screens";
     public static final String TAG_SUPPORTS_INPUT = "supports-input";
+    public static final String TAG_SUPPORT_SCREENS = "supports-screens";
     public static final String TAG_USES_CONFIGURATION = "uses-configuration";
     public static final String TAG_USES_FEATURE = "uses-feature";
     public static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
@@ -195,8 +199,6 @@
     public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
     public static final String TAG_USES_SDK = "uses-sdk";
     public static final String TAG_USES_SPLIT = "uses-split";
-    public static final String TAG_PROFILEABLE = "profileable";
-    public static final String TAG_RECEIVER = "receiver";
 
     public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
     public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
@@ -1026,6 +1028,8 @@
                 return input.success(pkg);
             case TAG_RESTRICT_UPDATE:
                 return parseRestrictUpdateHash(flags, input, pkg, res, parser);
+            case TAG_INSTALL_CONSTRAINTS:
+                return parseInstallConstraints(input, pkg, res, parser);
             case TAG_QUERIES:
                 return parseQueries(input, pkg, res, parser);
             default:
@@ -1719,6 +1723,12 @@
         return input.success(pkg);
     }
 
+    private static ParseResult<ParsingPackage> parseInstallConstraints(
+            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        return InstallConstraintsTagParser.parseInstallConstraints(input, pkg, res, parser);
+    }
+
     private static ParseResult<ParsingPackage> parseQueries(ParseInput input, ParsingPackage pkg,
             Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
         final int depth = parser.getDepth();
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e062c38..abedd96 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -131,6 +131,7 @@
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.am.PendingIntentRecord;
 import com.android.server.pm.InstantAppResolver;
 import com.android.server.power.ShutdownCheckPoints;
@@ -2095,6 +2096,49 @@
             }
         }
 
+        // Log activity starts which violate one of the following rules of the
+        // activity security model (ASM):
+        // 1. Only the top activity on a task can start activities on that task
+        // 2. Only the top activity on the top task can create new (top) tasks
+        // We don't currently block, but these checks may later become blocks
+        // TODO(b/236234252): Shift to BackgroundActivityStartController once
+        // class is ready
+        if (mSourceRecord != null) {
+            int callerUid = mSourceRecord.getUid();
+            ActivityRecord targetTopActivity =
+                    targetTask != null ? targetTask.getTopNonFinishingActivity() : null;
+            boolean passesAsmChecks = newTask
+                    ? mRootWindowContainer.hasResumedActivity(callerUid)
+                    : targetTopActivity != null && targetTopActivity.getUid() == callerUid;
+
+            if (!passesAsmChecks) {
+                Slog.i(TAG, "Launching r: " + r
+                        + " from background: " + mSourceRecord
+                        + ". New task: " + newTask);
+                boolean newOrEmptyTask = newTask || (targetTopActivity == null);
+                FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
+                        /* caller_uid */
+                        callerUid,
+                        /* caller_activity_class_name */
+                        mSourceRecord.info.name,
+                        /* target_task_top_activity_uid */
+                        newOrEmptyTask ? -1 : targetTopActivity.getUid(),
+                        /* target_task_top_activity_class_name */
+                        newOrEmptyTask ? null : targetTopActivity.info.name,
+                        /* target_task_is_different */
+                        newTask || !mSourceRecord.getTask().equals(targetTask),
+                        /* target_activity_uid */
+                        r.getUid(),
+                        /* target_activity_class_name */
+                        r.info.name,
+                        /* target_intent_action */
+                        r.intent.getAction(),
+                        /* target_intent_flags */
+                        r.intent.getFlags()
+                );
+            }
+        }
+
         return START_SUCCESS;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 345ec11..be995a8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -886,11 +886,12 @@
 
                 logIfTransactionTooLarge(r.intent, r.getSavedState());
 
-                if (r.isEmbedded()) {
+                final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
+                if (organizedTaskFragment != null) {
                     // Sending TaskFragmentInfo to client to ensure the info is updated before
                     // the activity creation.
                     mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
-                            r.getOrganizedTaskFragment());
+                            organizedTaskFragment);
                 }
 
                 // Create activity launch transaction.
@@ -1874,6 +1875,9 @@
         // End power mode launch before going sleep
         mService.endLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_ALL);
 
+        // Rank task layers to make sure the {@link Task#mLayerRank} is updated.
+        mRootWindowContainer.rankTaskLayers();
+
         removeSleepTimeouts();
 
         if (mGoingToSleepWakeLock.isHeld()) {
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index 2ea043a..6f19450 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -24,6 +24,7 @@
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
+import android.app.GameManagerInternal;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.Disabled;
@@ -48,6 +49,7 @@
 import android.util.Xml;
 
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.LocalServices;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -64,6 +66,7 @@
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
 
     private final ActivityTaskManagerService mService;
+    private GameManagerInternal mGameManager;
     private final AtomicFile mFile;
 
     // Compatibility state: no longer ask user to select the mode.
@@ -375,6 +378,18 @@
 
     float getCompatScale(String packageName, int uid) {
         final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+        if (mGameManager == null) {
+            mGameManager = LocalServices.getService(GameManagerInternal.class);
+        }
+        if (mGameManager != null) {
+            final int userId = userHandle.getIdentifier();
+            final float scalingFactor = mGameManager.getResolutionScalingFactor(packageName,
+                    userId);
+            if (scalingFactor > 0) {
+                return 1f / scalingFactor;
+            }
+        }
+
         if (CompatChanges.isChangeEnabled(DOWNSCALED, packageName, userHandle)) {
             if (CompatChanges.isChangeEnabled(DOWNSCALE_90, packageName, userHandle)) {
                 return 1f / 0.9f;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3e2d7c9..7a9e6a9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -398,16 +398,18 @@
 
         if (WindowConfiguration.isFloating(windowingMode)
                 || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
-            if (!stateCopied) {
-                state = new InsetsState(state);
-                stateCopied = true;
+            InsetsState newState = new InsetsState();
+
+            // Only caption and IME are needed.
+            if (state.peekSource(ITYPE_CAPTION_BAR) != null) {
+                newState.addSource(state.peekSource(ITYPE_CAPTION_BAR));
             }
-            state.removeSource(ITYPE_STATUS_BAR);
-            state.removeSource(ITYPE_NAVIGATION_BAR);
-            state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
-            if (windowingMode == WINDOWING_MODE_PINNED) {
-                state.removeSource(ITYPE_IME);
+            if (windowingMode != WINDOWING_MODE_PINNED && state.peekSource(ITYPE_IME) != null) {
+                newState.addSource(state.peekSource(ITYPE_IME));
             }
+
+            state = newState;
+            stateCopied = true;
         }
 
         return state;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 7d9dc21..552c6a5 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1820,6 +1820,10 @@
         return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
     }
 
+    boolean hasResumedActivity(int uid) {
+        return forAllActivities(ar -> ar.isState(RESUMED) && ar.getUid() == uid);
+    }
+
     boolean isTopDisplayFocusedRootTask(Task task) {
         return task != null && task == getTopDisplayFocusedRootTask();
     }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 74e1fe4..8de556a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1109,6 +1109,9 @@
         // as the one in the task because either one of them could be the alias activity.
         if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
             intent.setComponent(this.intent.getComponent());
+            // Make sure the package name the same to prevent one of the intent is set while the
+            // other one is not.
+            intent.setPackage(this.intent.getPackage());
         }
         return intent.filterEquals(this.intent);
     }
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 589618e..e6afdd6 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -586,7 +586,10 @@
         }
 
         // Cannot embed activity across TaskFragments for activity result.
-        if (a.resultTo != null && a.resultTo.getTaskFragment() != this) {
+        // If the activity that started for result is finishing, it's likely that this start mode
+        // is used to place an activity in the same task. Since the finishing activity won't be
+        // able to get the results, so it's OK to embed in a different TaskFragment.
+        if (a.resultTo != null && !a.resultTo.finishing && a.resultTo.getTaskFragment() != this) {
             return EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index a4d6f70..6ca5648 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.window.TaskFragmentOrganizer.putErrorInfoInBundle;
 import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENT_TO_TASK;
 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
@@ -28,6 +29,8 @@
 import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
 
+import static java.util.Objects.requireNonNull;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -38,6 +41,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.RemoteAnimationDefinition;
@@ -51,6 +55,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
 
@@ -70,15 +75,12 @@
     private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState =
             new ArrayMap<>();
     /**
-     * A List which manages the TaskFragment pending event {@link PendingTaskFragmentEvent}
+     * Map from {@link ITaskFragmentOrganizer} to a list of related {@link PendingTaskFragmentEvent}
      */
-    private final ArrayList<PendingTaskFragmentEvent> mPendingTaskFragmentEvents =
-            new ArrayList<>();
-
-    /** Map from {@link ITaskFragmentOrganizer} to {@link TaskFragmentTransaction}. */
-    private final ArrayMap<IBinder, TaskFragmentTransaction> mTmpOrganizerToTransactionMap =
+    private final ArrayMap<IBinder, List<PendingTaskFragmentEvent>> mPendingTaskFragmentEvents =
             new ArrayMap<>();
-    private final ArrayList<ITaskFragmentOrganizer> mTmpOrganizerList = new ArrayList<>();
+
+    private final ArraySet<Task> mTmpTaskSet = new ArraySet<>();
 
     TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
         mAtmService = atm;
@@ -94,10 +96,30 @@
         private final ITaskFragmentOrganizer mOrganizer;
         private final int mOrganizerPid;
         private final int mOrganizerUid;
+
+        /**
+         * Map from {@link TaskFragment} to the last {@link TaskFragmentInfo} sent to the
+         * organizer.
+         */
         private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
                 new WeakHashMap<>();
-        private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
-                new WeakHashMap<>();
+
+        /**
+         * Map from {@link TaskFragment} to its leaf {@link Task#mTaskId}. Embedded
+         * {@link TaskFragment} will not be reparented until it is removed.
+         */
+        private final Map<TaskFragment, Integer> mTaskFragmentTaskIds = new WeakHashMap<>();
+
+        /**
+         * Map from {@link Task#mTaskId} to the last Task {@link Configuration} sent to the
+         * organizer.
+         */
+        private final SparseArray<Configuration> mLastSentTaskFragmentParentConfigs =
+                new SparseArray<>();
+
+        /**
+         * Map from temporary activity token to the corresponding {@link ActivityRecord}.
+         */
         private final Map<IBinder, ActivityRecord> mTemporaryActivityTokens =
                 new WeakHashMap<>();
 
@@ -161,21 +183,15 @@
         TaskFragmentTransaction.Change prepareTaskFragmentAppeared(@NonNull TaskFragment tf) {
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
+            final int taskId = tf.getTask().mTaskId;
             tf.mTaskFragmentAppearedSent = true;
             mLastSentTaskFragmentInfos.put(tf, info);
-            final TaskFragmentTransaction.Change change =
-                    new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_APPEARED)
-                            .setTaskFragmentToken(tf.getFragmentToken())
-                            .setTaskFragmentInfo(info);
-            if (shouldSendTaskFragmentParentInfoChanged(tf)) {
-                // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the same Task
-                final Task task = tf.getTask();
-                mLastSentTaskFragmentParentConfigs
-                        .put(tf, new Configuration(task.getConfiguration()));
-                change.setTaskId(task.mTaskId)
-                        .setTaskConfiguration(task.getConfiguration());
-            }
-            return change;
+            mTaskFragmentTaskIds.put(tf, taskId);
+            return new TaskFragmentTransaction.Change(
+                    TYPE_TASK_FRAGMENT_APPEARED)
+                    .setTaskFragmentToken(tf.getFragmentToken())
+                    .setTaskFragmentInfo(info)
+                    .setTaskId(taskId);
         }
 
         @NonNull
@@ -183,10 +199,24 @@
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
             tf.mTaskFragmentAppearedSent = false;
             mLastSentTaskFragmentInfos.remove(tf);
-            mLastSentTaskFragmentParentConfigs.remove(tf);
+
+            // Cleanup TaskFragmentParentConfig if this is the last TaskFragment in the Task.
+            final int taskId;
+            if (mTaskFragmentTaskIds.containsKey(tf)) {
+                taskId = mTaskFragmentTaskIds.remove(tf);
+                if (!mTaskFragmentTaskIds.containsValue(taskId)) {
+                    // No more TaskFragment in the Task.
+                    mLastSentTaskFragmentParentConfigs.remove(taskId);
+                }
+            } else {
+                // This can happen if the appeared wasn't sent before remove.
+                taskId = INVALID_TASK_ID;
+            }
+
             return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_VANISHED)
                     .setTaskFragmentToken(tf.getFragmentToken())
-                    .setTaskFragmentInfo(tf.getTaskFragmentInfo());
+                    .setTaskFragmentInfo(tf.getTaskFragmentInfo())
+                    .setTaskId(taskId);
         }
 
         @Nullable
@@ -197,65 +227,39 @@
             final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf);
             if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(
                     info.getConfiguration(), lastInfo.getConfiguration())) {
-                // Parent config may have changed. The controller will check if there is any
-                // important config change for the organizer.
-                return prepareTaskFragmentParentInfoChanged(tf);
+                return null;
             }
 
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
                     tf.getName());
             mLastSentTaskFragmentInfos.put(tf, info);
-            final TaskFragmentTransaction.Change change =
-                    new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_INFO_CHANGED)
-                            .setTaskFragmentToken(tf.getFragmentToken())
-                            .setTaskFragmentInfo(info);
-            if (shouldSendTaskFragmentParentInfoChanged(tf)) {
-                // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the same Task
-                // at once.
-                // Parent config may have changed. The controller will check if there is any
-                // important config change for the organizer.
-                final Task task = tf.getTask();
-                mLastSentTaskFragmentParentConfigs
-                        .put(tf, new Configuration(task.getConfiguration()));
-                change.setTaskId(task.mTaskId)
-                        .setTaskConfiguration(task.getConfiguration());
-            }
-            return change;
+            return new TaskFragmentTransaction.Change(
+                    TYPE_TASK_FRAGMENT_INFO_CHANGED)
+                    .setTaskFragmentToken(tf.getFragmentToken())
+                    .setTaskFragmentInfo(info)
+                    .setTaskId(tf.getTask().mTaskId);
         }
 
         @Nullable
         TaskFragmentTransaction.Change prepareTaskFragmentParentInfoChanged(
-                @NonNull TaskFragment tf) {
-            if (!shouldSendTaskFragmentParentInfoChanged(tf)) {
+                @NonNull Task task) {
+            final int taskId = task.mTaskId;
+            // Check if the parent info is different from the last reported parent info.
+            final Configuration taskConfig = task.getConfiguration();
+            final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(taskId);
+            if (configurationsAreEqualForOrganizer(taskConfig, lastParentConfig)
+                    && taskConfig.windowConfiguration.getWindowingMode()
+                    == lastParentConfig.windowConfiguration.getWindowingMode()) {
                 return null;
             }
 
-            final Task parent = tf.getTask();
-            final Configuration parentConfig = parent.getConfiguration();
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
                     "TaskFragment parent info changed name=%s parentTaskId=%d",
-                    tf.getName(), parent.mTaskId);
-            mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig));
+                    task.getName(), taskId);
+            mLastSentTaskFragmentParentConfigs.put(taskId, new Configuration(taskConfig));
             return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
-                    .setTaskFragmentToken(tf.getFragmentToken())
-                    .setTaskId(parent.mTaskId)
-                    .setTaskConfiguration(parent.getConfiguration());
-        }
-
-        /** Whether the system should report TaskFragment parent info changed to the organizer. */
-        private boolean shouldSendTaskFragmentParentInfoChanged(@NonNull TaskFragment tf) {
-            final Task parent = tf.getTask();
-            if (parent == null) {
-                // The TaskFragment is not attached.
-                mLastSentTaskFragmentParentConfigs.remove(tf);
-                return false;
-            }
-            // Check if the parent info is different from the last reported parent info.
-            final Configuration parentConfig = parent.getConfiguration();
-            final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf);
-            return !configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)
-                    || parentConfig.windowConfiguration.getWindowingMode()
-                    != lastParentConfig.windowConfiguration.getWindowingMode();
+                    .setTaskId(taskId)
+                    .setTaskConfiguration(taskConfig);
         }
 
         @NonNull
@@ -345,6 +349,7 @@
             }
             mTaskFragmentOrganizerState.put(organizer.asBinder(),
                     new TaskFragmentOrganizerState(organizer, pid, uid));
+            mPendingTaskFragmentEvents.put(organizer.asBinder(), new ArrayList<>());
         }
     }
 
@@ -434,6 +439,11 @@
 
     void onTaskFragmentAppeared(@NonNull ITaskFragmentOrganizer organizer,
             @NonNull TaskFragment taskFragment) {
+        if (taskFragment.getTask() == null) {
+            Slog.w(TAG, "onTaskFragmentAppeared failed because it is not attached tf="
+                    + taskFragment);
+            return;
+        }
         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
         if (!state.addTaskFragment(taskFragment)) {
             return;
@@ -441,28 +451,15 @@
         PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment,
                 PendingTaskFragmentEvent.EVENT_APPEARED);
         if (pendingEvent == null) {
-            pendingEvent = new PendingTaskFragmentEvent.Builder(
+            addPendingEvent(new PendingTaskFragmentEvent.Builder(
                     PendingTaskFragmentEvent.EVENT_APPEARED, organizer)
                     .setTaskFragment(taskFragment)
-                    .build();
-            mPendingTaskFragmentEvents.add(pendingEvent);
+                    .build());
         }
     }
 
     void onTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
             @NonNull TaskFragment taskFragment) {
-        handleTaskFragmentInfoChanged(organizer, taskFragment,
-                PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
-    }
-
-    void onTaskFragmentParentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
-            @NonNull TaskFragment taskFragment) {
-        handleTaskFragmentInfoChanged(organizer, taskFragment,
-                PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED);
-    }
-
-    private void handleTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
-            @NonNull TaskFragment taskFragment, int eventType) {
         validateAndGetState(organizer);
         if (!taskFragment.mTaskFragmentAppearedSent) {
             // Skip if TaskFragment still not appeared.
@@ -470,45 +467,41 @@
         }
         PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment);
         if (pendingEvent == null) {
-            pendingEvent = new PendingTaskFragmentEvent.Builder(eventType, organizer)
-                            .setTaskFragment(taskFragment)
-                            .build();
+            pendingEvent = new PendingTaskFragmentEvent.Builder(
+                    PendingTaskFragmentEvent.EVENT_INFO_CHANGED, organizer)
+                    .setTaskFragment(taskFragment)
+                    .build();
         } else {
             if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) {
                 // Skipped the info changed event if vanished event is pending.
                 return;
             }
             // Remove and add for re-ordering.
-            mPendingTaskFragmentEvents.remove(pendingEvent);
+            removePendingEvent(pendingEvent);
             // Reset the defer time when TaskFragment is changed, so that it can check again if
             // the event should be sent to the organizer, for example the TaskFragment may become
             // empty.
             pendingEvent.mDeferTime = 0;
         }
-        mPendingTaskFragmentEvents.add(pendingEvent);
+        addPendingEvent(pendingEvent);
     }
 
     void onTaskFragmentVanished(@NonNull ITaskFragmentOrganizer organizer,
             @NonNull TaskFragment taskFragment) {
         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
-        for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
-            PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
-            if (taskFragment == entry.mTaskFragment) {
-                mPendingTaskFragmentEvents.remove(i);
-                if (entry.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED) {
-                    // If taskFragment appeared callback is pending, ignore the vanished request.
-                    return;
-                }
+        final List<PendingTaskFragmentEvent> pendingEvents = mPendingTaskFragmentEvents
+                .get(organizer.asBinder());
+        // Remove any pending events since this TaskFragment is being removed.
+        for (int i = pendingEvents.size() - 1; i >= 0; i--) {
+            final PendingTaskFragmentEvent event = pendingEvents.get(i);
+            if (taskFragment == event.mTaskFragment) {
+                pendingEvents.remove(i);
             }
         }
-        if (!taskFragment.mTaskFragmentAppearedSent) {
-            return;
-        }
-        final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+        addPendingEvent(new PendingTaskFragmentEvent.Builder(
                 PendingTaskFragmentEvent.EVENT_VANISHED, organizer)
                 .setTaskFragment(taskFragment)
-                .build();
-        mPendingTaskFragmentEvents.add(pendingEvent);
+                .build());
         state.removeTaskFragment(taskFragment);
     }
 
@@ -517,14 +510,13 @@
             int opType, @NonNull Throwable exception) {
         validateAndGetState(organizer);
         Slog.w(TAG, "onTaskFragmentError ", exception);
-        final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+        addPendingEvent(new PendingTaskFragmentEvent.Builder(
                 PendingTaskFragmentEvent.EVENT_ERROR, organizer)
                 .setErrorCallbackToken(errorCallbackToken)
                 .setTaskFragment(taskFragment)
                 .setException(exception)
                 .setOpType(opType)
-                .build();
-        mPendingTaskFragmentEvents.add(pendingEvent);
+                .build());
         // Make sure the error event will be dispatched if there are no other changes.
         mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal();
     }
@@ -554,11 +546,18 @@
             Slog.w(TAG, "The last TaskFragmentOrganizer no longer exists");
             return;
         }
-        final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+        addPendingEvent(new PendingTaskFragmentEvent.Builder(
                 PendingTaskFragmentEvent.EVENT_ACTIVITY_REPARENT_TO_TASK, organizer)
                 .setActivity(activity)
-                .build();
-        mPendingTaskFragmentEvents.add(pendingEvent);
+                .build());
+    }
+
+    private void addPendingEvent(@NonNull PendingTaskFragmentEvent event) {
+        mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).add(event);
+    }
+
+    private void removePendingEvent(@NonNull PendingTaskFragmentEvent event) {
+        mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).remove(event);
     }
 
     boolean isOrganizerRegistered(@NonNull ITaskFragmentOrganizer organizer) {
@@ -570,12 +569,7 @@
         // remove all of the children of the organized TaskFragment
         state.dispose();
         // Remove any pending event of this organizer.
-        for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
-            final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
-            if (event.mTaskFragmentOrg.asBinder().equals(organizer.asBinder())) {
-                mPendingTaskFragmentEvents.remove(i);
-            }
-        }
+        mPendingTaskFragmentEvents.remove(organizer.asBinder());
         mTaskFragmentOrganizerState.remove(organizer.asBinder());
     }
 
@@ -631,6 +625,8 @@
         private final Throwable mException;
         @Nullable
         private final ActivityRecord mActivity;
+        @Nullable
+        private final Task mTask;
         // Set when the event is deferred due to the host task is invisible. The defer time will
         // be the last active time of the host task.
         private long mDeferTime;
@@ -642,6 +638,7 @@
                 @Nullable IBinder errorCallbackToken,
                 @Nullable Throwable exception,
                 @Nullable ActivityRecord activity,
+                @Nullable Task task,
                 int opType) {
             mEventType = eventType;
             mTaskFragmentOrg = taskFragmentOrg;
@@ -649,6 +646,7 @@
             mErrorCallbackToken = errorCallbackToken;
             mException = exception;
             mActivity = activity;
+            mTask = task;
             mOpType = opType;
         }
 
@@ -680,11 +678,13 @@
             private Throwable mException;
             @Nullable
             private ActivityRecord mActivity;
+            @Nullable
+            private Task mTask;
             private int mOpType;
 
-            Builder(@EventType int eventType, ITaskFragmentOrganizer taskFragmentOrg) {
+            Builder(@EventType int eventType, @NonNull ITaskFragmentOrganizer taskFragmentOrg) {
                 mEventType = eventType;
-                mTaskFragmentOrg = taskFragmentOrg;
+                mTaskFragmentOrg = requireNonNull(taskFragmentOrg);
             }
 
             Builder setTaskFragment(@Nullable TaskFragment taskFragment) {
@@ -697,13 +697,18 @@
                 return this;
             }
 
-            Builder setException(@Nullable Throwable exception) {
-                mException = exception;
+            Builder setException(@NonNull Throwable exception) {
+                mException = requireNonNull(exception);
                 return this;
             }
 
-            Builder setActivity(@Nullable ActivityRecord activity) {
-                mActivity = activity;
+            Builder setActivity(@NonNull ActivityRecord activity) {
+                mActivity = requireNonNull(activity);
+                return this;
+            }
+
+            Builder setTask(@NonNull Task task) {
+                mTask = requireNonNull(task);
                 return this;
             }
 
@@ -714,17 +719,20 @@
 
             PendingTaskFragmentEvent build() {
                 return new PendingTaskFragmentEvent(mEventType, mTaskFragmentOrg, mTaskFragment,
-                        mErrorCallbackToken, mException, mActivity, mOpType);
+                        mErrorCallbackToken, mException, mActivity, mTask, mOpType);
             }
         }
     }
 
     @Nullable
     private PendingTaskFragmentEvent getLastPendingLifecycleEvent(@NonNull TaskFragment tf) {
-        for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
-            PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
-            if (tf == entry.mTaskFragment && entry.isLifecycleEvent()) {
-                return entry;
+        final ITaskFragmentOrganizer organizer = tf.getTaskFragmentOrganizer();
+        final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
+                .get(organizer.asBinder());
+        for (int i = events.size() - 1; i >= 0; i--) {
+            final PendingTaskFragmentEvent event = events.get(i);
+            if (tf == event.mTaskFragment && event.isLifecycleEvent()) {
+                return event;
             }
         }
         return null;
@@ -733,10 +741,13 @@
     @Nullable
     private PendingTaskFragmentEvent getPendingTaskFragmentEvent(@NonNull TaskFragment taskFragment,
             int type) {
-        for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
-            PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
-            if (taskFragment == entry.mTaskFragment && type == entry.mEventType) {
-                return entry;
+        final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
+        final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
+                .get(organizer.asBinder());
+        for (int i = events.size() - 1; i >= 0; i--) {
+            final PendingTaskFragmentEvent event = events.get(i);
+            if (taskFragment == event.mTaskFragment && type == event.mEventType) {
+                return event;
             }
         }
         return null;
@@ -762,12 +773,25 @@
                 || mPendingTaskFragmentEvents.isEmpty()) {
             return;
         }
+        final int organizerNum = mPendingTaskFragmentEvents.size();
+        for (int i = 0; i < organizerNum; i++) {
+            final ITaskFragmentOrganizer organizer = mTaskFragmentOrganizerState.get(
+                    mPendingTaskFragmentEvents.keyAt(i)).mOrganizer;
+            dispatchPendingEvents(organizer, mPendingTaskFragmentEvents.valueAt(i));
+        }
+    }
+
+    void dispatchPendingEvents(@NonNull ITaskFragmentOrganizer organizer,
+            @NonNull List<PendingTaskFragmentEvent> pendingEvents) {
+        if (pendingEvents.isEmpty()) {
+            return;
+        }
 
         final ArrayList<Task> visibleTasks = new ArrayList<>();
         final ArrayList<Task> invisibleTasks = new ArrayList<>();
         final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>();
-        for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
-            final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
+        for (int i = 0, n = pendingEvents.size(); i < n; i++) {
+            final PendingTaskFragmentEvent event = pendingEvents.get(i);
             final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
             if (task != null && (task.lastActiveTime <= event.mDeferTime
                     || !(isTaskVisible(task, visibleTasks, invisibleTasks)
@@ -783,27 +807,26 @@
             return;
         }
 
-        mTmpOrganizerToTransactionMap.clear();
-        mTmpOrganizerList.clear();
+        mTmpTaskSet.clear();
+        final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
         for (int i = 0; i < numEvents; i++) {
             final PendingTaskFragmentEvent event = candidateEvents.get(i);
-            if (!mTmpOrganizerToTransactionMap.containsKey(event.mTaskFragmentOrg.asBinder())) {
-                mTmpOrganizerToTransactionMap.put(event.mTaskFragmentOrg.asBinder(),
-                        new TaskFragmentTransaction());
-                mTmpOrganizerList.add(event.mTaskFragmentOrg);
+            if (event.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED
+                    || event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED) {
+                final Task task = event.mTaskFragment.getTask();
+                if (mTmpTaskSet.add(task)) {
+                    // Make sure the organizer know about the Task config.
+                    transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
+                            PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
+                            .setTask(task)
+                            .build()));
+                }
             }
-            mTmpOrganizerToTransactionMap.get(event.mTaskFragmentOrg.asBinder())
-                    .addChange(prepareChange(event));
+            transaction.addChange(prepareChange(event));
         }
-        final int numOrganizers = mTmpOrganizerList.size();
-        for (int i = 0; i < numOrganizers; i++) {
-            final ITaskFragmentOrganizer organizer = mTmpOrganizerList.get(i);
-            dispatchTransactionInfo(organizer,
-                    mTmpOrganizerToTransactionMap.get(organizer.asBinder()));
-        }
-        mPendingTaskFragmentEvents.removeAll(candidateEvents);
-        mTmpOrganizerToTransactionMap.clear();
-        mTmpOrganizerList.clear();
+        mTmpTaskSet.clear();
+        dispatchTransactionInfo(organizer, transaction);
+        pendingEvents.removeAll(candidateEvents);
     }
 
     private static boolean isTaskVisible(@NonNull Task task,
@@ -831,10 +854,16 @@
             return;
         }
 
+        final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
         final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+        // Make sure the organizer know about the Task config.
+        transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
+                PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
+                .setTask(taskFragment.getTask())
+                .build()));
         transaction.addChange(prepareChange(event));
         dispatchTransactionInfo(event.mTaskFragmentOrg, transaction);
-        mPendingTaskFragmentEvents.remove(event);
+        mPendingTaskFragmentEvents.get(organizer.asBinder()).remove(event);
     }
 
     private void dispatchTransactionInfo(@NonNull ITaskFragmentOrganizer organizer,
@@ -867,7 +896,7 @@
             case PendingTaskFragmentEvent.EVENT_INFO_CHANGED:
                 return state.prepareTaskFragmentInfoChanged(taskFragment);
             case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED:
-                return state.prepareTaskFragmentParentInfoChanged(taskFragment);
+                return state.prepareTaskFragmentParentInfoChanged(event.mTask);
             case PendingTaskFragmentEvent.EVENT_ERROR:
                 return state.prepareTaskFragmentError(event.mErrorCallbackToken, taskFragment,
                         event.mOpType, event.mException);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index adb8bf6..70dd9f3 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3389,6 +3389,13 @@
             pw.println(prefix + "mLastOrientationSource=" + mLastOrientationSource);
             pw.println(prefix + "deepestLastOrientationSource=" + getLastOrientationSource());
         }
+        if (mLocalInsetsSourceProviders != null && mLocalInsetsSourceProviders.size() != 0) {
+            pw.println(prefix + mLocalInsetsSourceProviders.size() + " LocalInsetsSourceProviders");
+            final String childPrefix = prefix + "  ";
+            for (int i = 0; i < mLocalInsetsSourceProviders.size(); ++i) {
+                mLocalInsetsSourceProviders.valueAt(i).dump(pw, childPrefix);
+            }
+        }
     }
 
     final void updateSurfacePositionNonOrganized() {
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index af5718f..1d56078 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -29,8 +29,10 @@
 #include <dirent.h>
 #include <jni.h>
 #include <linux/errno.h>
+#include <linux/time.h>
 #include <log/log.h>
 #include <meminfo/procmeminfo.h>
+#include <meminfo/sysmeminfo.h>
 #include <nativehelper/JNIHelp.h>
 #include <processgroup/processgroup.h>
 #include <stddef.h>
@@ -42,6 +44,7 @@
 #include <sys/sysinfo.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <utils/Timers.h>
 #include <utils/Trace.h>
 
 #include <algorithm>
@@ -457,6 +460,12 @@
     ATRACE_INSTANT_FOR_TRACK(ATRACE_COMPACTION_TRACK, "Cancel compaction");
 }
 
+static jlong com_android_server_am_CachedAppOptimizer_threadCpuTimeNs(JNIEnv*, jobject) {
+    int64_t currentCpuTime = systemTime(CLOCK_THREAD_CPUTIME_ID);
+
+    return currentCpuTime;
+}
+
 static jdouble com_android_server_am_CachedAppOptimizer_getFreeSwapPercent(JNIEnv*, jobject) {
     struct sysinfo memoryInfo;
     int error = sysinfo(&memoryInfo);
@@ -467,6 +476,16 @@
     return (double)memoryInfo.freeswap / (double)memoryInfo.totalswap;
 }
 
+static jlong com_android_server_am_CachedAppOptimizer_getUsedZramMemory() {
+    android::meminfo::SysMemInfo sysmeminfo;
+    return sysmeminfo.mem_zram_kb();
+}
+
+static jlong com_android_server_am_CachedAppOptimizer_getMemoryFreedCompaction() {
+    android::meminfo::SysMemInfo sysmeminfo;
+    return sysmeminfo.mem_compacted_kb("/sys/block/zram0/");
+}
+
 static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, jobject, jint pid,
                                                                     jint compactionFlags) {
     compactProcessOrFallback(pid, compactionFlags);
@@ -520,8 +539,13 @@
         /* name, signature, funcPtr */
         {"cancelCompaction", "()V",
          (void*)com_android_server_am_CachedAppOptimizer_cancelCompaction},
+        {"threadCpuTimeNs", "()J", (void*)com_android_server_am_CachedAppOptimizer_threadCpuTimeNs},
         {"getFreeSwapPercent", "()D",
          (void*)com_android_server_am_CachedAppOptimizer_getFreeSwapPercent},
+        {"getUsedZramMemory", "()J",
+         (void*)com_android_server_am_CachedAppOptimizer_getUsedZramMemory},
+        {"getMemoryFreedCompaction", "()J",
+         (void*)com_android_server_am_CachedAppOptimizer_getMemoryFreedCompaction},
         {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
         {"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
         {"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
diff --git a/services/proguard.flags b/services/proguard.flags
index c648f7d..c930346 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -64,6 +64,12 @@
 # Referenced via CarServiceHelperService in car-frameworks-service (avoid removing)
 -keep public class com.android.server.utils.Slogf { *; }
 
+# Referenced in wear-service
+# HIDL interfaces
+-keep public class android.hidl.base.** { *; }
+-keep public class android.hidl.manager.** { *; }
+-keep public class com.android.server.wm.WindowManagerInternal { *; }
+
 # Notification extractors
 # TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
 -keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
index 45e0d09..4ef6875 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
@@ -628,6 +628,7 @@
             CodePath.SAME, CodePath.DIFFERENT ->
                 throw AssertionError("secondDataPath cannot be a data path")
             CodePath.SYSTEM -> assertThat(codePaths[1]).isEqualTo(stubFile.parent.toString())
+            else -> {}
         }
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 2baa1ec..05cad16 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -17,12 +17,9 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-
 import static com.android.server.am.ActivityManagerService.Injector;
-import static com.android.server.am.CachedAppOptimizer.compactActionIntToString;
-
+import static com.android.server.am.CachedAppOptimizer.compactActionIntToAction;
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
@@ -37,15 +34,18 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
 import android.text.TextUtils;
-
 import androidx.test.platform.app.InstrumentationRegistry;
-
 import com.android.modules.utils.testing.TestableDeviceConfig;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.appop.AppOpsService;
 import com.android.server.wm.ActivityTaskManagerService;
-
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
@@ -55,13 +55,6 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
  * Tests for {@link CachedAppOptimizer}.
  *
@@ -147,36 +140,40 @@
     @Test
     public void init_setsDefaults() {
         mCachedAppOptimizerUnderTest.init();
-        assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isEqualTo(
-                CachedAppOptimizer.DEFAULT_USE_COMPACTION);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeFull).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_2);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullSome).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
-                CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
-        assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
-                CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6);
-        assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
-        assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
-        assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
-                CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+        synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+            assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_USE_COMPACTION);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeFull).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_2);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullSome).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
+            assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6);
+            assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+            assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
+            assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
+                    CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+        }
 
 
         Set<Integer> expected = new HashSet<>();
@@ -192,6 +189,7 @@
                 CachedAppOptimizer.DEFAULT_USE_FREEZER);
     }
 
+    @SuppressWarnings("GuardedBy")
     @Test
     public void init_withDeviceConfigSetsParameters() {
         // When the DeviceConfig already has a flag value stored (note this test will need to
@@ -256,11 +254,11 @@
         assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isTrue();
         assertThat(mCachedAppOptimizerUnderTest.mCachedAppOptimizerThread.isAlive()).isTrue();
 
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
-                compactActionIntToString(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+                .isEqualTo(compactActionIntToAction(
                         (CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1));
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
-                compactActionIntToString(
+        assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+                .isEqualTo(compactActionIntToAction(
                         (CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1));
         assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
                 CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1);
@@ -412,10 +410,12 @@
             assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
             // Then the updates are reflected in the flags.
-            assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
-                    compactActionIntToString(expectedSome));
-            assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
-                    compactActionIntToString(expectedFull));
+            synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+                assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+                        .isEqualTo(compactActionIntToAction(expectedSome));
+                assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+                        .isEqualTo(compactActionIntToAction(expectedFull));
+            }
         }
     }
 
@@ -431,11 +431,15 @@
                 CachedAppOptimizer.KEY_COMPACT_ACTION_2, "foo", false);
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
-        // Then the default values are reflected in the flag
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+        synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+            // Then the default values are reflected in the flag
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+        }
 
         mCountDown = new CountDownLatch(2);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -444,10 +448,14 @@
                 CachedAppOptimizer.KEY_COMPACT_ACTION_2, "", false);
         assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
 
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
-        assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
-                compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+        synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+            assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+                    .isEqualTo(
+                            compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+        }
     }
 
     @Test
@@ -893,7 +901,9 @@
         mProcessDependencies.setRss(rssBefore1);
         mProcessDependencies.setRssAfterCompaction(rssAfter1); //
         // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // THEN process IS compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -908,7 +918,9 @@
         processRecord.mOptRecord.setLastCompactTime(
                 processRecord.mOptRecord.getLastCompactTime() - 10_000);
         // WHEN we try to run compaction.
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // THEN process IS NOT compacted - values after compaction for process 1 should remain the
         // same as from the last compaction.
@@ -924,7 +936,9 @@
         processRecord.mOptRecord.setLastCompactTime(
                 processRecord.mOptRecord.getLastCompactTime() - 10_000);
         // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // THEN process IS compacted - values after compaction for process 1 should be updated.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -965,7 +979,9 @@
         mProcessDependencies.setRss(rssBelowThreshold);
         mProcessDependencies.setRssAfterCompaction(rssBelowThresholdAfter);
         // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // THEN process IS NOT compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
@@ -974,7 +990,9 @@
         mProcessDependencies.setRss(rssAboveThreshold);
         mProcessDependencies.setRssAfterCompaction(rssAboveThresholdAfter);
         // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // THEN process IS compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1008,22 +1026,16 @@
         mProcessDependencies.setRss(rssBefore);
         mProcessDependencies.setRssAfterCompaction(rssAfter);
 
-        // Compaction should occur if (setAdj < min for process || setAdj > max for process) &&
-        // (MIN < curAdj <  MAX)
-        // GIVEN OomAdj score below threshold.
-        processRecord.mState.setSetAdj(899);
-        processRecord.mState.setCurAdj(970);
-        // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        // When moving within cached state
+        mCachedAppOptimizerUnderTest.onOomAdjustChanged(
+                ProcessList.CACHED_APP_MIN_ADJ, ProcessList.CACHED_APP_MIN_ADJ + 1, processRecord);
         waitForHandler();
         // THEN process IS NOT compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
 
-        // GIVEN (setAdj < MIN || setAdj > MAX) && (MIN < curAdj <  MAX)
-        processRecord.mState.setSetAdj(910);
-        processRecord.mState.setCurAdj(930);
-        // WHEN we try to run compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        // When moving into cached state
+        mCachedAppOptimizerUnderTest.onOomAdjustChanged(ProcessList.CACHED_APP_MIN_ADJ - 1,
+                ProcessList.CACHED_APP_MIN_ADJ + 1, processRecord);
         waitForHandler();
         // THEN process IS compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1057,13 +1069,17 @@
         processRecord.mState.setCurAdj(100);
 
         // Compact process full
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // the process is not compacted
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
 
         // Compact process some
-        mCachedAppOptimizerUnderTest.compactAppSome(processRecord, false);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.SOME, CachedAppOptimizer.CompactSource.APP,
+                false);
         waitForHandler();
         // the process is not compacted
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
@@ -1072,7 +1088,9 @@
         processRecord.mState.setCurAdj(100);
 
         // We force a full compaction
-        mCachedAppOptimizerUnderTest.compactAppFull(processRecord, true);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+                true);
         waitForHandler();
         // then process is compacted.
         assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1080,13 +1098,13 @@
         mCachedAppOptimizerUnderTest.mLastCompactionStats.clear();
 
         // We force a some compaction
-        mCachedAppOptimizerUnderTest.compactAppSome(processRecord, true);
+        mCachedAppOptimizerUnderTest.compactApp(processRecord,
+                CachedAppOptimizer.CompactProfile.SOME, CachedAppOptimizer.CompactSource.APP, true);
         waitForHandler();
         // then process is compacted.
-        String executedCompactAction =
-                compactActionIntToString(processRecord.mOptRecord.getLastCompactAction());
-        assertThat(executedCompactAction)
-                .isEqualTo(mCachedAppOptimizerUnderTest.mCompactActionSome);
+        CachedAppOptimizer.CompactProfile executedCompactProfile =
+                processRecord.mOptRecord.getLastCompactProfile();
+        assertThat(executedCompactProfile).isEqualTo(CachedAppOptimizer.CompactProfile.SOME);
     }
 
     private void setFlag(String key, String value, boolean defaultValue) throws Exception {
@@ -1162,7 +1180,8 @@
         }
 
         @Override
-        public void performCompaction(String action, int pid) throws IOException {
+        public void performCompaction(CachedAppOptimizer.CompactAction action, int pid)
+                throws IOException {
             mRss = mRssAfterCompaction;
         }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 8d59dce..598c6b0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -40,6 +40,7 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static com.android.server.am.OomAdjuster.OOM_ADJ_REASON_ACTIVITY;
 import static com.android.server.am.ProcessList.BACKUP_APP_ADJ;
 import static com.android.server.am.ProcessList.CACHED_APP_MAX_ADJ;
 import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
@@ -146,6 +147,7 @@
     private static PackageManagerInternal sPackageManagerInternal;
     private static ActivityManagerService sService;
 
+    @SuppressWarnings("GuardedBy")
     @BeforeClass
     public static void setUpOnce() {
         sContext = getInstrumentation().getTargetContext();
@@ -196,7 +198,7 @@
                 new ActivityManagerService.Injector(sContext));
         doReturn(mock(AppOpsManager.class)).when(sService).getAppOpsManager();
         doCallRealMethod().when(sService).enqueueOomAdjTargetLocked(any(ProcessRecord.class));
-        doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(any(String.class));
+        doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ACTIVITY);
         setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
         doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
                 .enqueueProcessChangeItemLocked(anyInt(), anyInt());
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index d675b0a..b53a2c6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -201,7 +201,6 @@
     public void tearDown() throws Exception {
         LocalServices.removeServiceForTest(PowerManagerInternal.class);
         GameManagerService gameManagerService = new GameManagerService(mMockContext);
-        gameManagerService.disableCompatScale(mPackageName);
         if (mMockingSession != null) {
             mMockingSession.finishMocking();
         }
@@ -450,13 +449,13 @@
 
 
         startUser(gameManagerService, USER_ID_1);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         mockModifyGameModeGranted();
         assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
         // We need to make sure the mode is supported before setting it.
         mockDeviceConfigAll();
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
         assertEquals(GameManager.GAME_MODE_STANDARD,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
@@ -534,8 +533,8 @@
 
         startUser(gameManagerService, USER_ID_1);
         startUser(gameManagerService, USER_ID_2);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
-        gameManagerService.updateConfigsForUser(USER_ID_2, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_2, true, mPackageName);
 
         // Set User 1 to Standard
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
@@ -563,7 +562,7 @@
         if (gameManagerService == null) {
             gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
             startUser(gameManagerService, USER_ID_1);
-            gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+            gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         }
         ArraySet<Integer> reportedModes = new ArraySet<>();
         int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
@@ -578,20 +577,20 @@
     }
 
     private void checkDownscaling(GameManagerService gameManagerService,
-                int gameMode, String scaling) {
+                int gameMode, float scaling) {
         if (gameManagerService == null) {
             gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
             startUser(gameManagerService, USER_ID_1);
-            gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+            gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         }
         GameManagerService.GamePackageConfiguration config =
                 gameManagerService.getConfig(mPackageName);
-        assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling);
+        assertEquals(scaling, config.getGameModeConfiguration(gameMode).getScaling(), 0.01f);
     }
 
     private void checkAngleEnabled(GameManagerService gameManagerService, int gameMode,
             boolean angleEnabled) {
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
 
         // Validate GamePackageConfiguration returns the correct value.
         GameManagerService.GamePackageConfiguration config =
@@ -604,7 +603,7 @@
 
     private void checkLoadingBoost(GameManagerService gameManagerService, int gameMode,
             int loadingBoost) {
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
 
         // Validate GamePackageConfiguration returns the correct value.
         GameManagerService.GamePackageConfiguration config =
@@ -621,7 +620,7 @@
         if (gameManagerService == null) {
             gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
             startUser(gameManagerService, USER_ID_1);
-            gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+            gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         }
         GameManagerService.GamePackageConfiguration config =
                 gameManagerService.getConfig(mPackageName);
@@ -715,7 +714,7 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                 GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
     }
 
@@ -735,7 +734,7 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
                 GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
     }
 
@@ -757,9 +756,9 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                 GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
     }
 
@@ -782,7 +781,7 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                 GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
     }
 
@@ -805,7 +804,7 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
                 GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
     }
 
@@ -829,9 +828,9 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                 GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
     }
 
@@ -858,9 +857,9 @@
 
         checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                 GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
-        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
     }
 
@@ -933,7 +932,7 @@
     public void testInterventionAllowScalingDefault() throws Exception {
         mockDeviceConfigPerformance();
         mockModifyGameModeGranted();
-        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
     }
 
     /**
@@ -944,7 +943,7 @@
         mockDeviceConfigPerformance();
         mockInterventionAllowDownscaleFalse();
         mockModifyGameModeGranted();
-        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "1.0");
+        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, -1.0f);
     }
 
     /**
@@ -956,7 +955,7 @@
         mockDeviceConfigPerformance();
         mockInterventionAllowDownscaleTrue();
         mockModifyGameModeGranted();
-        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
     }
 
     /**
@@ -1091,7 +1090,7 @@
         GameManagerService gameManagerService =
                 new GameManagerService(mMockContext, mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         GameManagerService.GamePackageConfiguration config =
                 gameManagerService.getConfig(mPackageName);
         assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE));
@@ -1109,7 +1108,7 @@
                 new GameManagerService(mMockContext, mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
     }
@@ -1126,7 +1125,7 @@
                 new GameManagerService(mMockContext, mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         assertEquals(GameManager.GAME_MODE_STANDARD,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
     }
@@ -1143,7 +1142,7 @@
                 new GameManagerService(mMockContext, mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_UNSUPPORTED, USER_ID_1);
-        gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+        gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
         assertEquals(GameManager.GAME_MODE_STANDARD,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
     }
@@ -1404,4 +1403,102 @@
         assertEquals(splitLine[6], "angle=0,scaling=0.7,fps=30");
 
     }
+
+    @Test
+    public void testUpdateResolutionScalingFactor() {
+        mockModifyGameModeGranted();
+        mockDeviceConfigBattery();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+        float scalingFactor = 0.123f;
+        gameManagerService.updateResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, scalingFactor,
+                USER_ID_1);
+        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+        scalingFactor = 0.321f;
+        gameManagerService.updateResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, scalingFactor,
+                USER_ID_1);
+        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+    }
+
+    @Test
+    public void testUpdateResolutionScalingFactor_noDeviceConfig() {
+        mockModifyGameModeGranted();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+        float scalingFactor = 0.123f;
+        gameManagerService.updateResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, scalingFactor,
+                USER_ID_1);
+        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+        scalingFactor = 0.321f;
+        gameManagerService.updateResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, scalingFactor,
+                USER_ID_1);
+        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY,
+                USER_ID_1), 0.001f);
+    }
+
+    @Test
+    public void testUpdateResolutionScalingFactor_permissionDenied() {
+        mockModifyGameModeDenied();
+        mockDeviceConfigAll();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+        float scalingFactor = 0.123f;
+        assertThrows(SecurityException.class, () -> {
+            gameManagerService.updateResolutionScalingFactor(mPackageName,
+                    GameManager.GAME_MODE_BATTERY, scalingFactor,
+                    USER_ID_1);
+        });
+        mockModifyGameModeGranted();
+        assertEquals(0.7f, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+    }
+
+    @Test
+    public void testUpdateResolutionScalingFactor_noUserId() {
+        mockModifyGameModeGranted();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_2);
+        final float scalingFactor = 0.123f;
+        assertThrows(IllegalArgumentException.class, () -> {
+            gameManagerService.updateResolutionScalingFactor(mPackageName,
+                    GameManager.GAME_MODE_BATTERY, scalingFactor,
+                    USER_ID_1);
+        });
+    }
+
+    @Test
+    public void testGetResolutionScalingFactor_permissionDenied() {
+        mockModifyGameModeDenied();
+        mockDeviceConfigAll();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+        assertThrows(SecurityException.class, () -> {
+            gameManagerService.getResolutionScalingFactor(mPackageName,
+                    GameManager.GAME_MODE_BATTERY, USER_ID_1);
+        });
+    }
+
+    @Test
+    public void testGetResolutionScalingFactor_noUserId() {
+        mockModifyGameModeDenied();
+        mockDeviceConfigAll();
+        GameManagerService gameManagerService =
+                new GameManagerService(mMockContext, mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_2);
+        assertEquals(-1f, gameManagerService.getResolutionScalingFactor(mPackageName,
+                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 99693d2..7111047 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -35,6 +35,7 @@
 import android.os.HandlerThread;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.util.TypedXmlPullParser;
 import android.util.Xml;
 
@@ -97,9 +98,10 @@
         final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2);
         for(int i = 0; i < uidStates.size(); i++) {
             final AppOpsService.UidState uidState = uidStates.valueAt(i);
-            if (uidState.opModes != null) {
-                final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1);
-                final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2);
+            SparseIntArray opModes = uidState.getNonDefaultUidModes();
+            if (opModes != null) {
+                final int uidMode1 = opModes.get(op1, defaultModeOp1);
+                final int uidMode2 = opModes.get(op2, defaultModeOp2);
                 assertEquals(uidMode1, uidMode2);
                 if (uidMode1 != defaultModeOp1) {
                     numberOfNonDefaultOps++;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
new file mode 100644
index 0000000..2165301
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.pm
+
+import android.os.Build
+import android.os.SystemProperties
+import com.android.server.extendedtestutils.wheneverStatic
+import com.android.server.testutils.spy
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class InitAppsHelperTest {
+    @Rule
+    @JvmField
+    val rule = MockSystemRule()
+
+    @Before
+    fun setUp() {
+        rule.system().stageNominalSystemState()
+    }
+
+    private fun mockNoFirstBoot() {
+        // To mock that this is not the first boot
+        rule.system().stageScanExistingPackage("a.data.package", 1L,
+            rule.system().dataAppDirectory)
+    }
+
+    private fun mockFingerprintChanged() {
+        val versionInfo = Settings.VersionInfo()
+        versionInfo.fingerprint = "mockFingerprintForTesting"
+        whenever(rule.mocks().settings.internalVersion) {
+            versionInfo
+        }
+    }
+
+    private fun mockFingerprintUnchanged() {
+        // To mock that this is not the first boot
+        val versionInfo = Settings.VersionInfo()
+        versionInfo.fingerprint = MockSystem.DEFAULT_VERSION_INFO.fingerprint
+        whenever(rule.mocks().settings.internalVersion) {
+            versionInfo
+        }
+    }
+
+    private fun mockOta() {
+        wheneverStatic {
+            SystemProperties.getBoolean("persist.pm.mock-upgrade", false)
+        }.thenReturn(true)
+    }
+
+    private fun createPackageManagerService(): PackageManagerService {
+        return spy(PackageManagerService(rule.mocks().injector,
+            false /*factoryTest*/,
+            MockSystem.DEFAULT_VERSION_INFO.fingerprint,
+            false /*isEngBuild*/,
+            false /*isUserDebugBuild*/,
+            Build.VERSION_CODES.CUR_DEVELOPMENT,
+            Build.VERSION.INCREMENTAL))
+    }
+
+    @Test
+    fun testSystemScanFlagOnFirstBoot() {
+        val pms = createPackageManagerService()
+        assertThat(pms.isFirstBoot).isEqualTo(true)
+        assertThat(pms.isDeviceUpgrading).isEqualTo(false)
+        val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+            listOf<ScanPartition>())
+        assertThat(
+            initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+            .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+    }
+
+    @Test
+    fun testSystemScanFlagWithMockOTA() {
+        mockNoFirstBoot()
+        mockFingerprintUnchanged()
+        mockOta()
+        val pms = createPackageManagerService()
+        assertThat(pms.isFirstBoot).isEqualTo(false)
+        assertThat(pms.isDeviceUpgrading).isEqualTo(true)
+        val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+            listOf<ScanPartition>())
+        assertThat(
+            initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+            .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+    }
+
+    @Test
+    fun testSystemScanFlagNoOTA() {
+        mockNoFirstBoot()
+        mockFingerprintUnchanged()
+        val pms = createPackageManagerService()
+        assertThat(pms.isFirstBoot).isEqualTo(false)
+        assertThat(pms.isDeviceUpgrading).isEqualTo(false)
+        val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+            listOf<ScanPartition>())
+        assertThat(
+            initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+            .isEqualTo(0)
+    }
+
+    @Test
+    fun testSystemScanFlagWithFingerprintChanged() {
+        mockNoFirstBoot()
+        mockFingerprintChanged()
+        val pms = createPackageManagerService()
+        assertThat(pms.isFirstBoot).isEqualTo(false)
+        assertThat(pms.isDeviceUpgrading).isEqualTo(true)
+        val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+            listOf<ScanPartition>())
+        assertThat(
+            initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+            .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index 51498a6..a62569f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -23,7 +23,9 @@
 
 @Presubmit
 public class PackageVerificationStateTest extends AndroidTestCase {
-    private static final int REQUIRED_UID = 1948;
+    private static final int REQUIRED_UID_1 = 1948;
+
+    private static final int REQUIRED_UID_2 = 1949;
 
     private static final int SUFFICIENT_UID_1 = 1005;
 
@@ -31,12 +33,12 @@
 
     public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertTrue("Verification should be considered complete now",
                 state.isVerificationComplete());
@@ -47,23 +49,111 @@
 
     public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
 
         assertTrue("Verification should be considered complete now",
                 state.isVerificationComplete());
 
-        assertFalse("Installation should be marked as allowed",
+        assertFalse("Installation should be marked as denied",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_TwoRequiredVerifiers_AllowedInstall() {
+        PackageVerificationState state = new PackageVerificationState(null);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
+        state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_TwoRequiredVerifiers_DeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(null);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
+        state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as denied",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_TwoRequiredVerifiers_FirstDeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(null);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
+        state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as denied",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_TwoRequiredVerifiers_SecondDeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(null);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
+        state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as denied",
                 state.isInstallAllowed());
     }
 
     public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -78,18 +168,46 @@
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
 
         assertTrue("Verification should be considered complete now",
                 state.isVerificationComplete());
 
-        assertFalse("Installation should be marked as allowed",
+        assertFalse("Installation should be marked as denied",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndOneSufficient_OneRequiredDeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(null);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
+        state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as denied",
                 state.isInstallAllowed());
     }
 
     public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -104,7 +222,7 @@
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertTrue("Verification should be considered complete now",
                 state.isVerificationComplete());
@@ -115,7 +233,7 @@
 
     public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -131,7 +249,7 @@
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertTrue("Verification should be considered complete now",
                 state.isVerificationComplete());
@@ -142,7 +260,7 @@
 
     public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -153,7 +271,7 @@
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -174,7 +292,7 @@
 
     public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
 
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
@@ -185,7 +303,7 @@
         assertFalse("Verification should not be marked as complete yet",
                 state.isVerificationComplete());
 
-        state.setVerifierResponse(REQUIRED_UID,
+        state.setVerifierResponse(REQUIRED_UID_1,
                 PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
 
         assertTrue("Verification should be marked as complete immediately",
@@ -213,17 +331,17 @@
 
     public void testAreAllVerificationsComplete_onlyVerificationPasses() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
         assertFalse(state.areAllVerificationsComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertFalse(state.areAllVerificationsComplete());
     }
 
     public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
         assertFalse(state.areAllVerificationsComplete());
 
         state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
@@ -233,28 +351,28 @@
 
     public void testAreAllVerificationsComplete_bothPasses() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
         assertFalse(state.areAllVerificationsComplete());
 
         state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
 
         assertTrue(state.areAllVerificationsComplete());
     }
 
     public void testAreAllVerificationsComplete_onlyVerificationFails() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
         assertFalse(state.areAllVerificationsComplete());
 
-        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+        state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
 
         assertFalse(state.areAllVerificationsComplete());
     }
 
     public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
         PackageVerificationState state = new PackageVerificationState(null);
-        state.setRequiredVerifierUid(REQUIRED_UID);
+        state.addRequiredVerifierUid(REQUIRED_UID_1);
         assertFalse(state.areAllVerificationsComplete());
 
         state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index e9171c0c..92c7871 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -336,6 +336,59 @@
         assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
     }
 
+    /**
+     * Tests that readPermissions works correctly for the tag: {@code install-constraints-allowed}.
+     */
+    @Test
+    public void readPermissions_installConstraints_successful() throws IOException {
+        final String contents =
+                "<config>\n"
+                        + "    <install-constraints-allowed package=\"com.android.apex1\" />\n"
+                        + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+        readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(mSysConfig.getInstallConstraintsAllowlist())
+                .containsExactly("com.android.apex1");
+    }
+
+    /**
+     * Tests that readPermissions works correctly for the tag: {@code install-constraints-allowed}.
+     */
+    @Test
+    public void readPermissions_installConstraints_noPackage() throws IOException {
+        final String contents =
+                "<config>\n"
+                        + "    <install-constraints-allowed/>\n"
+                        + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+        readPermissions(folder, /* Grant all permission flags */ ~0);
+
+        assertThat(mSysConfig.getInstallConstraintsAllowlist()).isEmpty();
+    }
+
+    /**
+     * Tests that readPermissions works correctly for the tag {@code install-constraints-allowed}
+     * without {@link SystemConfig#ALLOW_VENDOR_APEX}.
+     */
+    @Test
+    public void readPermissions_installConstraints_noAppConfigs() throws IOException {
+        final String contents =
+                "<config>\n"
+                        + "    <install-constraints-allowed package=\"com.android.apex1\" />\n"
+                        + "</config>";
+        final File folder = createTempSubfolder("folder");
+        createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+        readPermissions(folder,  /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
+
+        assertThat(mSysConfig.getInstallConstraintsAllowlist()).isEmpty();
+    }
+
     @Test
     public void readApexPrivAppPermissions_addAllPermissions()
             throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
new file mode 100644
index 0000000..1f7b65e
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 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 com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+
+import android.app.GameManagerInternal;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link CompatModePackages} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CompatModePackagesTests
+ */
+@SmallTest
+@Presubmit
+public class CompatModePackagesTests extends SystemServiceTestsBase {
+    ActivityTaskManagerService mAtm;
+    GameManagerInternal mGm;
+    static final String TEST_PACKAGE = "compat.mode.packages";
+    static final int TEST_USER_ID = 1;
+
+    @Before
+    public void setUp() {
+        mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
+        mGm = mock(GameManagerInternal.class);
+    }
+
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(GameManagerInternal.class);
+    }
+
+    @Test
+    public void testGetCompatScale_gameManagerReturnsPositive() {
+        LocalServices.addService(GameManagerInternal.class, mGm);
+        float scale = 0.25f;
+        doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+        assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1 / scale,
+                0.01f);
+    }
+
+    @Test
+    public void testGetCompatScale_gameManagerReturnsZero() {
+        LocalServices.addService(GameManagerInternal.class, mGm);
+        float scale = 0f;
+        doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+        assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+                0.01f);
+    }
+
+    @Test
+    public void testGetCompatScale_gameManagerReturnsNegative() {
+        LocalServices.addService(GameManagerInternal.class, mGm);
+        float scale = -1f;
+        doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+        assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+                0.01f);
+    }
+
+    @Test
+    public void testGetCompatScale_noGameManager() {
+        assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+                0.01f);
+    }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 68079f4..9e658e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -72,6 +72,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.util.MergedConfiguration;
@@ -169,7 +170,8 @@
     public void testTaskLayerRank() {
         final Task rootTask = new TaskBuilder(mSupervisor).build();
         final Task task1 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
-        new ActivityBuilder(mAtm).setTask(task1).build().mVisibleRequested = true;
+        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task1).build();
+        activity1.mVisibleRequested = true;
         mWm.mRoot.rankTaskLayers();
 
         assertEquals(1, task1.mLayerRank);
@@ -177,7 +179,8 @@
         assertEquals(Task.LAYER_RANK_INVISIBLE, rootTask.mLayerRank);
 
         final Task task2 = new TaskBuilder(mSupervisor).build();
-        new ActivityBuilder(mAtm).setTask(task2).build().mVisibleRequested = true;
+        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task2).build();
+        activity2.mVisibleRequested = true;
         mWm.mRoot.rankTaskLayers();
 
         // Note that ensureActivitiesVisible is disabled in SystemServicesTestRule, so both the
@@ -192,6 +195,17 @@
 
         assertEquals(1, task1.mLayerRank);
         assertEquals(2, task2.mLayerRank);
+
+        // The rank should be updated to invisible when device went to sleep.
+        activity1.mVisibleRequested = false;
+        activity2.mVisibleRequested = false;
+        doReturn(true).when(mAtm).isSleepingOrShuttingDownLocked();
+        doReturn(true).when(mRootWindowContainer).putTasksToSleep(anyBoolean(), anyBoolean());
+        mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+        doReturn(false).when(mSupervisor.mGoingToSleepWakeLock).isHeld();
+        mAtm.mTaskSupervisor.checkReadyForSleepLocked(false /* allowDelay */);
+        assertEquals(Task.LAYER_RANK_INVISIBLE, task1.mLayerRank);
+        assertEquals(Task.LAYER_RANK_INVISIBLE, task2.mLayerRank);
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index f38731b..8b3cff8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -75,6 +75,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 /**
  * Build/Install/Run:
@@ -92,7 +94,6 @@
     private TaskFragmentOrganizerToken mOrganizerToken;
     private ITaskFragmentOrganizer mIOrganizer;
     private TaskFragment mTaskFragment;
-    private TaskFragmentInfo mTaskFragmentInfo;
     private IBinder mFragmentToken;
     private WindowContainerTransaction mTransaction;
     private WindowContainerToken mFragmentWindowToken;
@@ -100,14 +101,19 @@
     private IBinder mErrorToken;
     private Rect mTaskFragBounds;
 
+    @Mock
+    private TaskFragmentInfo mTaskFragmentInfo;
+    @Mock
+    private Task mTask;
+
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
         mWindowOrganizerController = mAtm.mWindowOrganizerController;
         mController = mWindowOrganizerController.mTaskFragmentOrganizerController;
         mOrganizer = new TaskFragmentOrganizer(Runnable::run);
         mOrganizerToken = mOrganizer.getOrganizerToken();
         mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder());
-        mTaskFragmentInfo = mock(TaskFragmentInfo.class);
         mFragmentToken = new Binder();
         mTaskFragment =
                 new TaskFragment(mAtm, mFragmentToken, true /* createdByOrganizer */);
@@ -131,6 +137,8 @@
 
     @Test
     public void testCallTaskFragmentCallbackWithoutRegister_throwsException() {
+        doReturn(mTask).when(mTaskFragment).getTask();
+
         assertThrows(IllegalArgumentException.class, () -> mController
                 .onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment));
 
@@ -140,16 +148,21 @@
 
         assertThrows(IllegalArgumentException.class, () -> mController
                 .onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment));
-
-        assertThrows(IllegalArgumentException.class, () -> mController
-                .onTaskFragmentParentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
-                        mTaskFragment));
     }
 
     @Test
     public void testOnTaskFragmentAppeared() {
         mController.registerOrganizer(mIOrganizer);
 
+        // No-op when the TaskFragment is not attached.
+        mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+        mController.dispatchPendingEvents();
+
+        verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+
+        // Send callback when the TaskFragment is attached.
+        setupMockParent(mTaskFragment, mTask);
+
         mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
@@ -159,9 +172,21 @@
     @Test
     public void testOnTaskFragmentInfoChanged() {
         mController.registerOrganizer(mIOrganizer);
+        setupMockParent(mTaskFragment, mTask);
+
+        // No-op if onTaskFragmentAppeared is not called yet.
+        mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
+                mTaskFragment);
+        mController.dispatchPendingEvents();
+
+        verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+
+        // Call onTaskFragmentAppeared first.
         mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
+        verify(mOrganizer).onTaskFragmentAppeared(any());
+
         // No callback if the info is not changed.
         doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
         doReturn(new Configuration()).when(mTaskFragmentInfo).getConfiguration();
@@ -194,49 +219,74 @@
     }
 
     @Test
+    public void testOnTaskFragmentVanished_clearUpRemaining() {
+        mController.registerOrganizer(mIOrganizer);
+        setupMockParent(mTaskFragment, mTask);
+
+        // Not trigger onTaskFragmentAppeared.
+        mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+        mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+        mController.dispatchPendingEvents();
+
+        verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+        verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+        verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
+        verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
+
+        // Not trigger onTaskFragmentInfoChanged.
+        // Call onTaskFragmentAppeared before calling onTaskFragmentInfoChanged.
+        mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+        mController.dispatchPendingEvents();
+        clearInvocations(mOrganizer);
+        doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
+        mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
+                mTaskFragment);
+        mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+        mController.dispatchPendingEvents();
+
+        verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+        verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+        verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
+        verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
+    }
+
+    @Test
     public void testOnTaskFragmentParentInfoChanged() {
         mController.registerOrganizer(mIOrganizer);
-        final Task parent = mock(Task.class);
-        final Configuration parentConfig = new Configuration();
-        parentConfig.smallestScreenWidthDp = 10;
-        doReturn(parent).when(mTaskFragment).getTask();
-        doReturn(parentConfig).when(parent).getConfiguration();
-        // Task needs to be visible
-        parent.lastActiveTime = 100;
-        doReturn(true).when(parent).shouldBeVisible(any());
+        setupMockParent(mTaskFragment, mTask);
+        mTask.getConfiguration().smallestScreenWidthDp = 10;
 
-        mTaskFragment.mTaskFragmentAppearedSent = true;
-        mController.onTaskFragmentParentInfoChanged(
+        mController.onTaskFragmentAppeared(
                 mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
-        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
 
         // No extra callback if the info is not changed.
         clearInvocations(mOrganizer);
 
-        mController.onTaskFragmentParentInfoChanged(
+        mController.onTaskFragmentInfoChanged(
                 mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
-        verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), any());
+        verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
 
         // Trigger callback if the size is changed.
-        parentConfig.smallestScreenWidthDp = 100;
-        mController.onTaskFragmentParentInfoChanged(
+        mTask.getConfiguration().smallestScreenWidthDp = 100;
+        mController.onTaskFragmentInfoChanged(
                 mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
-        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
 
         // Trigger callback if the windowing mode is changed.
         clearInvocations(mOrganizer);
-        parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
-        mController.onTaskFragmentParentInfoChanged(
+        mTask.getConfiguration().windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
+        mController.onTaskFragmentInfoChanged(
                 mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
         mController.dispatchPendingEvents();
 
-        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+        verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
     }
 
     @Test
@@ -1091,4 +1141,15 @@
                 .put(mFragmentToken, mTaskFragment);
         mTaskFragment.getTask().setWindowingMode(WINDOWING_MODE_PINNED);
     }
+
+    /** Setups the mock Task as the parent of the given TaskFragment. */
+    private static void setupMockParent(TaskFragment taskFragment, Task mockParent) {
+        doReturn(mockParent).when(taskFragment).getTask();
+        final Configuration taskConfig = new Configuration();
+        doReturn(taskConfig).when(mockParent).getConfiguration();
+
+        // Task needs to be visible
+        mockParent.lastActiveTime = 100;
+        doReturn(true).when(mockParent).shouldBeVisible(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 1096351..88eadfc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -32,6 +32,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
+import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
 import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
 import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
 import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
@@ -468,6 +469,10 @@
         newActivity.resultTo = activity;
         assertEquals(EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT,
                 newTaskFragment.isAllowedToEmbedActivity(newActivity));
+
+        // Allow embedding if the resultTo activity is finishing.
+        activity.finishing = true;
+        assertEquals(EMBEDDING_ALLOWED, newTaskFragment.isAllowedToEmbedActivity(newActivity));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index f4323db..6a7e388 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -846,6 +846,7 @@
                 new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME, targetClassName);
 
         final Intent intent = new Intent();
+        intent.setPackage(DEFAULT_COMPONENT_PACKAGE_NAME);
         intent.setComponent(aliasComponent);
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
index 41f9fae..6fc4b67 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
@@ -31,15 +31,14 @@
     public static UsbPortHal getInstance(UsbPortManager portManager, IndentingPrintWriter pw) {
 
         logAndPrint(Log.DEBUG, null, "Querying USB HAL version");
-        if (UsbPortHidl.isServicePresent(null)) {
-            logAndPrint(Log.INFO, null, "USB HAL HIDL present");
-            return new UsbPortHidl(portManager, pw);
-        }
         if (UsbPortAidl.isServicePresent(null)) {
             logAndPrint(Log.INFO, null, "USB HAL AIDL present");
             return new UsbPortAidl(portManager, pw);
         }
-
+        if (UsbPortHidl.isServicePresent(null)) {
+            logAndPrint(Log.INFO, null, "USB HAL HIDL present");
+            return new UsbPortHidl(portManager, pw);
+        }
         return null;
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index e0ae193..e138d33 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -108,7 +108,8 @@
     }
 
     /**
-     * Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition
+     * Checks that the [ComponentMatcher.TASK_BAR] window is visible at the start and end of the
+     * transition
      *
      * Note: Large screen only
      */
@@ -132,7 +133,8 @@
     }
 
     /**
-     * Checks that the [ComponentMatcher.STATUS_BAR] layer is visible during the whole transition
+     * Checks that the [ComponentMatcher.STATUS_BAR] layer is visible at the start and end
+     * of the transition
      */
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index d173b72..5e21252 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -53,6 +53,16 @@
 }
 
 /**
+ * Checks that [ComponentMatcher.TASK_BAR] window is visible and above the app windows in
+ * all WM trace entries
+ */
+fun FlickerTestParameter.taskBarWindowIsVisibleAtEnd() {
+    assertWmEnd {
+        this.isAboveAppWindowVisible(ComponentMatcher.TASK_BAR)
+    }
+}
+
+/**
  * If [allStates] is true, checks if the stack space of all displays is fully covered
  * by any visible layer, during the whole transitions
  *
@@ -103,9 +113,25 @@
  * trace
  */
 fun FlickerTestParameter.taskBarLayerIsVisibleAtStartAndEnd() {
+    this.taskBarLayerIsVisibleAtStart()
+    this.taskBarLayerIsVisibleAtEnd()
+}
+
+/**
+ * Checks that [ComponentMatcher.TASK_BAR] layer is visible at the start of the SF
+ * trace
+ */
+fun FlickerTestParameter.taskBarLayerIsVisibleAtStart() {
     assertLayersStart {
         this.isVisible(ComponentMatcher.TASK_BAR)
     }
+}
+
+/**
+ * Checks that [ComponentMatcher.TASK_BAR] layer is visible at the end of the SF
+ * trace
+ */
+fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
     assertLayersEnd {
         this.isVisible(ComponentMatcher.TASK_BAR)
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index 6e3e74d..866e819 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -32,8 +32,12 @@
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
+import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
+import com.android.server.wm.traces.common.ComponentMatcher
 import org.junit.Assume
 import org.junit.FixMethodOrder
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -231,6 +235,42 @@
         super.appWindowBecomesTopWindow()
     }
 
+    /**
+     * Checks that the [ComponentMatcher.TASK_BAR] window is visible at the end of the transition
+     *
+     * Note: Large screen only
+     */
+    @Postsubmit
+    @Test
+    open fun taskBarWindowIsVisibleAtEnd() {
+        Assume.assumeFalse(testSpec.isTablet)
+        testSpec.taskBarWindowIsVisibleAtEnd()
+    }
+
+    /**
+     * Checks that the [ComponentMatcher.TASK_BAR] layer is visible at the end of the transition
+     *
+     * Note: Large screen only
+     */
+    @Postsubmit
+    @Test
+    open fun taskBarLayerIsVisibleAtEnd() {
+        Assume.assumeFalse(testSpec.isTablet)
+        testSpec.taskBarLayerIsVisibleAtEnd()
+    }
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is locked at the start")
+    override fun taskBarWindowIsAlwaysVisible() =
+        super.taskBarWindowIsAlwaysVisible()
+
+    /** {@inheritDoc} */
+    @Test
+    @Ignore("Display is locked at the start")
+    override fun taskBarLayerIsVisibleAtStartAndEnd() =
+        super.taskBarLayerIsVisibleAtStartAndEnd()
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index cbf920ac..035f911 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -472,6 +472,7 @@
   manifest_action["compatible-screens"]["screen"];
   manifest_action["supports-gl-texture"];
   manifest_action["restrict-update"];
+  manifest_action["install-constraints"]["fingerprint-prefix"];
   manifest_action["package-verifier"];
   manifest_action["meta-data"] = meta_data_action;
   manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
diff --git a/tools/xmlpersistence/src/main/kotlin/Generator.kt b/tools/xmlpersistence/src/main/kotlin/Generator.kt
index b2c5f4a..8e62388 100644
--- a/tools/xmlpersistence/src/main/kotlin/Generator.kt
+++ b/tools/xmlpersistence/src/main/kotlin/Generator.kt
@@ -149,6 +149,7 @@
                 when (field) {
                     is ClassFieldInfo -> this += field.allClassFields
                     is ListFieldInfo -> this += field.element.allClassFields
+                    else -> {}
                 }
             }
         }