Merge "Temp skip /product folder during root-hash calculation." into tm-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index d6a067d..2c0b6e9 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -800,6 +800,7 @@
     method public boolean hasRequestForegroundServiceExemption();
     method public boolean isPrivilegedApp();
     method public boolean isSystemApp();
+    method public void setEnableOnBackInvokedCallback(boolean);
     field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
     field public int privateFlags;
   }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c7c654a..3b1943b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2537,8 +2537,8 @@
      * restriction} for a certain app-op.
      */
     private static RestrictionBypass[] sOpAllowSystemRestrictionBypass = new RestrictionBypass[] {
-            null, //COARSE_LOCATION
-            null, //FINE_LOCATION
+            new RestrictionBypass(true, false, false), //COARSE_LOCATION
+            new RestrictionBypass(true, false, false), //FINE_LOCATION
             null, //GPS
             null, //VIBRATE
             null, //READ_CONTACTS
@@ -2547,7 +2547,7 @@
             null, //WRITE_CALL_LOG
             null, //READ_CALENDAR
             null, //WRITE_CALENDAR
-            new RestrictionBypass(true, false), //WIFI_SCAN
+            new RestrictionBypass(false, true, false), //WIFI_SCAN
             null, //POST_NOTIFICATION
             null, //NEIGHBORING_CELLS
             null, //CALL_PHONE
@@ -2561,10 +2561,10 @@
             null, //READ_ICC_SMS
             null, //WRITE_ICC_SMS
             null, //WRITE_SETTINGS
-            new RestrictionBypass(true, false), //SYSTEM_ALERT_WINDOW
+            new RestrictionBypass(false, true, false), //SYSTEM_ALERT_WINDOW
             null, //ACCESS_NOTIFICATIONS
             null, //CAMERA
-            new RestrictionBypass(false, true), //RECORD_AUDIO
+            new RestrictionBypass(false, false, true), //RECORD_AUDIO
             null, //PLAY_AUDIO
             null, //READ_CLIPBOARD
             null, //WRITE_CLIPBOARD
@@ -2582,7 +2582,7 @@
             null, //MONITOR_HIGH_POWER_LOCATION
             null, //GET_USAGE_STATS
             null, //MUTE_MICROPHONE
-            new RestrictionBypass(true, false), //TOAST_WINDOW
+            new RestrictionBypass(false, true, false), //TOAST_WINDOW
             null, //PROJECT_MEDIA
             null, //ACTIVATE_VPN
             null, //WALLPAPER
@@ -2614,7 +2614,7 @@
             null, // ACCEPT_HANDOVER
             null, // MANAGE_IPSEC_HANDOVERS
             null, // START_FOREGROUND
-            new RestrictionBypass(true, false), // BLUETOOTH_SCAN
+            new RestrictionBypass(false, true, false), // BLUETOOTH_SCAN
             null, // USE_BIOMETRIC
             null, // ACTIVITY_RECOGNITION
             null, // SMS_FINANCIAL_TRANSACTIONS
@@ -3331,6 +3331,9 @@
      * @hide
      */
     public static class RestrictionBypass {
+        /** Does the app need to be system uid to bypass the restriction */
+        public boolean isSystemUid;
+
         /** Does the app need to be privileged to bypass the restriction */
         public boolean isPrivileged;
 
@@ -3340,12 +3343,14 @@
          */
         public boolean isRecordAudioRestrictionExcept;
 
-        public RestrictionBypass(boolean isPrivileged, boolean isRecordAudioRestrictionExcept) {
+        public RestrictionBypass(boolean isSystemUid, boolean isPrivileged,
+                boolean isRecordAudioRestrictionExcept) {
+            this.isSystemUid = isSystemUid;
             this.isPrivileged = isPrivileged;
             this.isRecordAudioRestrictionExcept = isRecordAudioRestrictionExcept;
         }
 
-        public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(true, true);
+        public static RestrictionBypass UNRESTRICTED = new RestrictionBypass(false, true, true);
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 315bd71..0a2b421 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1811,10 +1811,6 @@
      * #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link
      * #PROVISIONING_MODE_MANAGED_PROFILE} and {@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}.
      *
-     * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity
-     * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link
-     * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras.
-     *
      * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_PERSONALLY_OWNED}. In
      * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have
      * the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link
@@ -1834,6 +1830,10 @@
      * activity to have the {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra
      * contain only {@link #PROVISIONING_MODE_MANAGED_PROFILE}.
      *
+     * <p>Also, if this flag is set, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity
+     * will not receive the {@link #EXTRA_PROVISIONING_IMEI} and {@link
+     * #EXTRA_PROVISIONING_SERIAL_NUMBER} extras.
+     *
      * <p>This flag can be combined with {@link #FLAG_SUPPORTED_MODES_ORGANIZATION_OWNED}. In
      * that case, the admin app's {@link #ACTION_GET_PROVISIONING_MODE} activity will have the
      * {@link #EXTRA_PROVISIONING_ALLOWED_PROVISIONING_MODES} array extra contain {@link
@@ -13249,8 +13249,9 @@
      * Called by a device owner, profile owner of a managed profile or delegated app with
      * {@link #DELEGATION_NETWORK_LOGGING} to control the network logging feature.
      *
-     * <p> When network logging is enabled by a profile owner, the network logs will only include
-     * work profile network activity, not activity on the personal profile.
+     * <p> Supported for a device owner from Android 8. Supported for a profile owner of a managed
+     * profile from Android 12. When network logging is enabled by a profile owner, the network logs
+     * will only include work profile network activity, not activity on the personal profile.
      *
      * <p> Network logs contain DNS lookup and connect() library call events. The following library
      *     functions are recorded while network logging is active:
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2961b55..24c3836 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2752,4 +2752,21 @@
             mKnownActivityEmbeddingCerts.add(knownCert.toUpperCase(Locale.US));
         }
     }
+
+    /**
+     * Sets whether the application will use the {@link android.window.OnBackInvokedCallback}
+     * navigation system instead of the {@link android.view.KeyEvent#KEYCODE_BACK} and related
+     * callbacks. Intended to be used from tests only.
+     *
+     * @see #isOnBackInvokedCallbackEnabled()
+     * @hide
+     */
+    @TestApi
+    public void setEnableOnBackInvokedCallback(boolean isEnable) {
+        if (isEnable) {
+            privateFlagsExt |= PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
+        } else {
+            privateFlagsExt &= ~PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
+        }
+    }
 }
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index f9ed0e3d..3f49b73 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -37,6 +37,7 @@
 import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodSession;
 import android.view.inputmethod.InputMethodSubtype;
+import android.window.ImeOnBackInvokedDispatcher;
 
 import com.android.internal.inputmethod.CancellationGroup;
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
@@ -194,7 +195,9 @@
             case DO_START_INPUT: {
                 final SomeArgs args = (SomeArgs) msg.obj;
                 final IBinder startInputToken = (IBinder) args.arg1;
-                final IInputContext inputContext = (IInputContext) args.arg2;
+                final IInputContext inputContext = (IInputContext) ((SomeArgs) args.arg2).arg1;
+                final ImeOnBackInvokedDispatcher imeDispatcher =
+                        (ImeOnBackInvokedDispatcher) ((SomeArgs) args.arg2).arg2;
                 final EditorInfo info = (EditorInfo) args.arg3;
                 final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
                 final boolean restarting = args.argi5 == 1;
@@ -205,7 +208,7 @@
                         : null;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken,
-                        navButtonFlags);
+                        navButtonFlags, imeDispatcher);
                 args.recycle();
                 return;
             }
@@ -348,13 +351,17 @@
     @Override
     public void startInput(IBinder startInputToken, IInputContext inputContext,
             EditorInfo attribute, boolean restarting,
-            @InputMethodNavButtonFlags int navButtonFlags) {
+            @InputMethodNavButtonFlags int navButtonFlags,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         if (mCancellationGroup == null) {
             Log.e(TAG, "startInput must be called after bindInput.");
             mCancellationGroup = new CancellationGroup();
         }
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = inputContext;
+        args.arg2 = imeDispatcher;
         mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken,
-                inputContext, attribute, mCancellationGroup, restarting ? 1 : 0, navButtonFlags));
+                args, attribute, mCancellationGroup, restarting ? 1 : 0, navButtonFlags));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index efd4f06..25296bc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -101,6 +101,7 @@
 import android.view.Choreographer;
 import android.view.Gravity;
 import android.view.InputChannel;
+import android.view.InputDevice;
 import android.view.InputEventReceiver;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -134,6 +135,9 @@
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+import android.window.ImeOnBackInvokedDispatcher;
+import android.window.OnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
 import android.window.WindowMetricsHelper;
 
 import com.android.internal.annotations.GuardedBy;
@@ -344,6 +348,9 @@
      * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
      **/
     private RingBuffer<MotionEvent> mPendingEvents;
+    private ImeOnBackInvokedDispatcher mImeDispatcher;
+    private Boolean mBackCallbackRegistered = false;
+    private final OnBackInvokedCallback mCompatBackCallback = this::compatHandleBack;
 
     /**
      * Returns whether {@link InputMethodService} is responsible for rendering the back button and
@@ -797,7 +804,13 @@
         @Override
         public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
                 @NonNull EditorInfo editorInfo, boolean restarting,
-                @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags) {
+                @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
+                @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+            mImeDispatcher = imeDispatcher;
+            if (mWindow != null) {
+                mWindow.getOnBackInvokedDispatcher().setImeOnBackInvokedDispatcher(
+                        imeDispatcher);
+            }
             mPrivOps.reportStartInputAsync(startInputToken);
             mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags);
             if (restarting) {
@@ -1496,6 +1509,10 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initSoftInputWindow");
         mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
+        if (mImeDispatcher != null) {
+            mWindow.getOnBackInvokedDispatcher()
+                    .setImeOnBackInvokedDispatcher(mImeDispatcher);
+        }
         mNavigationBarController.onSoftInputWindowCreated(mWindow);
         {
             final Window window = mWindow.getWindow();
@@ -1608,6 +1625,8 @@
             // when IME developers are doing something unsupported.
             InputMethodPrivilegedOperationsRegistry.remove(mToken);
         }
+        unregisterCompatOnBackInvokedCallback();
+        mImeDispatcher = null;
     }
 
     /**
@@ -2568,9 +2587,47 @@
         cancelImeSurfaceRemoval();
         mInShowWindow = false;
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        registerCompatOnBackInvokedCallback();
     }
 
 
+    /**
+     * Registers an {@link OnBackInvokedCallback} to handle back invocation when ahead-of-time
+     *  back dispatching is enabled. We keep the {@link KeyEvent#KEYCODE_BACK} based legacy code
+     *  around to handle back on older devices.
+     */
+    private void registerCompatOnBackInvokedCallback() {
+        if (mBackCallbackRegistered) {
+            return;
+        }
+        if (mWindow != null) {
+            mWindow.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+                    OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatBackCallback);
+            mBackCallbackRegistered = true;
+        }
+    }
+
+    private void unregisterCompatOnBackInvokedCallback() {
+        if (!mBackCallbackRegistered) {
+            return;
+        }
+        if (mWindow != null) {
+            mWindow.getOnBackInvokedDispatcher()
+                    .unregisterOnBackInvokedCallback(mCompatBackCallback);
+            mBackCallbackRegistered = false;
+        }
+    }
+
+    private KeyEvent createBackKeyEvent(int action, boolean isTracking) {
+        final long when = SystemClock.uptimeMillis();
+        return new KeyEvent(when, when, action,
+                KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY
+                        | (isTracking ? KeyEvent.FLAG_TRACKING : 0),
+                InputDevice.SOURCE_KEYBOARD);
+    }
+
     private boolean prepareWindow(boolean showInput) {
         boolean doShowInput = false;
         mDecorViewVisible = true;
@@ -2658,6 +2715,7 @@
         }
         mLastWasInFullscreenMode = mIsFullscreen;
         updateFullscreenMode();
+        unregisterCompatOnBackInvokedCallback();
     }
 
     /**
@@ -3797,4 +3855,14 @@
             proto.end(token);
         }
     };
+
+    private void compatHandleBack() {
+        final KeyEvent downEvent = createBackKeyEvent(
+                KeyEvent.ACTION_DOWN, false /* isTracking */);
+        onKeyDown(KeyEvent.KEYCODE_BACK, downEvent);
+        final boolean hasStartedTracking =
+                (downEvent.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0;
+        final KeyEvent upEvent = createBackKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking);
+        onKeyUp(KeyEvent.KEYCODE_BACK, upEvent);
+    }
 }
diff --git a/core/java/android/service/quickaccesswallet/TEST_MAPPING b/core/java/android/service/quickaccesswallet/TEST_MAPPING
index 4d97ab6..5d2a3a8 100644
--- a/core/java/android/service/quickaccesswallet/TEST_MAPPING
+++ b/core/java/android/service/quickaccesswallet/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     {
       "name": "CtsQuickAccessWalletTestCases"
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2475e2c..d04b07c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9922,7 +9922,7 @@
      * <ol>
      *   <li>It should only be called when content capture is enabled for the view.
      *   <li>It must call viewAppeared() before viewDisappeared()
-     *   <li>viewAppearead() can only be called when the view is visible and laidout
+     *   <li>viewAppeared() can only be called when the view is visible and laid out
      *   <li>It should not call the same event twice.
      * </ol>
      */
@@ -9999,6 +9999,11 @@
                     Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
                 }
             }
+
+            // We reset any translation state as views may be re-used (e.g., as in ListView and
+            // RecyclerView). We only need to do this for views important for content capture since
+            // views unimportant for content capture won't be translated anyway.
+            clearTranslationState();
         }
     }
 
@@ -12719,6 +12724,21 @@
     }
 
     /**
+     * @hide
+     */
+    public void clearTranslationState() {
+        if (mViewTranslationCallback != null) {
+            mViewTranslationCallback.onClearTranslation(this);
+        }
+        clearViewTranslationCallback();
+        clearViewTranslationResponse();
+        if (hasTranslationTransientState()) {
+            setHasTransientState(false);
+            setHasTranslationTransientState(false);
+        }
+    }
+
+    /**
      * Returns true if this view is currently attached to a window.
      */
     public boolean isAttachedToWindow() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0bdbfbc..48c102b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6095,6 +6095,28 @@
 
         @Override
         protected int onProcess(QueuedInputEvent q) {
+            if (q.mEvent instanceof KeyEvent) {
+                final KeyEvent event = (KeyEvent) q.mEvent;
+
+                // If the new back dispatch is enabled, intercept KEYCODE_BACK before it reaches the
+                // view tree or IME, and invoke the appropriate {@link OnBackInvokedCallback}.
+                if (isBack(event)
+                        && mContext != null
+                        && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
+                    OnBackInvokedCallback topCallback =
+                            getOnBackInvokedDispatcher().getTopCallback();
+                    if (event.getAction() == KeyEvent.ACTION_UP) {
+                        if (topCallback != null) {
+                            topCallback.onBackInvoked();
+                            return FINISH_HANDLED;
+                        }
+                    } else {
+                        // Drop other actions such as {@link KeyEvent.ACTION_DOWN}.
+                        return FINISH_NOT_HANDLED;
+                    }
+                }
+            }
+
             if (mInputQueue != null && q.mEvent instanceof KeyEvent) {
                 mInputQueue.sendInputEvent(q.mEvent, q, true, this);
                 return DEFER;
@@ -6446,24 +6468,6 @@
                 return FINISH_HANDLED;
             }
 
-            // If the new back dispatch is enabled, intercept KEYCODE_BACK before it reaches the
-            // view tree and invoke the appropriate {@link OnBackInvokedCallback}.
-            if (isBack(event)
-                    && mContext != null
-                    && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
-                OnBackInvokedCallback topCallback =
-                        getOnBackInvokedDispatcher().getTopCallback();
-                if (event.getAction() == KeyEvent.ACTION_UP) {
-                    if (topCallback != null) {
-                        topCallback.onBackInvoked();
-                        return FINISH_HANDLED;
-                    }
-                } else {
-                    // Drop other actions such as {@link KeyEvent.ACTION_DOWN}.
-                    return FINISH_NOT_HANDLED;
-                }
-            }
-
             // Deliver the key to the view hierarchy.
             if (mView.dispatchKeyEvent(event)) {
                 return FINISH_HANDLED;
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index 6209b46..dbdc0da 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -29,6 +29,7 @@
 import android.view.InputChannel;
 import android.view.MotionEvent;
 import android.view.View;
+import android.window.ImeOnBackInvokedDispatcher;
 
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodNavButtonFlags;
@@ -232,6 +233,10 @@
      *                        long as your implementation of {@link InputMethod} relies on such
      *                        IPCs
      * @param navButtonFlags {@link InputMethodNavButtonFlags} in the initial state of this session.
+     * @param imeDispatcher The {@link ImeOnBackInvokedDispatcher }} to be set on the
+     *                      IME's {@link android.window.WindowOnBackInvokedDispatcher}, so that IME
+     *                      {@link android.window.OnBackInvokedCallback}s can be forwarded to
+     *                      the client requesting to start input.
      * @see #startInput(InputConnection, EditorInfo)
      * @see #restartInput(InputConnection, EditorInfo)
      * @see EditorInfo
@@ -240,7 +245,8 @@
     @MainThread
     default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
             @NonNull EditorInfo editorInfo, boolean restarting,
-            @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags) {
+            @NonNull IBinder startInputToken, @InputMethodNavButtonFlags int navButtonFlags,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         if (restarting) {
             restartInput(inputConnection, editorInfo);
         } else {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d9bde58..e2e9a85 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -91,6 +91,8 @@
 import android.view.ViewRootImpl;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
 import android.view.autofill.AutofillManager;
+import android.window.ImeOnBackInvokedDispatcher;
+import android.window.WindowOnBackInvokedDispatcher;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.DirectBootAwareness;
@@ -105,6 +107,7 @@
 import com.android.internal.inputmethod.StartInputReason;
 import com.android.internal.inputmethod.UnbindReason;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
@@ -279,6 +282,21 @@
     private static final String SUBTYPE_MODE_VOICE = "voice";
 
     /**
+     * Provide this to {@link IInputMethodManager#startInputOrWindowGainedFocus(
+     * int, IInputMethodClient, IBinder, int, int, int, EditorInfo, IInputContext, int)} to receive
+     * {@link android.window.OnBackInvokedCallback} registrations from IME.
+     */
+    private final ImeOnBackInvokedDispatcher mImeDispatcher =
+            new ImeOnBackInvokedDispatcher(Handler.getMain()) {
+        @Override
+        public WindowOnBackInvokedDispatcher getReceivingDispatcher() {
+            synchronized (mH) {
+                return mCurRootView != null ? mCurRootView.getOnBackInvokedDispatcher() : null;
+            }
+        }
+    };
+
+    /**
      * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
      * or indirectly relied on {@link #sInstance} via reflection or something like that.
      *
@@ -740,7 +758,8 @@
                             windowFlags,
                             null,
                             null, null,
-                            mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
+                            mCurRootView.mContext.getApplicationInfo().targetSdkVersion,
+                            mImeDispatcher);
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
                 }
@@ -1687,6 +1706,8 @@
             mServedConnecting = false;
             clearConnectionLocked();
         }
+        // Clear the back callbacks held by the ime dispatcher to avoid memory leaks.
+        mImeDispatcher.clear();
     }
 
     public void displayCompletions(View view, CompletionInfo[] completions) {
@@ -2359,7 +2380,8 @@
                         softInputMode, windowFlags, tba, servedInputConnection,
                         servedInputConnection == null ? null
                                 : servedInputConnection.asIRemoteAccessibilityInputConnection(),
-                        view.getContext().getApplicationInfo().targetSdkVersion);
+                        view.getContext().getApplicationInfo().targetSdkVersion,
+                        mImeDispatcher);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 8cf032b..6bf2474 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -158,12 +158,7 @@
             case STATE_UI_TRANSLATION_FINISHED:
                 destroyTranslators();
                 runForEachView((view, callback) -> {
-                    callback.onClearTranslation(view);
-                    view.clearViewTranslationResponse();
-                    if (view.hasTranslationTransientState()) {
-                        view.setHasTransientState(false);
-                        view.setHasTranslationTransientState(false);
-                    }
+                    view.clearTranslationState();
                 });
                 notifyTranslationFinished(/* activityDestroyed= */ false);
                 synchronized (mLock) {
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.aidl b/core/java/android/window/ImeOnBackInvokedDispatcher.aidl
new file mode 100644
index 0000000..04e6420
--- /dev/null
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/os/ParcelFileDescriptor.aidl
+**
+** Copyright 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.window;
+
+parcelable ImeOnBackInvokedDispatcher;
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
new file mode 100644
index 0000000..d5763aa
--- /dev/null
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -0,0 +1,187 @@
+/*
+ * 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.window;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * A {@link OnBackInvokedDispatcher} for IME that forwards {@link OnBackInvokedCallback}
+ * registrations from the IME process to the app process to be registered on the app window.
+ * <p>
+ * The app process creates and propagates an instance of {@link ImeOnBackInvokedDispatcher}
+ * to the IME to be set on the IME window's {@link WindowOnBackInvokedDispatcher}.
+ * <p>
+ * @see WindowOnBackInvokedDispatcher#setImeOnBackInvokedDispatcher
+ *
+ * @hide
+ */
+public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parcelable {
+
+    private static final String TAG = "ImeBackDispatcher";
+    static final String RESULT_KEY_ID = "id";
+    static final String RESULT_KEY_CALLBACK = "callback";
+    static final String RESULT_KEY_PRIORITY = "priority";
+    static final int RESULT_CODE_REGISTER = 0;
+    static final int RESULT_CODE_UNREGISTER = 1;
+    @NonNull
+    private final ResultReceiver mResultReceiver;
+
+    public ImeOnBackInvokedDispatcher(Handler handler) {
+        mResultReceiver = new ResultReceiver(handler) {
+            @Override
+            public void onReceiveResult(int resultCode, Bundle resultData) {
+                WindowOnBackInvokedDispatcher dispatcher = getReceivingDispatcher();
+                if (dispatcher != null) {
+                    receive(resultCode, resultData, dispatcher);
+                }
+            }
+        };
+    }
+
+    /**
+     * Override this method to return the {@link WindowOnBackInvokedDispatcher} of the window
+     * that should receive the forwarded callback.
+     */
+    @Nullable
+    protected WindowOnBackInvokedDispatcher getReceivingDispatcher() {
+        return null;
+    }
+
+    ImeOnBackInvokedDispatcher(Parcel in) {
+        mResultReceiver = in.readTypedObject(ResultReceiver.CREATOR);
+    }
+
+    @Override
+    public void registerOnBackInvokedCallback(
+            @OnBackInvokedDispatcher.Priority int priority,
+            @NonNull OnBackInvokedCallback callback) {
+        final Bundle bundle = new Bundle();
+        final IOnBackInvokedCallback iCallback =
+                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
+        bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
+        bundle.putInt(RESULT_KEY_PRIORITY, priority);
+        bundle.putInt(RESULT_KEY_ID, callback.hashCode());
+        mResultReceiver.send(RESULT_CODE_REGISTER, bundle);
+    }
+
+    @Override
+    public void unregisterOnBackInvokedCallback(
+            @NonNull OnBackInvokedCallback callback) {
+        Bundle bundle = new Bundle();
+        bundle.putInt(RESULT_KEY_ID, callback.hashCode());
+        mResultReceiver.send(RESULT_CODE_UNREGISTER, bundle);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedObject(mResultReceiver, flags);
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<ImeOnBackInvokedDispatcher> CREATOR =
+            new Parcelable.Creator<ImeOnBackInvokedDispatcher>() {
+                public ImeOnBackInvokedDispatcher createFromParcel(Parcel in) {
+                    return new ImeOnBackInvokedDispatcher(in);
+                }
+                public ImeOnBackInvokedDispatcher[] newArray(int size) {
+                    return new ImeOnBackInvokedDispatcher[size];
+                }
+            };
+
+    private final HashMap<Integer, OnBackInvokedCallback> mImeCallbackMap = new HashMap<>();
+
+    private void receive(
+            int resultCode, Bundle resultData,
+            @NonNull OnBackInvokedDispatcher receivingDispatcher) {
+        final int callbackId = resultData.getInt(RESULT_KEY_ID);
+        if (resultCode == RESULT_CODE_REGISTER) {
+            int priority = resultData.getInt(RESULT_KEY_PRIORITY);
+            final IOnBackInvokedCallback callback = IOnBackInvokedCallback.Stub.asInterface(
+                    resultData.getBinder(RESULT_KEY_CALLBACK));
+            registerReceivedCallback(
+                    callback, priority, callbackId, receivingDispatcher);
+        } else if (resultCode == RESULT_CODE_UNREGISTER) {
+            unregisterReceivedCallback(callbackId, receivingDispatcher);
+        }
+    }
+
+    private void registerReceivedCallback(
+            @NonNull IOnBackInvokedCallback iCallback,
+            @OnBackInvokedDispatcher.Priority int priority,
+            int callbackId,
+            @NonNull OnBackInvokedDispatcher receivingDispatcher) {
+        final ImeOnBackInvokedCallback imeCallback =
+                new ImeOnBackInvokedCallback(iCallback);
+        mImeCallbackMap.put(callbackId, imeCallback);
+        receivingDispatcher.registerOnBackInvokedCallback(priority, imeCallback);
+    }
+
+    private void unregisterReceivedCallback(
+            int callbackId, OnBackInvokedDispatcher receivingDispatcher) {
+        final OnBackInvokedCallback callback = mImeCallbackMap.get(callbackId);
+        if (callback == null) {
+            Log.e(TAG, "Ime callback not found. Ignoring unregisterReceivedCallback. "
+                    + "callbackId: " + callbackId);
+            return;
+        }
+        receivingDispatcher.unregisterOnBackInvokedCallback(callback);
+    }
+
+    /** Clears all registered callbacks on the instance. */
+    public void clear() {
+        mImeCallbackMap.clear();
+    }
+
+    static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
+        @NonNull
+        private final IOnBackInvokedCallback mIOnBackInvokedCallback;
+
+        ImeOnBackInvokedCallback(@NonNull IOnBackInvokedCallback iCallback) {
+            mIOnBackInvokedCallback = iCallback;
+        }
+
+        @Override
+        public void onBackInvoked() {
+            try {
+                if (mIOnBackInvokedCallback != null) {
+                    mIOnBackInvokedCallback.onBackInvoked();
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Exception when invoking forwarded callback. e: ", e);
+            }
+        }
+
+        IOnBackInvokedCallback getIOnBackInvokedCallback() {
+            return mIOnBackInvokedCallback;
+        }
+    }
+}
diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java
index 6bc2b50..3539049a 100644
--- a/core/java/android/window/OnBackInvokedDispatcher.java
+++ b/core/java/android/window/OnBackInvokedDispatcher.java
@@ -96,4 +96,19 @@
      * @hide
      */
     default void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) { }
+
+
+    /**
+     * Sets an {@link ImeOnBackInvokedDispatcher} to forward {@link OnBackInvokedCallback}s
+     * from IME to the app process to be registered on the app window.
+     *
+     * Only call this on the IME window. Create the {@link ImeOnBackInvokedDispatcher} from
+     * the application process and override
+     * {@link ImeOnBackInvokedDispatcher#getReceivingDispatcher()} to point to the app
+     * window's {@link WindowOnBackInvokedDispatcher}.
+     *
+     * @hide
+     */
+    default void setImeOnBackInvokedDispatcher(
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) { }
 }
diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
index 4409397..bedf503 100644
--- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java
@@ -49,6 +49,7 @@
     private final List<Pair<OnBackInvokedCallback, Integer>> mCallbacks = new ArrayList<>();
     private final Object mLock = new Object();
     private OnBackInvokedDispatcher mActualDispatcher = null;
+    private ImeOnBackInvokedDispatcher mImeDispatcher;
 
     @Override
     public void registerOnBackInvokedCallback(
@@ -108,6 +109,9 @@
             Log.v(TAG, String.format("Proxy transferring %d callbacks to %s", mCallbacks.size(),
                     mActualDispatcher));
         }
+        if (mImeDispatcher != null) {
+            mActualDispatcher.setImeOnBackInvokedDispatcher(mImeDispatcher);
+        }
         for (Pair<OnBackInvokedCallback, Integer> callbackPair : mCallbacks) {
             int priority = callbackPair.second;
             if (priority >= 0) {
@@ -117,6 +121,7 @@
             }
         }
         mCallbacks.clear();
+        mImeDispatcher = null;
     }
 
     private void clearCallbacksOnDispatcher() {
@@ -142,6 +147,7 @@
         }
         synchronized (mLock) {
             mCallbacks.clear();
+            mImeDispatcher = null;
         }
     }
 
@@ -169,4 +175,14 @@
             transferCallbacksToDispatcher();
         }
     }
+
+    @Override
+    public void setImeOnBackInvokedDispatcher(
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+        if (mActualDispatcher != null) {
+            mActualDispatcher.setImeOnBackInvokedDispatcher(imeDispatcher);
+        } else {
+            mImeDispatcher = imeDispatcher;
+        }
+    }
 }
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 781859c..edfdbcc 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -55,6 +55,8 @@
             .getInt("persist.wm.debug.predictive_back", 1) != 0;
     private static final boolean ALWAYS_ENFORCE_PREDICTIVE_BACK = SystemProperties
             .getInt("persist.wm.debug.predictive_back_always_enforce", 0) != 0;
+    @Nullable
+    private ImeOnBackInvokedDispatcher mImeDispatcher;
 
     /** Convenience hashmap to quickly decide if a callback has been added. */
     private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>();
@@ -94,6 +96,10 @@
 
     private void registerOnBackInvokedCallbackUnchecked(
             @NonNull OnBackInvokedCallback callback, @Priority int priority) {
+        if (mImeDispatcher != null) {
+            mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
+            return;
+        }
         if (!mOnBackInvokedCallbacks.containsKey(priority)) {
             mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
         }
@@ -120,6 +126,10 @@
 
     @Override
     public void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
+        if (mImeDispatcher != null) {
+            mImeDispatcher.unregisterOnBackInvokedCallback(callback);
+            return;
+        }
         if (!mAllCallbacks.containsKey(callback)) {
             if (DEBUG) {
                 Log.i(TAG, "Callback not found. returning...");
@@ -153,6 +163,9 @@
         }
         mAllCallbacks.clear();
         mOnBackInvokedCallbacks.clear();
+        if (mImeDispatcher != null) {
+            mImeDispatcher = null;
+        }
     }
 
     private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) {
@@ -160,14 +173,18 @@
             return;
         }
         try {
-            if (callback == null) {
-                mWindowSession.setOnBackInvokedCallbackInfo(mWindow, null);
-            } else {
+            OnBackInvokedCallbackInfo callbackInfo = null;
+            if (callback != null) {
                 int priority = mAllCallbacks.get(callback);
-                mWindowSession.setOnBackInvokedCallbackInfo(
-                        mWindow, new OnBackInvokedCallbackInfo(
-                                new OnBackInvokedCallbackWrapper(callback), priority));
+                final IOnBackInvokedCallback iCallback =
+                        callback instanceof ImeOnBackInvokedDispatcher
+                                    .ImeOnBackInvokedCallback
+                                ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
+                                        callback).getIOnBackInvokedCallback()
+                                : new OnBackInvokedCallbackWrapper(callback);
+                callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
             }
+            mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
             if (DEBUG && callback == null) {
                 Log.d(TAG, TextUtils.formatSimple("setTopOnBackInvokedCallback(null) Callers:%s",
                         Debug.getCallers(5, "  ")));
@@ -190,7 +207,7 @@
         return null;
     }
 
-    private static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
+    static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
         private final WeakReference<OnBackInvokedCallback> mCallback;
 
         OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
@@ -270,4 +287,10 @@
 
         return featureFlagEnabled && (appRequestsPredictiveBack || ALWAYS_ENFORCE_PREDICTIVE_BACK);
     }
+
+    @Override
+    public void setImeOnBackInvokedDispatcher(
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+        mImeDispatcher = imeDispatcher;
+    }
 }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 3fee914..781b6d5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -971,7 +971,8 @@
             getChooserActivityLogger().logShareTargetSelected(
                     SELECTION_TYPE_COPY,
                     "",
-                    -1);
+                    -1,
+                    false);
 
             setResult(RESULT_OK);
             finish();
@@ -1155,7 +1156,8 @@
                     getChooserActivityLogger().logShareTargetSelected(
                             SELECTION_TYPE_NEARBY,
                             "",
-                            -1);
+                            -1,
+                            false);
                     // Action bar is user-independent, always start as primary
                     safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
                     finish();
@@ -1177,7 +1179,8 @@
                     getChooserActivityLogger().logShareTargetSelected(
                             SELECTION_TYPE_EDIT,
                             "",
-                            -1);
+                            -1,
+                            false);
                     // Action bar is user-independent, always start as primary
                     safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
                     finish();
@@ -1754,7 +1757,8 @@
                             target.getComponentName().getPackageName()
                                     + target.getTitle().toString(),
                             mMaxHashSaltDays);
-                    directTargetAlsoRanked = getRankedPosition((SelectableTargetInfo) targetInfo);
+                    SelectableTargetInfo selectableTargetInfo = (SelectableTargetInfo) targetInfo;
+                    directTargetAlsoRanked = getRankedPosition(selectableTargetInfo);
 
                     if (mCallerChooserTargets != null) {
                         numCallerProvided = mCallerChooserTargets.length;
@@ -1762,7 +1766,8 @@
                     getChooserActivityLogger().logShareTargetSelected(
                             SELECTION_TYPE_SERVICE,
                             targetInfo.getResolveInfo().activityInfo.processName,
-                            value
+                            value,
+                            selectableTargetInfo.isPinned()
                     );
                     break;
                 case ChooserListAdapter.TARGET_CALLER:
@@ -1773,7 +1778,8 @@
                     getChooserActivityLogger().logShareTargetSelected(
                             SELECTION_TYPE_APP,
                             targetInfo.getResolveInfo().activityInfo.processName,
-                            value
+                            value,
+                            targetInfo.isPinned()
                     );
                     break;
                 case ChooserListAdapter.TARGET_STANDARD_AZ:
@@ -1784,7 +1790,8 @@
                     getChooserActivityLogger().logShareTargetSelected(
                             SELECTION_TYPE_STANDARD,
                             targetInfo.getResolveInfo().activityInfo.processName,
-                            value
+                            value,
+                            false
                     );
                     break;
             }
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
index 3217307..bb7d50a 100644
--- a/core/java/com/android/internal/app/ChooserActivityLogger.java
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -34,7 +34,8 @@
             int appProvidedApp, boolean isWorkprofile, int previewType, String intent);
 
     /** Logs a UiEventReported event for the system sharesheet when the user selects a target. */
-    void logShareTargetSelected(int targetType, String packageName, int positionPicked);
+    void logShareTargetSelected(int targetType, String packageName, int positionPicked,
+            boolean isPinned);
 
     /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */
     default void logSharesheetTriggered() {
diff --git a/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java b/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java
index 48bdba3..e3cc4f1 100644
--- a/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java
+++ b/core/java/com/android/internal/app/ChooserActivityLoggerImpl.java
@@ -51,12 +51,14 @@
     }
 
     @Override
-    public void logShareTargetSelected(int targetType, String packageName, int positionPicked) {
+    public void logShareTargetSelected(int targetType, String packageName, int positionPicked,
+            boolean isPinned) {
         FrameworkStatsLog.write(FrameworkStatsLog.RANKING_SELECTED,
                 /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(),
                 /* package_name = 2 */ packageName,
                 /* instance_id = 3 */ getInstanceId().getId(),
-                /* position_picked = 4 */ positionPicked);
+                /* position_picked = 4 */ positionPicked,
+                /* is_pinned = 5 */ isPinned);
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
index c5b21ac..e7f80a7 100644
--- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
@@ -589,7 +589,7 @@
                 MetricsLogger metricsLogger = new MetricsLogger();
                 LogMaker log = new LogMaker(MetricsEvent.ACTION_TARGET_SELECTED);
                 log.setComponentName(mRankerServiceName);
-                log.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, mAnnotationsUsed);
+                log.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, mAnnotationsUsed ? 1 : 0);
                 log.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, selectedPos);
                 metricsLogger.write(log);
             }
diff --git a/core/java/com/android/internal/logging/UiEventLoggerImpl.java b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
index 983e0fe..ffbf646 100644
--- a/core/java/com/android/internal/logging/UiEventLoggerImpl.java
+++ b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
@@ -69,7 +69,8 @@
                     /* event_id = 1 */ eventID,
                     /* package_name = 2 */ packageName,
                     /* instance_id = 3 */ 0,
-                    /* position_picked = 4 */ position);
+                    /* position_picked = 4 */ position,
+                    /* is_pinned = 5 */ false);
         }
     }
 
@@ -82,7 +83,8 @@
                     /* event_id = 1 */ eventID,
                     /* package_name = 2 */ packageName,
                     /* instance_id = 3 */ instance.getId(),
-                    /* position_picked = 4 */ position);
+                    /* position_picked = 4 */ position,
+                    /* is_pinned = 5 */ false);
         } else if ((eventID > 0)) {
             logWithPosition(event, uid, packageName, position);
         }
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index 397b2c0..62dea9d 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -137,6 +137,18 @@
      */
     public static Bitmap buildScaledBitmap(Drawable drawable, int maxWidth,
             int maxHeight) {
+        return buildScaledBitmap(drawable, maxWidth, maxHeight, false);
+    }
+
+    /**
+     * Convert a drawable to a bitmap, scaled to fit within maxWidth and maxHeight.
+     *
+     * @param allowUpscaling if true, the drawable will not only be scaled down, but also scaled up
+     *                       to fit within the maximum size given. This is useful for converting
+     *                       vectorized icons which usually have a very small intrinsic size.
+     */
+    public static Bitmap buildScaledBitmap(Drawable drawable, int maxWidth,
+            int maxHeight, boolean allowUpscaling) {
         if (drawable == null) {
             return null;
         }
@@ -155,7 +167,9 @@
         // a large notification icon if necessary
         float ratio = Math.min((float) maxWidth / (float) originalWidth,
                 (float) maxHeight / (float) originalHeight);
-        ratio = Math.min(1.0f, ratio);
+        if (!allowUpscaling) {
+            ratio = Math.min(1.0f, ratio);
+        }
         int scaledWidth = (int) (ratio * originalWidth);
         int scaledHeight = (int) (ratio * originalHeight);
         Bitmap result = Bitmap.createBitmap(scaledWidth, scaledHeight, Config.ARGB_8888);
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 40d89db..4e2526a 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -23,6 +23,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputMethodSubtype;
+import android.window.ImeOnBackInvokedDispatcher;
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
 import com.android.internal.view.IInputContext;
@@ -47,7 +48,8 @@
     void unbindInput();
 
     void startInput(in IBinder startInputToken, in IInputContext inputContext,
-            in EditorInfo attribute, boolean restarting, int navigationBarFlags);
+            in EditorInfo attribute, boolean restarting, int navigationBarFlags,
+            in ImeOnBackInvokedDispatcher imeDispatcher);
 
     void onNavButtonFlagsChanged(int navButtonFlags);
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index d7bb2cb..3157760 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -20,6 +20,7 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.EditorInfo;
+import android.window.ImeOnBackInvokedDispatcher;
 
 import com.android.internal.inputmethod.InputBindResult;
 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
@@ -57,7 +58,7 @@
             /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
             int windowFlags, in EditorInfo attribute, in IInputContext inputContext,
             in IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
-            int unverifiedTargetSdkVersion);
+            int unverifiedTargetSdkVersion, in ImeOnBackInvokedDispatcher imeDispatcher);
 
     void showInputMethodPickerFromClient(in IInputMethodClient client,
             int auxiliarySubtypeMode);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java
index 2ecc261..0dca638 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityLoggerFake.java
@@ -44,6 +44,7 @@
         // share completed fields
         public int targetType;
         public int positionPicked;
+        public boolean isPinned;
 
         CallRecord(int atomId, UiEventLogger.UiEventEnum eventId,
                 String packageName, InstanceId instanceId) {
@@ -68,12 +69,13 @@
         }
 
         CallRecord(int atomId, String packageName, InstanceId instanceId, int targetType,
-                int positionPicked) {
+                int positionPicked, boolean isPinned) {
             this.atomId = atomId;
             this.packageName = packageName;
             this.instanceId = instanceId;
             this.targetType = targetType;
             this.positionPicked = positionPicked;
+            this.isPinned = isPinned;
         }
 
     }
@@ -112,9 +114,11 @@
     }
 
     @Override
-    public void logShareTargetSelected(int targetType, String packageName, int positionPicked) {
+    public void logShareTargetSelected(int targetType, String packageName, int positionPicked,
+            boolean isPinned) {
         mCalls.add(new CallRecord(FrameworkStatsLog.RANKING_SELECTED, packageName, getInstanceId(),
-                SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), positionPicked));
+                SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), positionPicked,
+                isPinned));
     }
 
     @Override
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 0e8388b..12d3d64 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -2581,12 +2581,6 @@
       "group": "WM_DEBUG_ANIM",
       "at": "com\/android\/server\/wm\/WindowContainer.java"
     },
-    "397105698": {
-      "message": "grantEmbeddedWindowFocus remove request for win=%s dropped since no candidate was found",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "397382873": {
       "message": "Moving to PAUSED: %s %s",
       "level": "VERBOSE",
@@ -3115,6 +3109,12 @@
       "group": "WM_DEBUG_LOCKTASK",
       "at": "com\/android\/server\/wm\/LockTaskController.java"
     },
+    "958338552": {
+      "message": "grantEmbeddedWindowFocus win=%s dropped focus so setting focus to null since no candidate was found",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_FOCUS",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "959486822": {
       "message": "setSyncGroup #%d on %s",
       "level": "VERBOSE",
diff --git a/data/keyboards/Vendor_0957_Product_0001.kl b/data/keyboards/Vendor_0957_Product_0001.kl
index 13b4096..54f8808 100644
--- a/data/keyboards/Vendor_0957_Product_0001.kl
+++ b/data/keyboards/Vendor_0957_Product_0001.kl
@@ -44,33 +44,37 @@
 key 11    0
 
 # custom keys
-key usage 0x000c019C    PROFILE_SWITCH
-key usage 0x000c01A2    ALL_APPS
 key usage 0x000c01BB    TV_INPUT
-key usage 0x000c022A    BOOKMARK
-key usage 0x000c0096    SETTINGS
-key usage 0x000c009F    NOTIFICATION
-key usage 0x000c008D    GUIDE
-key usage 0x000c0089    TV
-key usage 0x000c009C    CHANNEL_UP
-key usage 0x000c009D    CHANNEL_DOWN
-key usage 0x000c00CD    MEDIA_PLAY_PAUSE
-key usage 0x000c00B2    MEDIA_RECORD
-key usage 0x000c00B4    MEDIA_SKIP_BACKWARD
-key usage 0x000c00B3    MEDIA_SKIP_FORWARD
-key usage 0x000c0226    MEDIA_STOP
 
-key usage 0x000c0077    BUTTON_3     WAKE #YouTube
-key usage 0x000c0078    BUTTON_4     WAKE #Netflix
-key usage 0x000c0079    BUTTON_6     WAKE #Disney+
-key usage 0x000c007A    BUTTON_7     WAKE #HBOmax
-
-key usage 0x00070037    PERIOD
-key usage 0x000c01BD    INFO
-key usage 0x000c0061    CAPTIONS
 key usage 0x000c0185    TV_TELETEXT
+key usage 0x000c0061    CAPTIONS
+
+key usage 0x000c01BD    INFO
+key usage 0x000c0037    PERIOD
 
 key usage 0x000c0069    PROG_RED
 key usage 0x000c006A    PROG_GREEN
+key usage 0x000c006C    PROG_YELLOW
 key usage 0x000c006B    PROG_BLUE
-key usage 0x000c006C    PROG_YELLOW
\ No newline at end of file
+key usage 0x000c00B4    MEDIA_SKIP_BACKWARD
+key usage 0x000c00CD    MEDIA_PLAY_PAUSE
+key usage 0x000c00B2    MEDIA_RECORD
+key usage 0x000c00B3    MEDIA_SKIP_FORWARD
+
+key usage 0x000c022A    BOOKMARK
+key usage 0x000c01A2    ALL_APPS
+key usage 0x000c019C    PROFILE_SWITCH
+
+key usage 0x000c0096    SETTINGS
+key usage 0x000c009F    NOTIFICATION
+
+key usage 0x000c008D    GUIDE
+key usage 0x000c0089    TV
+
+key usage 0x000c009C    CHANNEL_UP
+key usage 0x000c009D    CHANNEL_DOWN
+
+key usage 0x000c0077    BUTTON_3     WAKE #YouTube
+key usage 0x000c0078    BUTTON_4     WAKE #Netflix
+key usage 0x000c0079    BUTTON_6     WAKE
+key usage 0x000c007A    BUTTON_7     WAKE
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index c3fbe55..8fa9f56 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -246,9 +246,13 @@
      * {@link BackAnimationController}
      */
     public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
-        if (action == MotionEvent.ACTION_DOWN) {
-            initAnimation(event);
-        } else if (action == MotionEvent.ACTION_MOVE) {
+        if (action == MotionEvent.ACTION_MOVE) {
+            if (!mBackGestureStarted) {
+                // Let the animation initialized here to make sure the onPointerDownOutsideFocus
+                // could be happened when ACTION_DOWN, it may change the current focus that we
+                // would access it when startBackNavigation.
+                initAnimation(event);
+            }
             onMove(event, swipeEdge);
         } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
             ProtoLog.d(WM_SHELL_BACK_PREVIEW,
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 145e527..dfd4362 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
@@ -143,8 +143,11 @@
     @Provides
     static TvPipNotificationController provideTvPipNotificationController(Context context,
             PipMediaController pipMediaController,
+            PipParamsChangedForwarder pipParamsChangedForwarder,
+            TvPipBoundsState tvPipBoundsState,
             @ShellMainThread Handler mainHandler) {
-        return new TvPipNotificationController(context, pipMediaController, mainHandler);
+        return new TvPipNotificationController(context, pipMediaController,
+                pipParamsChangedForwarder, tvPipBoundsState, mainHandler);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
index 8a50f22..65a12d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Icon;
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
+import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.Handler;
@@ -64,7 +65,7 @@
      */
     public interface ActionListener {
         /**
-         * Called when the media actions changes.
+         * Called when the media actions changed.
          */
         void onMediaActionsChanged(List<RemoteAction> actions);
     }
@@ -74,11 +75,21 @@
      */
     public interface MetadataListener {
         /**
-         * Called when the media metadata changes.
+         * Called when the media metadata changed.
          */
         void onMediaMetadataChanged(MediaMetadata metadata);
     }
 
+    /**
+     * A listener interface to receive notification on changes to the media session token.
+     */
+    public interface TokenListener {
+        /**
+         * Called when the media session token changed.
+         */
+        void onMediaSessionTokenChanged(MediaSession.Token token);
+    }
+
     private final Context mContext;
     private final Handler mMainHandler;
     private final HandlerExecutor mHandlerExecutor;
@@ -133,6 +144,7 @@
 
     private final ArrayList<ActionListener> mActionListeners = new ArrayList<>();
     private final ArrayList<MetadataListener> mMetadataListeners = new ArrayList<>();
+    private final ArrayList<TokenListener> mTokenListeners = new ArrayList<>();
 
     public PipMediaController(Context context, Handler mainHandler) {
         mContext = context;
@@ -204,6 +216,31 @@
         mMetadataListeners.remove(listener);
     }
 
+    /**
+     * Adds a new token listener.
+     */
+    public void addTokenListener(TokenListener listener) {
+        if (!mTokenListeners.contains(listener)) {
+            mTokenListeners.add(listener);
+            listener.onMediaSessionTokenChanged(getToken());
+        }
+    }
+
+    /**
+     * Removes a token listener.
+     */
+    public void removeTokenListener(TokenListener listener) {
+        listener.onMediaSessionTokenChanged(null);
+        mTokenListeners.remove(listener);
+    }
+
+    private MediaSession.Token getToken() {
+        if (mMediaController == null) {
+            return null;
+        }
+        return mMediaController.getSessionToken();
+    }
+
     private MediaMetadata getMediaMetadata() {
         return mMediaController != null ? mMediaController.getMetadata() : null;
     }
@@ -294,6 +331,7 @@
             }
             notifyActionsChanged();
             notifyMetadataChanged(getMediaMetadata());
+            notifyTokenChanged(getToken());
 
             // TODO(winsonc): Consider if we want to close the PIP after a timeout (like on TV)
         }
@@ -317,4 +355,10 @@
             mMetadataListeners.forEach(l -> l.onMediaMetadataChanged(metadata));
         }
     }
+
+    private void notifyTokenChanged(MediaSession.Token token) {
+        if (!mTokenListeners.isEmpty()) {
+            mTokenListeners.forEach(l -> l.onMediaSessionTokenChanged(token));
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index fcd1f95..7667794 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -293,6 +293,8 @@
         }
         mTvPipBoundsState.setTvPipManuallyCollapsed(!expanding);
         mTvPipBoundsState.setTvPipExpanded(expanding);
+        mPipNotificationController.updateExpansionState();
+
         updatePinnedStackBounds();
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
index 4033f03..61a609d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipNotificationController.java
@@ -16,36 +16,47 @@
 
 package com.android.wm.shell.pip.tv;
 
+import static android.app.Notification.Action.SEMANTIC_ACTION_DELETE;
+import static android.app.Notification.Action.SEMANTIC_ACTION_NONE;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.RemoteAction;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.media.MediaMetadata;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaSession;
+import android.os.Bundle;
 import android.os.Handler;
 import android.text.TextUtils;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.ImageUtils;
 import com.android.wm.shell.R;
 import com.android.wm.shell.pip.PipMediaController;
+import com.android.wm.shell.pip.PipParamsChangedForwarder;
+import com.android.wm.shell.pip.PipUtils;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
-import java.util.Objects;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
- * A notification that informs users that PIP is running and also provides PIP controls.
- * <p>Once it's created, it will manage the PIP notification UI by itself except for handling
- * configuration changes.
+ * A notification that informs users that PiP is running and also provides PiP controls.
+ * <p>Once it's created, it will manage the PiP notification UI by itself except for handling
+ * configuration changes and user initiated expanded PiP toggling.
  */
 public class TvPipNotificationController {
     private static final String TAG = "TvPipNotification";
-    private static final boolean DEBUG = TvPipController.DEBUG;
 
     // Referenced in com.android.systemui.util.NotificationChannels.
     public static final String NOTIFICATION_CHANNEL = "TVPIP";
@@ -60,6 +71,8 @@
             "com.android.wm.shell.pip.tv.notification.action.MOVE_PIP";
     private static final String ACTION_TOGGLE_EXPANDED_PIP =
             "com.android.wm.shell.pip.tv.notification.action.TOGGLE_EXPANDED_PIP";
+    private static final String ACTION_FULLSCREEN =
+            "com.android.wm.shell.pip.tv.notification.action.FULLSCREEN";
 
     private final Context mContext;
     private final PackageManager mPackageManager;
@@ -68,44 +81,88 @@
     private final ActionBroadcastReceiver mActionBroadcastReceiver;
     private final Handler mMainHandler;
     private Delegate mDelegate;
+    private final TvPipBoundsState mTvPipBoundsState;
 
     private String mDefaultTitle;
 
+    private final List<RemoteAction> mCustomActions = new ArrayList<>();
+    private final List<RemoteAction> mMediaActions = new ArrayList<>();
+    private RemoteAction mCustomCloseAction;
+
+    private MediaSession.Token mMediaSessionToken;
+
     /** Package name for the application that owns PiP window. */
     private String mPackageName;
-    private boolean mNotified;
-    private String mMediaTitle;
-    private Bitmap mArt;
+
+    private boolean mIsNotificationShown;
+    private String mPipTitle;
+    private String mPipSubtitle;
+
+    private Bitmap mActivityIcon;
 
     public TvPipNotificationController(Context context, PipMediaController pipMediaController,
+            PipParamsChangedForwarder pipParamsChangedForwarder, TvPipBoundsState tvPipBoundsState,
             Handler mainHandler) {
         mContext = context;
         mPackageManager = context.getPackageManager();
         mNotificationManager = context.getSystemService(NotificationManager.class);
         mMainHandler = mainHandler;
+        mTvPipBoundsState = tvPipBoundsState;
 
         mNotificationBuilder = new Notification.Builder(context, NOTIFICATION_CHANNEL)
                 .setLocalOnly(true)
-                .setOngoing(false)
+                .setOngoing(true)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setShowWhen(true)
                 .setSmallIcon(R.drawable.pip_icon)
+                .setAllowSystemGeneratedContextualActions(false)
+                .setContentIntent(createPendingIntent(context, ACTION_FULLSCREEN))
+                .setDeleteIntent(getCloseAction().actionIntent)
                 .extend(new Notification.TvExtender()
                         .setContentIntent(createPendingIntent(context, ACTION_SHOW_PIP_MENU))
                         .setDeleteIntent(createPendingIntent(context, ACTION_CLOSE_PIP)));
 
         mActionBroadcastReceiver = new ActionBroadcastReceiver();
 
-        pipMediaController.addMetadataListener(this::onMediaMetadataChanged);
+        pipMediaController.addActionListener(this::onMediaActionsChanged);
+        pipMediaController.addTokenListener(this::onMediaSessionTokenChanged);
+
+        pipParamsChangedForwarder.addListener(
+                new PipParamsChangedForwarder.PipParamsChangedCallback() {
+                    @Override
+                    public void onExpandedAspectRatioChanged(float ratio) {
+                        updateExpansionState();
+                    }
+
+                    @Override
+                    public void onActionsChanged(List<RemoteAction> actions,
+                            RemoteAction closeAction) {
+                        mCustomActions.clear();
+                        mCustomActions.addAll(actions);
+                        mCustomCloseAction = closeAction;
+                        updateNotificationContent();
+                    }
+
+                    @Override
+                    public void onTitleChanged(String title) {
+                        mPipTitle = title;
+                        updateNotificationContent();
+                    }
+
+                    @Override
+                    public void onSubtitleChanged(String subtitle) {
+                        mPipSubtitle = subtitle;
+                        updateNotificationContent();
+                    }
+                });
 
         onConfigurationChanged(context);
     }
 
     void setDelegate(Delegate delegate) {
-        if (DEBUG) {
-            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                    "%s: setDelegate(), delegate=%s", TAG, delegate);
-        }
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: setDelegate(), delegate=%s",
+                TAG, delegate);
+
         if (mDelegate != null) {
             throw new IllegalStateException(
                     "The delegate has already been set and should not change.");
@@ -118,90 +175,181 @@
     }
 
     void show(String packageName) {
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: show %s", TAG, packageName);
         if (mDelegate == null) {
             throw new IllegalStateException("Delegate is not set.");
         }
 
+        mIsNotificationShown = true;
         mPackageName = packageName;
-        update();
+        mActivityIcon = getActivityIcon();
         mActionBroadcastReceiver.register();
+
+        updateNotificationContent();
     }
 
     void dismiss() {
-        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
-        mNotified = false;
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: dismiss()", TAG);
+
+        mIsNotificationShown = false;
         mPackageName = null;
         mActionBroadcastReceiver.unregister();
+
+        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
     }
 
-    private void onMediaMetadataChanged(MediaMetadata metadata) {
-        if (updateMediaControllerMetadata(metadata) && mNotified) {
-            // update notification
-            update();
+    private Notification.Action getToggleAction(boolean expanded) {
+        if (expanded) {
+            return createSystemAction(R.drawable.pip_ic_collapse,
+                    R.string.pip_collapse, ACTION_TOGGLE_EXPANDED_PIP);
+        } else {
+            return createSystemAction(R.drawable.pip_ic_expand, R.string.pip_expand,
+                    ACTION_TOGGLE_EXPANDED_PIP);
         }
     }
 
+    private Notification.Action createSystemAction(int iconRes, int titleRes, String action) {
+        Notification.Action.Builder builder = new Notification.Action.Builder(
+                Icon.createWithResource(mContext, iconRes),
+                mContext.getString(titleRes),
+                createPendingIntent(mContext, action));
+        builder.setContextual(true);
+        return builder.build();
+    }
+
+    private void onMediaActionsChanged(List<RemoteAction> actions) {
+        mMediaActions.clear();
+        mMediaActions.addAll(actions);
+        if (mCustomActions.isEmpty()) {
+            updateNotificationContent();
+        }
+    }
+
+    private void onMediaSessionTokenChanged(MediaSession.Token token) {
+        mMediaSessionToken = token;
+        updateNotificationContent();
+    }
+
+    private Notification.Action remoteToNotificationAction(RemoteAction action) {
+        return remoteToNotificationAction(action, SEMANTIC_ACTION_NONE);
+    }
+
+    private Notification.Action remoteToNotificationAction(RemoteAction action,
+            int semanticAction) {
+        Notification.Action.Builder builder = new Notification.Action.Builder(action.getIcon(),
+                action.getTitle(),
+                action.getActionIntent());
+        if (action.getContentDescription() != null) {
+            Bundle extras = new Bundle();
+            extras.putCharSequence(Notification.EXTRA_PICTURE_CONTENT_DESCRIPTION,
+                    action.getContentDescription());
+            builder.addExtras(extras);
+        }
+        builder.setSemanticAction(semanticAction);
+        builder.setContextual(true);
+        return builder.build();
+    }
+
+    private Notification.Action[] getNotificationActions() {
+        final List<Notification.Action> actions = new ArrayList<>();
+
+        // 1. Fullscreen
+        actions.add(getFullscreenAction());
+        // 2. Close
+        actions.add(getCloseAction());
+        // 3. App actions
+        final List<RemoteAction> appActions =
+                mCustomActions.isEmpty() ? mMediaActions : mCustomActions;
+        for (RemoteAction appAction : appActions) {
+            if (PipUtils.remoteActionsMatch(mCustomCloseAction, appAction)
+                    || !appAction.isEnabled()) {
+                continue;
+            }
+            actions.add(remoteToNotificationAction(appAction));
+        }
+        // 4. Move
+        actions.add(getMoveAction());
+        // 5. Toggle expansion (if expanded PiP enabled)
+        if (mTvPipBoundsState.getDesiredTvExpandedAspectRatio() > 0
+                && mTvPipBoundsState.isTvExpandedPipSupported()) {
+            actions.add(getToggleAction(mTvPipBoundsState.isTvPipExpanded()));
+        }
+        return actions.toArray(new Notification.Action[0]);
+    }
+
+    private Notification.Action getCloseAction() {
+        if (mCustomCloseAction == null) {
+            return createSystemAction(R.drawable.pip_ic_close_white, R.string.pip_close,
+                    ACTION_CLOSE_PIP);
+        } else {
+            return remoteToNotificationAction(mCustomCloseAction, SEMANTIC_ACTION_DELETE);
+        }
+    }
+
+    private Notification.Action getFullscreenAction() {
+        return createSystemAction(R.drawable.pip_ic_fullscreen_white,
+                R.string.pip_fullscreen, ACTION_FULLSCREEN);
+    }
+
+    private Notification.Action getMoveAction() {
+        return createSystemAction(R.drawable.pip_ic_move_white, R.string.pip_move,
+                ACTION_MOVE_PIP);
+    }
+
     /**
-     * Called by {@link PipController} when the configuration is changed.
+     * Called by {@link TvPipController} when the configuration is changed.
      */
     void onConfigurationChanged(Context context) {
         mDefaultTitle = context.getResources().getString(R.string.pip_notification_unknown_title);
-        if (mNotified) {
-            // Update the notification.
-            update();
-        }
+        updateNotificationContent();
     }
 
-    private void update() {
-        mNotified = true;
+    void updateExpansionState() {
+        updateNotificationContent();
+    }
+
+    private void updateNotificationContent() {
+        if (mPackageManager == null || !mIsNotificationShown) {
+            return;
+        }
+
+        Notification.Action[] actions = getNotificationActions();
+        ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                "%s: update(), title: %s, subtitle: %s, mediaSessionToken: %s, #actions: %s", TAG,
+                getNotificationTitle(), mPipSubtitle, mMediaSessionToken, actions.length);
+        for (Notification.Action action : actions) {
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: action: %s", TAG,
+                    action.toString());
+        }
+
         mNotificationBuilder
                 .setWhen(System.currentTimeMillis())
-                .setContentTitle(getNotificationTitle());
-        if (mArt != null) {
-            mNotificationBuilder.setStyle(new Notification.BigPictureStyle()
-                    .bigPicture(mArt));
-        } else {
-            mNotificationBuilder.setStyle(null);
-        }
+                .setContentTitle(getNotificationTitle())
+                .setContentText(mPipSubtitle)
+                .setSubText(getApplicationLabel(mPackageName))
+                .setActions(actions);
+        setPipIcon();
+
+        Bundle extras = new Bundle();
+        extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, mMediaSessionToken);
+        mNotificationBuilder.setExtras(extras);
+
+        // TvExtender not recognized if not set last.
+        mNotificationBuilder.extend(new Notification.TvExtender()
+                .setContentIntent(createPendingIntent(mContext, ACTION_SHOW_PIP_MENU))
+                .setDeleteIntent(createPendingIntent(mContext, ACTION_CLOSE_PIP)));
         mNotificationManager.notify(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP,
                 mNotificationBuilder.build());
     }
 
-    private boolean updateMediaControllerMetadata(MediaMetadata metadata) {
-        String title = null;
-        Bitmap art = null;
-        if (metadata != null) {
-            title = metadata.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE);
-            if (TextUtils.isEmpty(title)) {
-                title = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);
-            }
-            art = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
-            if (art == null) {
-                art = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
-            }
-        }
-
-        if (TextUtils.equals(title, mMediaTitle) && Objects.equals(art, mArt)) {
-            return false;
-        }
-
-        mMediaTitle = title;
-        mArt = art;
-
-        return true;
-    }
-
-
     private String getNotificationTitle() {
-        if (!TextUtils.isEmpty(mMediaTitle)) {
-            return mMediaTitle;
+        if (!TextUtils.isEmpty(mPipTitle)) {
+            return mPipTitle;
         }
-
         final String applicationTitle = getApplicationLabel(mPackageName);
         if (!TextUtils.isEmpty(applicationTitle)) {
             return applicationTitle;
         }
-
         return mDefaultTitle;
     }
 
@@ -214,10 +362,37 @@
         }
     }
 
+    private void setPipIcon() {
+        if (mActivityIcon != null) {
+            mNotificationBuilder.setLargeIcon(mActivityIcon);
+            return;
+        }
+        // Fallback: Picture-in-Picture icon
+        mNotificationBuilder.setLargeIcon(Icon.createWithResource(mContext, R.drawable.pip_icon));
+    }
+
+    private Bitmap getActivityIcon() {
+        if (mContext == null) return null;
+        ComponentName componentName = PipUtils.getTopPipActivity(mContext).first;
+        if (componentName == null) return null;
+
+        Drawable drawable;
+        try {
+            drawable = mPackageManager.getActivityIcon(componentName);
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+        int width = mContext.getResources().getDimensionPixelSize(
+                android.R.dimen.notification_large_icon_width);
+        int height = mContext.getResources().getDimensionPixelSize(
+                android.R.dimen.notification_large_icon_height);
+        return ImageUtils.buildScaledBitmap(drawable, width, height, /* allowUpscaling */ true);
+    }
+
     private static PendingIntent createPendingIntent(Context context, String action) {
         return PendingIntent.getBroadcast(context, 0,
                 new Intent(action).setPackage(context.getPackageName()),
-                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
     }
 
     private class ActionBroadcastReceiver extends BroadcastReceiver {
@@ -228,6 +403,7 @@
             mIntentFilter.addAction(ACTION_SHOW_PIP_MENU);
             mIntentFilter.addAction(ACTION_MOVE_PIP);
             mIntentFilter.addAction(ACTION_TOGGLE_EXPANDED_PIP);
+            mIntentFilter.addAction(ACTION_FULLSCREEN);
         }
         boolean mRegistered = false;
 
@@ -249,10 +425,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (DEBUG) {
-                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                        "%s: on(Broadcast)Receive(), action=%s", TAG, action);
-            }
+            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                    "%s: on(Broadcast)Receive(), action=%s", TAG, action);
 
             if (ACTION_SHOW_PIP_MENU.equals(action)) {
                 mDelegate.showPictureInPictureMenu();
@@ -262,14 +436,21 @@
                 mDelegate.enterPipMovementMenu();
             } else if (ACTION_TOGGLE_EXPANDED_PIP.equals(action)) {
                 mDelegate.togglePipExpansion();
+            } else if (ACTION_FULLSCREEN.equals(action)) {
+                mDelegate.movePipToFullscreen();
             }
         }
     }
 
     interface Delegate {
         void showPictureInPictureMenu();
+
         void closePip();
+
         void enterPipMovementMenu();
+
         void togglePipExpansion();
+
+        void movePipToFullscreen();
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 6cf8829..42b1014 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -209,12 +209,11 @@
         createNavigationInfo(animationTarget, null, null,
                 BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
 
-        // Check that back start is dispatched.
         doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        verify(mIOnBackInvokedCallback).onBackStarted();
 
-        // Check that back progress is dispatched.
+        // Check that back start and progress is dispatched when first move.
         doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        verify(mIOnBackInvokedCallback).onBackStarted();
         ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class);
         verify(mIOnBackInvokedCallback).onBackProgressed(backEventCaptor.capture());
         assertEquals(animationTarget, backEventCaptor.getValue().getDepartingAnimationTarget());
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 284da73..2f30baa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -234,5 +234,10 @@
         if (!(mPreference instanceof RestrictedTopLevelPreference)) {
             mPreference.setEnabled(!(mDisabledByAdmin || mDisabledByAppOps));
         }
+
+        if (mPreference instanceof PrimarySwitchPreference) {
+            ((PrimarySwitchPreference) mPreference)
+                    .setSwitchEnabled(!(mDisabledByAdmin || mDisabledByAppOps));
+        }
     }
 }
diff --git a/packages/SystemUI/res/layout/alert_dialog_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_systemui.xml
index 528f603..fd06238 100644
--- a/packages/SystemUI/res/layout/alert_dialog_systemui.xml
+++ b/packages/SystemUI/res/layout/alert_dialog_systemui.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-
 <!--
-  ~ Copyright (C) 2021 The Android Open Source Project
+  ~ 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.
@@ -15,88 +14,83 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<androidx.core.widget.NestedScrollView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
 
-    <com.android.internal.widget.AlertDialogLayout
-        android:id="@*android:id/parentPanel"
+<com.android.internal.widget.AlertDialogLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@*android:id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal|top"
+    android:orientation="vertical"
+    android:paddingTop="@dimen/dialog_top_padding"
+>
+
+    <include layout="@layout/alert_dialog_title_systemui" />
+
+    <FrameLayout
+        android:id="@*android:id/contentPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:gravity="center_horizontal|top"
-        android:orientation="vertical"
-        android:paddingTop="@dimen/dialog_top_padding"
-        >
+        android:minHeight="48dp"
+        android:paddingStart="@dimen/dialog_side_padding"
+        android:paddingEnd="@dimen/dialog_side_padding"
+    >
 
-        <include layout="@layout/alert_dialog_title_systemui" />
-
-        <FrameLayout
-            android:id="@*android:id/contentPanel"
+        <ScrollView
+            android:id="@*android:id/scrollView"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:minHeight="48dp"
-            android:paddingStart="@dimen/dialog_side_padding"
-            android:paddingEnd="@dimen/dialog_side_padding"
-            >
+            android:clipToPadding="false">
 
-            <ScrollView
-                android:id="@*android:id/scrollView"
+            <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:clipToPadding="false">
+                android:orientation="vertical">
 
-                <LinearLayout
+                <Space
+                    android:id="@*android:id/textSpacerNoTitle"
+                    android:visibility="gone"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp" />
+
+                <TextView
+                    android:id="@*android:id/message"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:orientation="vertical">
+                    style="@style/TextAppearance.Dialog.Body.Message" />
 
-                    <Space
-                        android:id="@*android:id/textSpacerNoTitle"
-                        android:visibility="gone"
-                        android:layout_width="match_parent"
-                        android:layout_height="0dp" />
+                <Space
+                    android:id="@*android:id/textSpacerNoButtons"
+                    android:visibility="gone"
+                    android:layout_width="match_parent"
+                    android:layout_height="6dp" />
+            </LinearLayout>
+        </ScrollView>
+    </FrameLayout>
 
-                    <TextView
-                        android:id="@*android:id/message"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        style="@style/TextAppearance.Dialog.Body.Message" />
-
-                    <Space
-                        android:id="@*android:id/textSpacerNoButtons"
-                        android:visibility="gone"
-                        android:layout_width="match_parent"
-                        android:layout_height="6dp" />
-                </LinearLayout>
-            </ScrollView>
-        </FrameLayout>
+    <FrameLayout
+        android:id="@*android:id/customPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
+        android:paddingStart="@dimen/dialog_side_padding"
+        android:paddingEnd="@dimen/dialog_side_padding"
+    >
 
         <FrameLayout
-            android:id="@*android:id/customPanel"
+            android:id="@*android:id/custom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </FrameLayout>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/dialog_side_padding"
+        android:paddingEnd="@dimen/dialog_side_padding">
+        <include
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:minHeight="48dp"
-            android:paddingStart="@dimen/dialog_side_padding"
-            android:paddingEnd="@dimen/dialog_side_padding"
-            >
-
-            <FrameLayout
-                android:id="@*android:id/custom"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-        </FrameLayout>
-
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="@dimen/dialog_side_padding"
-            android:paddingEnd="@dimen/dialog_side_padding">
-            <include
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                layout="@layout/alert_dialog_button_bar_systemui" />
-        </FrameLayout>
-    </com.android.internal.widget.AlertDialogLayout>
-
-</androidx.core.widget.NestedScrollView>
\ No newline at end of file
+            layout="@layout/alert_dialog_button_bar_systemui" />
+    </FrameLayout>
+</com.android.internal.widget.AlertDialogLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/scrollable_alert_dialog_systemui.xml b/packages/SystemUI/res/layout/scrollable_alert_dialog_systemui.xml
new file mode 100644
index 0000000..71bb938
--- /dev/null
+++ b/packages/SystemUI/res/layout/scrollable_alert_dialog_systemui.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 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.
+  -->
+<androidx.core.widget.NestedScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <include layout="@layout/alert_dialog_systemui" />
+
+</androidx.core.widget.NestedScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index f9e73ec..0c25f54 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -380,7 +380,7 @@
         <item name="android:buttonBarNegativeButtonStyle">@style/Widget.Dialog.Button.BorderButton</item>
         <item name="android:buttonBarNeutralButtonStyle">@style/Widget.Dialog.Button.BorderButton</item>
         <item name="android:colorBackground">?androidprv:attr/colorSurface</item>
-        <item name="android:alertDialogStyle">@style/AlertDialogStyle</item>
+        <item name="android:alertDialogStyle">@style/ScrollableAlertDialogStyle</item>
         <item name="android:buttonBarStyle">@style/ButtonBarStyle</item>
         <item name="android:buttonBarButtonStyle">@style/Widget.Dialog.Button.Large</item>
     </style>
@@ -389,6 +389,10 @@
         <item name="android:layout">@layout/alert_dialog_systemui</item>
     </style>
 
+    <style name="ScrollableAlertDialogStyle" parent="@androidprv:style/AlertDialog.DeviceDefault">
+        <item name="android:layout">@layout/scrollable_alert_dialog_systemui</item>
+    </style>
+
     <style name="ButtonBarStyle" parent="@androidprv:style/DeviceDefault.ButtonBar.AlertDialog">
         <item name="android:paddingTop">@dimen/dialog_button_bar_top_padding</item>
         <item name="android:paddingBottom">@dimen/dialog_bottom_padding</item>
@@ -994,6 +998,7 @@
 
     <style name="Theme.SystemUI.Dialog.Cast">
         <item name="android:textAppearanceMedium">@style/TextAppearance.CastItem</item>
+        <item name="android:alertDialogStyle">@style/AlertDialogStyle</item>
     </style>
     <!-- ************************************************************************************* -->
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 5d154c3..4e48a52 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -38,7 +38,6 @@
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
-import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.power.dagger.PowerModule;
 import com.android.systemui.qs.dagger.QSModule;
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
@@ -80,8 +79,19 @@
 import dagger.Provides;
 
 /**
- * A dagger module for injecting default implementations of components of System UI that may be
- * overridden by the System UI implementation.
+ * A dagger module for injecting default implementations of components of System UI.
+ *
+ * Variants of SystemUI should make a copy of this, include it in their component, and customize it
+ * as needed.
+ *
+ * This module might alternatively be named `AospSystemUIModule`, `PhoneSystemUIModule`,
+ * or `BasicSystemUIModule`.
+ *
+ * Nothing in the module should be strictly required. Each piece should either be swappable with
+ * a different implementation or entirely removable.
+ *
+ * This is different from {@link SystemUIModule} which should be used for pieces of required
+ * SystemUI code that variants of SystemUI _must_ include to function correctly.
  */
 @Module(includes = {
         MediaModule.class,
@@ -90,7 +100,7 @@
         StartCentralSurfacesModule.class,
         VolumeModule.class
 })
-public abstract class SystemUIDefaultModule {
+public abstract class ReferenceSystemUIModule {
 
     @SysUISingleton
     @Provides
@@ -101,9 +111,6 @@
     }
 
     @Binds
-    abstract EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
-
-    @Binds
     abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager(
             NotificationLockscreenUserManagerImpl notificationLockscreenUserManager);
 
@@ -148,6 +155,7 @@
         return spC;
     }
 
+    /** */
     @Binds
     @SysUISingleton
     public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 701972a..5d34a69 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -73,7 +73,7 @@
         SystemUIBinder.class,
         SystemUIModule.class,
         SystemUICoreStartableModule.class,
-        SystemUIDefaultModule.class})
+        ReferenceSystemUIModule.class})
 public interface SysUIComponent {
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index bbeb66c..535eff8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -100,8 +100,14 @@
 import dagger.Provides;
 
 /**
- * A dagger module for injecting components of System UI that are not overridden by the System UI
- * implementation.
+ * A dagger module for injecting components of System UI that are required by System UI.
+ *
+ * If your feature can be excluded, subclassed, or re-implemented by a variant of SystemUI, put
+ * your Dagger Module in {@link ReferenceSystemUIModule} and/or any variant modules that
+ * rely on the feature.
+ *
+ * Adding an entry in this file means that _all_ variants of SystemUI will receive that code. They
+ * may not appreciate that.
  */
 @Module(includes = {
             AppOpsModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
index 1437c96..7eccb3b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
@@ -278,13 +278,14 @@
     /**
      * Apply squishFraction to a copy of viewState such that the cached version is untouched.
      */
-    private fun squishViewState(
+    @VisibleForTesting
+    internal fun squishViewState(
         viewState: TransitionViewState,
         squishFraction: Float
     ): TransitionViewState {
         val squishedViewState = viewState.copy()
         squishedViewState.height = (squishedViewState.height * squishFraction).toInt()
-        val albumArtViewState = viewState.widgetStates.get(R.id.album_art)
+        val albumArtViewState = squishedViewState.widgetStates.get(R.id.album_art)
         if (albumArtViewState != null) {
             albumArtViewState.height = squishedViewState.height
         }
@@ -317,6 +318,7 @@
         if (transitionLayout == null) {
             return null
         }
+
         // Not cached. Let's create a new measurement
         if (state.expansion == 0.0f || state.expansion == 1.0f) {
             result = transitionLayout!!.calculateViewState(
diff --git a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
index 8b8941a..3709a86 100644
--- a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
+++ b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.power.dagger;
 
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
 
@@ -28,5 +30,9 @@
 public interface PowerModule {
     /** */
     @Binds
+    EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
+
+    /** */
+    @Binds
     PowerUI.WarningsUI provideWarningsUi(PowerNotificationWarnings controllerImpl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 985df42..7da3238 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -24,6 +24,7 @@
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
 import static com.android.keyguard.KeyguardClockSwitch.SMALL;
+import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
 import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE;
 import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
@@ -936,7 +937,7 @@
                                         // the launcher icons animation starts, so use that as our
                                         // duration.
                                         .setDuration(unlockAnimationStartDelay)
-                                        .setInterpolator(EMPHASIZED_DECELERATE)
+                                        .setInterpolator(EMPHASIZED_ACCELERATE)
                                         .withEndAction(() -> {
                                             instantCollapse();
                                             mView.setAlpha(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index b7f90a4..4685c14 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -38,7 +38,6 @@
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
-import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.power.dagger.PowerModule;
 import com.android.systemui.qs.dagger.QSModule;
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
@@ -102,9 +101,6 @@
     }
 
     @Binds
-    abstract EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
-
-    @Binds
     abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager(
             NotificationLockscreenUserManagerImpl notificationLockscreenUserManager);
 
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index acff871..ebdddbf 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -180,7 +180,7 @@
         int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
         GetWalletCardsRequest request =
                 new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 1);
-        mQuickAccessWalletClient.getWalletCards(mExecutor, request, cardsRetriever);
+        mQuickAccessWalletClient.getWalletCards(mCallbackExecutor, request, cardsRetriever);
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt
index 604e1f3..1817809 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaViewControllerTest.kt
@@ -4,16 +4,22 @@
 import android.testing.TestableLooper
 import android.view.View
 import androidx.test.filters.SmallTest
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.animation.MeasurementInput
 import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.animation.TransitionViewState
+import com.android.systemui.util.animation.WidgetState
 import junit.framework.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
 
 /**
  * Tests for {@link MediaViewController}.
@@ -31,6 +37,9 @@
     private lateinit var mediaViewController: MediaViewController
     private val mediaHostStateHolder = MediaHost.MediaHostStateHolder()
     private var transitionLayout = TransitionLayout(context, /* attrs */ null, /* defStyleAttr */ 0)
+    @Mock private lateinit var mockViewState: TransitionViewState
+    @Mock private lateinit var mockCopiedState: TransitionViewState
+    @Mock private lateinit var mockWidgetState: WidgetState
 
     @Before
     fun setUp() {
@@ -63,4 +72,15 @@
         mediaHostStateHolder.squishFraction = 0.5f
         assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
     }
+
+    @Test
+    fun testSquish_DoesNotMutateViewState() {
+        whenever(mockViewState.copy()).thenReturn(mockCopiedState)
+        whenever(mockCopiedState.widgetStates)
+            .thenReturn(mutableMapOf(R.id.album_art to mockWidgetState))
+
+        mediaViewController.squishViewState(mockViewState, 0.5f)
+        verify(mockViewState, times(1)).copy()
+        verifyNoMoreInteractions(mockViewState)
+    }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index fc73a59..cceacd8 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2792,6 +2792,15 @@
         }
 
         int N = procs.size();
+        for (int i = 0; i < N; ++i) {
+            final ProcessRecord proc = procs.get(i).first;
+            try {
+                Process.setProcessFrozen(proc.getPid(), proc.uid, true);
+            } catch (Exception e) {
+                Slog.w(TAG, "Unable to freeze " + proc.getPid() + " " + proc.processName);
+            }
+        }
+
         for (int i=0; i<N; i++) {
             final Pair<ProcessRecord, Boolean> proc = procs.get(i);
             removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 3e97b91..36afb36 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4545,8 +4545,9 @@
      * @return The restriction matching the package
      */
     private RestrictionBypass getBypassforPackage(@NonNull AndroidPackage pkg) {
-        return new RestrictionBypass(pkg.isPrivileged(), mContext.checkPermission(
-                android.Manifest.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, pkg.getUid())
+        return new RestrictionBypass(pkg.getUid() == Process.SYSTEM_UID, pkg.isPrivileged(),
+                mContext.checkPermission(android.Manifest.permission
+                        .EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS, -1, pkg.getUid())
                 == PackageManager.PERMISSION_GRANTED);
     }
 
@@ -4853,6 +4854,9 @@
                 if (opBypass != null) {
                     // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
+                        if (opBypass.isSystemUid && appBypass != null && appBypass.isSystemUid) {
+                            return false;
+                        }
                         if (opBypass.isPrivileged && appBypass != null && appBypass.isPrivileged) {
                             return false;
                         }
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 122a950..d8aa9aa 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -486,8 +486,7 @@
 
         for (SADeviceState deviceState : mSADevices) {
             if (deviceType == deviceState.mDeviceType
-                    && (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
-                    || !wireless) {
+                    && (!wireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
                 isInList = true;
                 if (forceEnable) {
                     deviceState.mEnabled = true;
@@ -511,8 +510,7 @@
 
         for (SADeviceState deviceState : mSADevices) {
             if (deviceType == deviceState.mDeviceType
-                    && (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
-                    || !wireless) {
+                    && (!wireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
                 deviceState.mEnabled = false;
                 break;
             }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 5ae3f33..e4e9d1d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1712,6 +1712,13 @@
             mPointerIconDisplayContext = null;
         }
 
+        synchronized (mAdditionalDisplayInputPropertiesLock) {
+            setPointerIconVisible(AdditionalDisplayInputProperties.DEFAULT_POINTER_ICON_VISIBLE,
+                    displayId);
+            setPointerAcceleration(AdditionalDisplayInputProperties.DEFAULT_POINTER_ACCELERATION,
+                    displayId);
+        }
+
         mNative.displayRemoved(displayId);
     }
 
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
index e62c5c1..1703310 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
@@ -30,6 +30,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputMethodSubtype;
+import android.window.ImeOnBackInvokedDispatcher;
 
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodNavButtonFlags;
@@ -148,10 +149,11 @@
 
     @AnyThread
     void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo attribute,
-            boolean restarting, @InputMethodNavButtonFlags int navButtonFlags) {
+            boolean restarting, @InputMethodNavButtonFlags int navButtonFlags,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         try {
             mTarget.startInput(startInputToken, inputContext, attribute, restarting,
-                    navButtonFlags);
+                    navButtonFlags, imeDispatcher);
         } catch (RemoteException e) {
             logRemoteException(e);
         }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6af00b3..c759c64 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -150,6 +150,7 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
+import android.window.ImeOnBackInvokedDispatcher;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
@@ -616,6 +617,12 @@
     IInputContext mCurInputContext;
 
     /**
+     * The {@link ImeOnBackInvokedDispatcher} last provided by the current client to
+     * receive {@link android.window.OnBackInvokedCallback}s forwarded from IME.
+     */
+    ImeOnBackInvokedDispatcher mCurImeDispatcher;
+
+    /**
      * The {@link IRemoteAccessibilityInputConnection} last provided by the current client.
      */
     @Nullable IRemoteAccessibilityInputConnection mCurRemoteAccessibilityInputConnection;
@@ -2623,7 +2630,7 @@
         final SessionState session = mCurClient.curSession;
         setEnabledSessionLocked(session);
         session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting,
-                navButtonFlags);
+                navButtonFlags, mCurImeDispatcher);
         if (mShowRequested) {
             if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
             showCurrentInputLocked(mCurFocusedWindow, getAppShowFlagsLocked(), null,
@@ -2733,7 +2740,8 @@
             @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
             @NonNull EditorInfo attribute, @StartInputFlags int startInputFlags,
             @StartInputReason int startInputReason,
-            int unverifiedTargetSdkVersion) {
+            int unverifiedTargetSdkVersion,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         // If no method is currently selected, do nothing.
         final String selectedMethodId = getSelectedMethodIdLocked();
         if (selectedMethodId == null) {
@@ -2777,6 +2785,7 @@
         mCurClient = cs;
         mCurInputContext = inputContext;
         mCurRemoteAccessibilityInputConnection = remoteAccessibilityInputConnection;
+        mCurImeDispatcher = imeDispatcher;
         mCurVirtualDisplayToScreenMatrix =
                 getVirtualDisplayToScreenMatrixLocked(cs.selfReportedDisplayId,
                         mDisplayIdToShowIme);
@@ -3780,10 +3789,12 @@
             @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
             int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
             IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
-            int unverifiedTargetSdkVersion) {
+            int unverifiedTargetSdkVersion,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         return startInputOrWindowGainedFocusInternal(startInputReason, client, windowToken,
                 startInputFlags, softInputMode, windowFlags, attribute, inputContext,
-                remoteAccessibilityInputConnection, unverifiedTargetSdkVersion);
+                remoteAccessibilityInputConnection, unverifiedTargetSdkVersion,
+                imeDispatcher);
     }
 
     @NonNull
@@ -3792,7 +3803,8 @@
             @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
             int windowFlags, @Nullable EditorInfo attribute, @Nullable IInputContext inputContext,
             @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
-            int unverifiedTargetSdkVersion) {
+            int unverifiedTargetSdkVersion,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         if (windowToken == null) {
             Slog.e(TAG, "windowToken cannot be null.");
             return InputBindResult.NULL;
@@ -3829,7 +3841,7 @@
                     result = startInputOrWindowGainedFocusInternalLocked(startInputReason,
                             client, windowToken, startInputFlags, softInputMode, windowFlags,
                             attribute, inputContext, remoteAccessibilityInputConnection,
-                            unverifiedTargetSdkVersion, userId);
+                            unverifiedTargetSdkVersion, userId, imeDispatcher);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
@@ -3857,7 +3869,8 @@
             @SoftInputModeFlags int softInputMode, int windowFlags, EditorInfo attribute,
             IInputContext inputContext,
             @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
-            int unverifiedTargetSdkVersion, @UserIdInt int userId) {
+            int unverifiedTargetSdkVersion, @UserIdInt int userId,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         if (DEBUG) {
             Slog.v(TAG, "startInputOrWindowGainedFocusInternalLocked: reason="
                     + InputMethodDebug.startInputReasonToString(startInputReason)
@@ -3868,7 +3881,8 @@
                     + InputMethodDebug.startInputFlagsToString(startInputFlags)
                     + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
                     + " windowFlags=#" + Integer.toHexString(windowFlags)
-                    + " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion);
+                    + " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion
+                    + " imeDispatcher=" + imeDispatcher);
         }
 
         final ClientState cs = mClients.get(client.asBinder());
@@ -3952,7 +3966,7 @@
             if (attribute != null) {
                 return startInputUncheckedLocked(cs, inputContext,
                         remoteAccessibilityInputConnection, attribute, startInputFlags,
-                        startInputReason, unverifiedTargetSdkVersion);
+                        startInputReason, unverifiedTargetSdkVersion, imeDispatcher);
             }
             return new InputBindResult(
                     InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
@@ -3993,7 +4007,8 @@
         if (isTextEditor && attribute != null
                 && shouldRestoreImeVisibility(windowToken, softInputMode)) {
             res = startInputUncheckedLocked(cs, inputContext, remoteAccessibilityInputConnection,
-                    attribute, startInputFlags, startInputReason, unverifiedTargetSdkVersion);
+                    attribute, startInputFlags, startInputReason, unverifiedTargetSdkVersion,
+                    imeDispatcher);
             showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
                     SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
             return res;
@@ -4033,7 +4048,8 @@
                     if (attribute != null) {
                         res = startInputUncheckedLocked(cs, inputContext,
                                 remoteAccessibilityInputConnection, attribute, startInputFlags,
-                                startInputReason, unverifiedTargetSdkVersion);
+                                startInputReason, unverifiedTargetSdkVersion,
+                                imeDispatcher);
                         didStart = true;
                     }
                     showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
@@ -4065,7 +4081,8 @@
                         if (attribute != null) {
                             res = startInputUncheckedLocked(cs, inputContext,
                                     remoteAccessibilityInputConnection, attribute, startInputFlags,
-                                    startInputReason, unverifiedTargetSdkVersion);
+                                    startInputReason, unverifiedTargetSdkVersion,
+                                    imeDispatcher);
                             didStart = true;
                         }
                         showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
@@ -4085,7 +4102,8 @@
                         if (attribute != null) {
                             res = startInputUncheckedLocked(cs, inputContext,
                                     remoteAccessibilityInputConnection, attribute, startInputFlags,
-                                    startInputReason, unverifiedTargetSdkVersion);
+                                    startInputReason, unverifiedTargetSdkVersion,
+                                    imeDispatcher);
                             didStart = true;
                         }
                         showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
@@ -4115,7 +4133,8 @@
                 }
                 res = startInputUncheckedLocked(cs, inputContext,
                         remoteAccessibilityInputConnection, attribute, startInputFlags,
-                        startInputReason, unverifiedTargetSdkVersion);
+                        startInputReason, unverifiedTargetSdkVersion,
+                        imeDispatcher);
             } else {
                 res = InputBindResult.NULL_EDITOR_INFO;
             }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 92703ec..604e8f3 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -60,8 +60,8 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.NoSuchElementException;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * This is the system implementation of a Session. Apps will interact with the
@@ -1159,6 +1159,9 @@
         public void sendCommand(String packageName, int pid, int uid, String command, Bundle args,
                 ResultReceiver cb) {
             try {
+                final String reason = TAG + ":" + command;
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onCommand(packageName, pid, uid, command, args, cb);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in sendCommand.", e);
@@ -1168,6 +1171,9 @@
         public void sendCustomAction(String packageName, int pid, int uid, String action,
                 Bundle args) {
             try {
+                final String reason = TAG + ":custom-" + action;
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onCustomAction(packageName, pid, uid, action, args);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in sendCustomAction.", e);
@@ -1176,6 +1182,9 @@
 
         public void prepare(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":prepare";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPrepare(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in prepare.", e);
@@ -1185,6 +1194,9 @@
         public void prepareFromMediaId(String packageName, int pid, int uid, String mediaId,
                 Bundle extras) {
             try {
+                final String reason = TAG + ":prepareFromMediaId";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPrepareFromMediaId(packageName, pid, uid, mediaId, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in prepareFromMediaId.", e);
@@ -1194,6 +1206,9 @@
         public void prepareFromSearch(String packageName, int pid, int uid, String query,
                 Bundle extras) {
             try {
+                final String reason = TAG + ":prepareFromSearch";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPrepareFromSearch(packageName, pid, uid, query, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in prepareFromSearch.", e);
@@ -1202,6 +1217,9 @@
 
         public void prepareFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
             try {
+                final String reason = TAG + ":prepareFromUri";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPrepareFromUri(packageName, pid, uid, uri, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in prepareFromUri.", e);
@@ -1210,6 +1228,9 @@
 
         public void play(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":play";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPlay(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in play.", e);
@@ -1219,6 +1240,9 @@
         public void playFromMediaId(String packageName, int pid, int uid, String mediaId,
                 Bundle extras) {
             try {
+                final String reason = TAG + ":playFromMediaId";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPlayFromMediaId(packageName, pid, uid, mediaId, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in playFromMediaId.", e);
@@ -1228,6 +1252,9 @@
         public void playFromSearch(String packageName, int pid, int uid, String query,
                 Bundle extras) {
             try {
+                final String reason = TAG + ":playFromSearch";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPlayFromSearch(packageName, pid, uid, query, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in playFromSearch.", e);
@@ -1236,6 +1263,9 @@
 
         public void playFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
             try {
+                final String reason = TAG + ":playFromUri";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPlayFromUri(packageName, pid, uid, uri, extras);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in playFromUri.", e);
@@ -1244,6 +1274,9 @@
 
         public void skipToTrack(String packageName, int pid, int uid, long id) {
             try {
+                final String reason = TAG + ":skipToTrack";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onSkipToTrack(packageName, pid, uid, id);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in skipToTrack", e);
@@ -1252,6 +1285,9 @@
 
         public void pause(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":pause";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPause(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in pause.", e);
@@ -1260,6 +1296,9 @@
 
         public void stop(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":stop";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onStop(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in stop.", e);
@@ -1268,6 +1307,9 @@
 
         public void next(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":next";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onNext(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in next.", e);
@@ -1276,6 +1318,9 @@
 
         public void previous(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":previous";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onPrevious(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in previous.", e);
@@ -1284,6 +1329,9 @@
 
         public void fastForward(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":fastForward";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onFastForward(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in fastForward.", e);
@@ -1292,6 +1340,9 @@
 
         public void rewind(String packageName, int pid, int uid) {
             try {
+                final String reason = TAG + ":rewind";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onRewind(packageName, pid, uid);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in rewind.", e);
@@ -1300,6 +1351,9 @@
 
         public void seekTo(String packageName, int pid, int uid, long pos) {
             try {
+                final String reason = TAG + ":seekTo";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onSeekTo(packageName, pid, uid, pos);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in seekTo.", e);
@@ -1308,6 +1362,9 @@
 
         public void rate(String packageName, int pid, int uid, Rating rating) {
             try {
+                final String reason = TAG + ":rate";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onRate(packageName, pid, uid, rating);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in rate.", e);
@@ -1316,6 +1373,9 @@
 
         public void setPlaybackSpeed(String packageName, int pid, int uid, float speed) {
             try {
+                final String reason = TAG + ":setPlaybackSpeed";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onSetPlaybackSpeed(packageName, pid, uid, speed);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in setPlaybackSpeed.", e);
@@ -1325,6 +1385,9 @@
         public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
                 int direction) {
             try {
+                final String reason = TAG + ":adjustVolume";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 if (asSystemService) {
                     mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(),
                             Process.SYSTEM_UID, direction);
@@ -1338,6 +1401,9 @@
 
         public void setVolumeTo(String packageName, int pid, int uid, int value) {
             try {
+                final String reason = TAG + ":setVolumeTo";
+                mService.tempAllowlistTargetPkgIfPossible(getUid(), getPackageName(),
+                        pid, uid, packageName, reason);
                 mCb.onSetVolumeTo(packageName, pid, uid, value);
             } catch (RemoteException e) {
                 Log.e(TAG, "Remote failure in setVolumeTo.", e);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 4df54b7..fa0c6c3 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -166,18 +166,19 @@
      * An in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs.
      */
     @GuardedBy("mLock")
-    final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
+    private final ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
 
     /**
      * A temporary copy of shortcuts that are to be cleared once persisted into AppSearch, keyed on
      * IDs.
      */
     @GuardedBy("mLock")
-    private ArrayMap<String, ShortcutInfo> mTransientShortcuts = new ArrayMap<>(0);
+    private final ArrayMap<String, ShortcutInfo> mTransientShortcuts = new ArrayMap<>(0);
 
     /**
      * All the share targets from the package
      */
+    @GuardedBy("mLock")
     private final ArrayList<ShareTargetInfo> mShareTargets = new ArrayList<>(0);
 
     /**
@@ -231,7 +232,9 @@
     }
 
     public int getShortcutCount() {
-        return mShortcuts.size();
+        synchronized (mLock) {
+            return mShortcuts.size();
+        }
     }
 
     @Override
@@ -272,7 +275,9 @@
     @Nullable
     public ShortcutInfo findShortcutById(@Nullable final String id) {
         if (id == null) return null;
-        return mShortcuts.get(id);
+        synchronized (mLock) {
+            return mShortcuts.get(id);
+        }
     }
 
     public boolean isShortcutExistsAndInvisibleToPublisher(String id) {
@@ -347,11 +352,14 @@
      * Delete a shortcut by ID. This will *always* remove it even if it's immutable or invisible.
      */
     private ShortcutInfo forceDeleteShortcutInner(@NonNull String id) {
-        final ShortcutInfo shortcut = mShortcuts.remove(id);
-        if (shortcut != null) {
-            removeIcon(shortcut);
-            shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
-                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED_ALL);
+        final ShortcutInfo shortcut;
+        synchronized (mLock) {
+            shortcut = mShortcuts.remove(id);
+            if (shortcut != null) {
+                removeIcon(shortcut);
+                shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
+                        | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED_ALL);
+            }
         }
         return shortcut;
     }
@@ -524,14 +532,16 @@
     public List<ShortcutInfo> deleteAllDynamicShortcuts() {
         final long now = mShortcutUser.mService.injectCurrentTimeMillis();
         boolean changed = false;
-        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
-            ShortcutInfo si = mShortcuts.valueAt(i);
-            if (si.isDynamic() && si.isVisibleToPublisher()) {
-                changed = true;
+        synchronized (mLock) {
+            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+                ShortcutInfo si = mShortcuts.valueAt(i);
+                if (si.isDynamic() && si.isVisibleToPublisher()) {
+                    changed = true;
 
-                si.setTimestamp(now);
-                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
-                si.setRank(0); // It may still be pinned, so clear the rank.
+                    si.setTimestamp(now);
+                    si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                    si.setRank(0); // It may still be pinned, so clear the rank.
+                }
             }
         }
         removeAllShortcutsAsync();
@@ -874,59 +884,63 @@
      */
     public List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets(
             @NonNull IntentFilter filter) {
-        final List<ShareTargetInfo> matchedTargets = new ArrayList<>();
-        for (int i = 0; i < mShareTargets.size(); i++) {
-            final ShareTargetInfo target = mShareTargets.get(i);
-            for (ShareTargetInfo.TargetData data : target.mTargetData) {
-                if (filter.hasDataType(data.mMimeType)) {
-                    // Matched at least with one data type
-                    matchedTargets.add(target);
-                    break;
-                }
-            }
-        }
-
-        if (matchedTargets.isEmpty()) {
-            return new ArrayList<>();
-        }
-
-        // Get the list of all dynamic shortcuts in this package.
-        final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
-        // Pass callingLauncher to ensure pinned flag marked by system ui, e.g. ShareSheet, are
-        // included in the result
-        findAll(shortcuts, ShortcutInfo::isNonManifestVisible,
-                ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION,
-                mShortcutUser.mService.mContext.getPackageName(),
-                0, /*getPinnedByAnyLauncher=*/ false);
-
-        final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
-        for (int i = 0; i < shortcuts.size(); i++) {
-            final Set<String> categories = shortcuts.get(i).getCategories();
-            if (categories == null || categories.isEmpty()) {
-                continue;
-            }
-            for (int j = 0; j < matchedTargets.size(); j++) {
-                // Shortcut must have all of share target categories
-                boolean hasAllCategories = true;
-                final ShareTargetInfo target = matchedTargets.get(j);
-                for (int q = 0; q < target.mCategories.length; q++) {
-                    if (!categories.contains(target.mCategories[q])) {
-                        hasAllCategories = false;
+        synchronized (mLock) {
+            final List<ShareTargetInfo> matchedTargets = new ArrayList<>();
+            for (int i = 0; i < mShareTargets.size(); i++) {
+                final ShareTargetInfo target = mShareTargets.get(i);
+                for (ShareTargetInfo.TargetData data : target.mTargetData) {
+                    if (filter.hasDataType(data.mMimeType)) {
+                        // Matched at least with one data type
+                        matchedTargets.add(target);
                         break;
                     }
                 }
-                if (hasAllCategories) {
-                    result.add(new ShortcutManager.ShareShortcutInfo(shortcuts.get(i),
-                            new ComponentName(getPackageName(), target.mTargetClass)));
-                    break;
+            }
+
+            if (matchedTargets.isEmpty()) {
+                return new ArrayList<>();
+            }
+
+            // Get the list of all dynamic shortcuts in this package.
+            final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+            // Pass callingLauncher to ensure pinned flag marked by system ui, e.g. ShareSheet, are
+            // included in the result
+            findAll(shortcuts, ShortcutInfo::isNonManifestVisible,
+                    ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION,
+                    mShortcutUser.mService.mContext.getPackageName(),
+                    0, /*getPinnedByAnyLauncher=*/ false);
+
+            final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
+            for (int i = 0; i < shortcuts.size(); i++) {
+                final Set<String> categories = shortcuts.get(i).getCategories();
+                if (categories == null || categories.isEmpty()) {
+                    continue;
+                }
+                for (int j = 0; j < matchedTargets.size(); j++) {
+                    // Shortcut must have all of share target categories
+                    boolean hasAllCategories = true;
+                    final ShareTargetInfo target = matchedTargets.get(j);
+                    for (int q = 0; q < target.mCategories.length; q++) {
+                        if (!categories.contains(target.mCategories[q])) {
+                            hasAllCategories = false;
+                            break;
+                        }
+                    }
+                    if (hasAllCategories) {
+                        result.add(new ShortcutManager.ShareShortcutInfo(shortcuts.get(i),
+                                new ComponentName(getPackageName(), target.mTargetClass)));
+                        break;
+                    }
                 }
             }
+            return result;
         }
-        return result;
     }
 
     public boolean hasShareTargets() {
-        return !mShareTargets.isEmpty();
+        synchronized (mLock) {
+            return !mShareTargets.isEmpty();
+        }
     }
 
     /**
@@ -935,38 +949,40 @@
      * the app's Xml resource.
      */
     int getSharingShortcutCount() {
-        if (mShareTargets.isEmpty()) {
-            return 0;
-        }
-
-        // Get the list of all dynamic shortcuts in this package
-        final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
-        findAll(shortcuts, ShortcutInfo::isNonManifestVisible,
-                ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
-
-        int sharingShortcutCount = 0;
-        for (int i = 0; i < shortcuts.size(); i++) {
-            final Set<String> categories = shortcuts.get(i).getCategories();
-            if (categories == null || categories.isEmpty()) {
-                continue;
+        synchronized (mLock) {
+            if (mShareTargets.isEmpty()) {
+                return 0;
             }
-            for (int j = 0; j < mShareTargets.size(); j++) {
-                // A SharingShortcut must have all of share target categories
-                boolean hasAllCategories = true;
-                final ShareTargetInfo target = mShareTargets.get(j);
-                for (int q = 0; q < target.mCategories.length; q++) {
-                    if (!categories.contains(target.mCategories[q])) {
-                        hasAllCategories = false;
+
+            // Get the list of all dynamic shortcuts in this package
+            final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+            findAll(shortcuts, ShortcutInfo::isNonManifestVisible,
+                    ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+
+            int sharingShortcutCount = 0;
+            for (int i = 0; i < shortcuts.size(); i++) {
+                final Set<String> categories = shortcuts.get(i).getCategories();
+                if (categories == null || categories.isEmpty()) {
+                    continue;
+                }
+                for (int j = 0; j < mShareTargets.size(); j++) {
+                    // A SharingShortcut must have all of share target categories
+                    boolean hasAllCategories = true;
+                    final ShareTargetInfo target = mShareTargets.get(j);
+                    for (int q = 0; q < target.mCategories.length; q++) {
+                        if (!categories.contains(target.mCategories[q])) {
+                            hasAllCategories = false;
+                            break;
+                        }
+                    }
+                    if (hasAllCategories) {
+                        sharingShortcutCount++;
                         break;
                     }
                 }
-                if (hasAllCategories) {
-                    sharingShortcutCount++;
-                    break;
-                }
             }
+            return sharingShortcutCount;
         }
-        return sharingShortcutCount;
     }
 
     /**
@@ -1090,19 +1106,25 @@
 
         // Now prepare to publish manifest shortcuts.
         List<ShortcutInfo> newManifestShortcutList = null;
-        try {
-            newManifestShortcutList = ShortcutParser.parseShortcuts(mShortcutUser.mService,
-                    getPackageName(), getPackageUserId(), mShareTargets);
-        } catch (IOException|XmlPullParserException e) {
-            Slog.e(TAG, "Failed to load shortcuts from AndroidManifest.xml.", e);
+        final int shareTargetSize;
+        synchronized (mLock) {
+            try {
+                shareTargetSize = mShareTargets.size();
+                newManifestShortcutList = ShortcutParser.parseShortcuts(mShortcutUser.mService,
+                        getPackageName(), getPackageUserId(), mShareTargets);
+            } catch (IOException | XmlPullParserException e) {
+                Slog.e(TAG, "Failed to load shortcuts from AndroidManifest.xml.", e);
+            }
         }
         final int manifestShortcutSize = newManifestShortcutList == null ? 0
                 : newManifestShortcutList.size();
         if (ShortcutService.DEBUG || ShortcutService.DEBUG_REBOOT) {
             Slog.d(TAG,
-                    String.format("Package %s has %d manifest shortcut(s), and %d share target(s)",
-                            getPackageName(), manifestShortcutSize, mShareTargets.size()));
+                    String.format(
+                            "Package %s has %d manifest shortcut(s), and %d share target(s)",
+                            getPackageName(), manifestShortcutSize, shareTargetSize));
         }
+
         if (isNewApp && (manifestShortcutSize == 0)) {
             // If it's a new app, and it doesn't have manifest shortcuts, then nothing to do.
 
@@ -1701,37 +1723,38 @@
     @Override
     public void saveToXml(@NonNull TypedXmlSerializer out, boolean forBackup)
             throws IOException, XmlPullParserException {
-        final int size = mShortcuts.size();
-        final int shareTargetSize = mShareTargets.size();
+        synchronized (mLock) {
+            final int size = mShortcuts.size();
+            final int shareTargetSize = mShareTargets.size();
 
-        if (hasNoShortcut() && shareTargetSize == 0 && mApiCallCount == 0) {
-            return; // nothing to write.
-        }
+            if (hasNoShortcut() && shareTargetSize == 0 && mApiCallCount == 0) {
+                return; // nothing to write.
+            }
 
-        out.startTag(null, TAG_ROOT);
+            out.startTag(null, TAG_ROOT);
 
-        ShortcutService.writeAttr(out, ATTR_NAME, getPackageName());
-        ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
-        ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
-        if (!forBackup) {
-            synchronized (mLock) {
-                ShortcutService.writeAttr(out, ATTR_SCHEMA_VERSON, (mIsAppSearchSchemaUpToDate)
+            ShortcutService.writeAttr(out, ATTR_NAME, getPackageName());
+            ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
+            ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
+            if (!forBackup) {
+                ShortcutService.writeAttr(out, ATTR_SCHEMA_VERSON, mIsAppSearchSchemaUpToDate
                         ? AppSearchShortcutInfo.SCHEMA_VERSION : 0);
             }
-        }
-        getPackageInfo().saveToXml(mShortcutUser.mService, out, forBackup);
+            getPackageInfo().saveToXml(mShortcutUser.mService, out, forBackup);
 
-        for (int j = 0; j < size; j++) {
-            saveShortcut(out, mShortcuts.valueAt(j), forBackup, getPackageInfo().isBackupAllowed());
-        }
-
-        if (!forBackup) {
-            for (int j = 0; j < shareTargetSize; j++) {
-                mShareTargets.get(j).saveToXml(out);
+            for (int j = 0; j < size; j++) {
+                saveShortcut(
+                        out, mShortcuts.valueAt(j), forBackup, getPackageInfo().isBackupAllowed());
             }
-        }
 
-        out.endTag(null, TAG_ROOT);
+            if (!forBackup) {
+                for (int j = 0; j < shareTargetSize; j++) {
+                    mShareTargets.get(j).saveToXml(out);
+                }
+            }
+
+            out.endTag(null, TAG_ROOT);
+        }
     }
 
     private void saveShortcut(TypedXmlSerializer out, ShortcutInfo si, boolean forBackup,
@@ -1917,38 +1940,38 @@
         synchronized (ret.mLock) {
             ret.mIsAppSearchSchemaUpToDate = ShortcutService.parseIntAttribute(
                     parser, ATTR_SCHEMA_VERSON, 0) == AppSearchShortcutInfo.SCHEMA_VERSION;
-        }
-        ret.mApiCallCount = ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
-        ret.mLastResetTime = ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
 
+            ret.mApiCallCount = ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
+            ret.mLastResetTime = ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
 
-        final int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-            final int depth = parser.getDepth();
-            final String tag = parser.getName();
-            if (depth == outerDepth + 1) {
-                switch (tag) {
-                    case ShortcutPackageInfo.TAG_ROOT:
-                        ret.getPackageInfo().loadFromXml(parser, fromBackup);
-
-                        continue;
-                    case TAG_SHORTCUT:
-                        final ShortcutInfo si = parseShortcut(parser, packageName,
-                                shortcutUser.getUserId(), fromBackup);
-                        // Don't use addShortcut(), we don't need to save the icon.
-                        ret.mShortcuts.put(si.getId(), si);
-                        continue;
-                    case TAG_SHARE_TARGET:
-                        ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
-                        continue;
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
                 }
+                final int depth = parser.getDepth();
+                final String tag = parser.getName();
+                if (depth == outerDepth + 1) {
+                    switch (tag) {
+                        case ShortcutPackageInfo.TAG_ROOT:
+                            ret.getPackageInfo().loadFromXml(parser, fromBackup);
+
+                            continue;
+                        case TAG_SHORTCUT:
+                            final ShortcutInfo si = parseShortcut(parser, packageName,
+                                    shortcutUser.getUserId(), fromBackup);
+                            // Don't use addShortcut(), we don't need to save the icon.
+                            ret.mShortcuts.put(si.getId(), si);
+                            continue;
+                        case TAG_SHARE_TARGET:
+                            ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
+                            continue;
+                    }
+                }
+                ShortcutService.warnForInvalidTag(depth, tag);
             }
-            ShortcutService.warnForInvalidTag(depth, tag);
         }
         return ret;
     }
@@ -2152,7 +2175,9 @@
 
     @VisibleForTesting
     List<ShareTargetInfo> getAllShareTargetsForTest() {
-        return new ArrayList<>(mShareTargets);
+        synchronized (mLock) {
+            return new ArrayList<>(mShareTargets);
+        }
     }
 
     @Override
@@ -2291,15 +2316,19 @@
 
     private void saveShortcut(@NonNull final Collection<ShortcutInfo> shortcuts) {
         Objects.requireNonNull(shortcuts);
-        for (ShortcutInfo si : shortcuts) {
-            mShortcuts.put(si.getId(), si);
+        synchronized (mLock) {
+            for (ShortcutInfo si : shortcuts) {
+                mShortcuts.put(si.getId(), si);
+            }
         }
     }
 
     @Nullable
     List<ShortcutInfo> findAll(@NonNull final Collection<String> ids) {
-        return ids.stream().map(mShortcuts::get)
-                .filter(Objects::nonNull).collect(Collectors.toList());
+        synchronized (mLock) {
+            return ids.stream().map(mShortcuts::get)
+                    .filter(Objects::nonNull).collect(Collectors.toList());
+        }
     }
 
     private void forEachShortcut(@NonNull final Consumer<ShortcutInfo> cb) {
@@ -2318,10 +2347,12 @@
 
     private void forEachShortcutStopWhen(
             @NonNull final Function<ShortcutInfo, Boolean> cb) {
-        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
-            final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (cb.apply(si)) {
-                return;
+        synchronized (mLock) {
+            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+                final ShortcutInfo si = mShortcuts.valueAt(i);
+                if (cb.apply(si)) {
+                    return;
+                }
             }
         }
     }
@@ -2461,6 +2492,7 @@
                         })));
     }
 
+    @GuardedBy("mLock")
     @Override
     void scheduleSaveToAppSearchLocked() {
         final Map<String, ShortcutInfo> copy = new ArrayMap<>(mShortcuts);
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index b37f980..247117e 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -124,8 +124,7 @@
                     LocalServices.getService(WindowManagerInternal.class);
             IBinder focusedWindowToken = windowManagerInternal.getFocusedWindowToken();
 
-            window = wmService.windowForClientLocked(null, focusedWindowToken,
-                    false /* throwOnError */);
+            window = wmService.getFocusedWindowLocked();
 
             if (window == null) {
                 EmbeddedWindowController.EmbeddedWindow embeddedWindow =
@@ -147,12 +146,6 @@
             }
 
             if (window == null) {
-                window = wmService.getFocusedWindowLocked();
-                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
-                        "Focused window found using wmService.getFocusedWindowLocked()");
-            }
-
-            if (window == null) {
                 // We don't have any focused window, fallback ont the top currentTask of the focused
                 // display.
                 ProtoLog.w(WM_DEBUG_BACK_PREVIEW,
@@ -194,7 +187,6 @@
             if (backType == BackNavigationInfo.TYPE_CALLBACK
                     || currentActivity == null
                     || currentTask == null
-                    || currentTask.getDisplayContent().getImeContainer().isVisible()
                     || currentActivity.isActivityTypeHome()) {
                 return infoBuilder
                         .setType(backType)
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2975a95..d0baa23 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2922,7 +2922,7 @@
     }
 
     DisplayCutout loadDisplayCutout(int displayWidth, int displayHeight) {
-        if (mDisplayPolicy == null) {
+        if (mDisplayPolicy == null || mInitialDisplayCutout == null) {
             return null;
         }
         return DisplayCutout.fromResourcesRectApproximation(
@@ -2931,7 +2931,7 @@
     }
 
     RoundedCorners loadRoundedCorners(int displayWidth, int displayHeight) {
-        if (mDisplayPolicy == null) {
+        if (mDisplayPolicy == null || mInitialRoundedCorners == null) {
             return null;
         }
         return RoundedCorners.fromResources(
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 65062e5..ea72e12 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -573,7 +573,7 @@
                             recentsAnimationController.getTargetAppDisplayArea();
                     if (targetDA != null) {
                         mRecentsAnimationInputConsumer.reparent(mInputTransaction, targetDA);
-                        mRecentsAnimationInputConsumer.show(mInputTransaction, MAX_VALUE - 1);
+                        mRecentsAnimationInputConsumer.show(mInputTransaction, MAX_VALUE - 2);
                         mAddRecentsAnimationInputConsumerHandle = false;
                     }
                 }
@@ -584,10 +584,14 @@
                     final Task rootTask = w.getTask().getRootTask();
                     mPipInputConsumer.mWindowHandle.replaceTouchableRegionWithCrop(
                             rootTask.getSurfaceControl());
+                    final DisplayArea targetDA = rootTask.getDisplayArea();
                     // We set the layer to z=MAX-1 so that it's always on top.
-                    mPipInputConsumer.reparent(mInputTransaction, rootTask);
-                    mPipInputConsumer.show(mInputTransaction, MAX_VALUE - 1);
-                    mAddPipInputConsumerHandle = false;
+                    if (targetDA != null) {
+                        mPipInputConsumer.layout(mInputTransaction, rootTask.getBounds());
+                        mPipInputConsumer.reparent(mInputTransaction, targetDA);
+                        mPipInputConsumer.show(mInputTransaction, MAX_VALUE - 1);
+                        mAddPipInputConsumerHandle = false;
+                    }
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 4068a97..c7f8a1e 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -158,7 +158,7 @@
     void continueStartingAnimations() {
         synchronized (mLock) {
             mAnimationStartDeferred = false;
-            if (!mPendingAnimations.isEmpty()) {
+            if (!mPendingAnimations.isEmpty() && mPreProcessingAnimations.isEmpty()) {
                 mChoreographer.postFrameCallback(this::startAnimations);
             }
         }
@@ -204,7 +204,7 @@
 
                             mPreProcessingAnimations.remove(animationLeash);
                             mPendingAnimations.put(animationLeash, runningAnim);
-                            if (!mAnimationStartDeferred) {
+                            if (!mAnimationStartDeferred && mPreProcessingAnimations.isEmpty()) {
                                 mChoreographer.postFrameCallback(this::startAnimations);
                             }
                         }
@@ -214,7 +214,7 @@
 
             if (!requiresEdgeExtension) {
                 mPendingAnimations.put(animationLeash, runningAnim);
-                if (!mAnimationStartDeferred) {
+                if (!mAnimationStartDeferred && mPreProcessingAnimations.isEmpty()) {
                     mChoreographer.postFrameCallback(this::startAnimations);
                 }
 
@@ -330,6 +330,14 @@
 
     private void startAnimations(long frameTimeNanos) {
         synchronized (mLock) {
+            if (!mPreProcessingAnimations.isEmpty()) {
+                // We only want to start running animations once all mPreProcessingAnimations have
+                // been processed to ensure preprocessed animations start in sync.
+                // NOTE: This means we might delay running animations that require preprocessing if
+                // new animations that also require preprocessing are requested before the previous
+                // ones have finished (see b/227449117).
+                return;
+            }
             startPendingAnimationsLocked();
         }
         mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
@@ -553,4 +561,4 @@
             return mAnimationHandler;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3906a19..a9f56d3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8877,16 +8877,18 @@
                 WindowState newFocusTarget =  displayContent == null
                         ? null : displayContent.findFocusedWindow();
                 if (newFocusTarget == null) {
-                    ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus remove request for "
-                                    + "win=%s dropped since no candidate was found",
+                    t.setFocusedWindow(null, null, displayId).apply();
+                    ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s"
+                                    + " dropped focus so setting focus to null since no candidate"
+                                    + " was found",
                             embeddedWindow);
                     return;
                 }
-                t.requestFocusTransfer(newFocusTarget.mInputChannelToken, newFocusTarget.getName(),
-                        inputToken, embeddedWindow.toString(),
+                t.setFocusedWindow(newFocusTarget.mInputChannelToken, newFocusTarget.getName(),
                         displayId).apply();
+
                 EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
-                        "Transfer focus request " + newFocusTarget,
+                        "Focus request " + newFocusTarget,
                         "reason=grantEmbeddedWindowFocus(false)");
             }
             ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index d2e56fa..ed9b2f0 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -378,7 +378,7 @@
     SurfaceControl.Builder makeSurface() {
         final SurfaceControl.Builder builder = super.makeSurface();
         if (mRoundedCornerOverlay) {
-            builder.setParent(null);
+            builder.setParent(getDisplayContent().getSurfaceControl());
         }
         return builder;
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8a7134e..7f466f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8513,6 +8513,13 @@
         }
     }
 
+    private boolean isDeviceOwnerUserId(int userId) {
+        synchronized (getLockObject()) {
+            return mOwners.getDeviceOwnerComponent() != null
+                    && mOwners.getDeviceOwnerUserId() == userId;
+        }
+    }
+
     private boolean isDeviceOwnerPackage(String packageName, int userId) {
         synchronized (getLockObject()) {
             return mOwners.hasDeviceOwner()
@@ -12117,10 +12124,11 @@
             return;
         }
         final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(isProfileOwner(caller)
+        Preconditions.checkCallAuthorization((isProfileOwner(caller)
+                        && isManagedProfile(caller.getUserId()))
                         || isDefaultDeviceOwner(caller),
-                "Caller is not profile owner or device owner;"
-                        + " only profile owner or device owner may control the preferential"
+                "Caller is not managed profile owner or device owner;"
+                        + " only managed profile owner or device owner may control the preferential"
                         + " network service");
         synchronized (getLockObject()) {
             final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
@@ -12147,11 +12155,12 @@
         }
 
         final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(isProfileOwner(caller)
+        Preconditions.checkCallAuthorization((isProfileOwner(caller)
+                        && isManagedProfile(caller.getUserId()))
                         || isDefaultDeviceOwner(caller),
-                "Caller is not profile owner or device owner;"
-                        + " only profile owner or device owner may retrieve the preferential"
-                        + " network service configurations");
+                "Caller is not managed profile owner or device owner;"
+                        + " only managed profile owner or device owner may retrieve the "
+                        + "preferential network service configurations");
         synchronized (getLockObject()) {
             final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
                     caller.getUserId());
@@ -18266,7 +18275,7 @@
 
     private void updateNetworkPreferenceForUser(int userId,
             List<PreferentialNetworkServiceConfig> preferentialNetworkServiceConfigs) {
-        if (!isManagedProfile(userId)) {
+        if (!isManagedProfile(userId) && !isDeviceOwnerUserId(userId)) {
             return;
         }
         List<ProfileNetworkPreference> preferences = new ArrayList<>();
diff --git a/services/proguard.flags b/services/proguard.flags
index 425da6c..bad02b4 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -33,6 +33,11 @@
   public <init>(...);
 }
 
+# Accessed from com.android.compos APEX
+-keep,allowoptimization,allowaccessmodification class com.android.internal.art.ArtStatsLog {
+   public static void write(...);
+}
+
 # Binder interfaces
 -keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface
 -keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface
diff --git a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt b/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
index cb97c9b..e78f0c7 100644
--- a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
@@ -20,9 +20,11 @@
 import android.content.ContextWrapper
 import android.hardware.display.DisplayViewport
 import android.hardware.input.InputManagerInternal
+import android.os.IInputConstants
 import android.os.test.TestLooper
 import android.platform.test.annotations.Presubmit
 import android.view.Display
+import android.view.PointerIcon
 import androidx.test.InstrumentationRegistry
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -31,6 +33,7 @@
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.doAnswer
@@ -38,6 +41,7 @@
 import org.mockito.Mockito.spy
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.junit.MockitoJUnit
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -219,4 +223,23 @@
             secondRequestLatch.await(100, TimeUnit.MILLISECONDS))
         verify(native, times(2)).setPointerDisplayId(anyInt())
     }
-}
\ No newline at end of file
+
+    @Test
+    fun onDisplayRemoved_resetAllAdditionalInputProperties() {
+        localService.setVirtualMousePointerDisplayId(10)
+        localService.setPointerIconVisible(false, 10)
+        verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL))
+        localService.setPointerAcceleration(5f, 10)
+        verify(native).setPointerAcceleration(eq(5f))
+
+        service.onDisplayRemoved(10)
+        verify(native).displayRemoved(eq(10))
+        verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED))
+        verify(native).setPointerAcceleration(
+            eq(IInputConstants.DEFAULT_POINTER_ACCELERATION.toFloat()))
+
+        localService.setVirtualMousePointerDisplayId(10)
+        verify(native).setPointerDisplayId(eq(10))
+        verifyNoMoreInteractions(native)
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index a227cd3..035249e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -70,6 +70,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -516,6 +517,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/231667368")
     @Test
     public void initRecoveryService_alwaysUpdatesCertsWhenTestRootCertIsUsed() throws Exception {
         int uid = Binder.getCallingUid();
@@ -539,6 +541,7 @@
                 testRootCertAlias)).isEqualTo(TestData.getInsecureCertPathForEndpoint2());
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/231667368")
     @Test
     public void initRecoveryService_updatesCertsIndependentlyForDifferentRoots() throws Exception {
         int uid = Binder.getCallingUid();
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 49cd343..873d9f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -306,6 +306,7 @@
         if (focus) {
             doReturn(window.getWindowInfo().token)
                     .when(mWindowManagerInternal).getFocusedWindowToken();
+            doReturn(window).when(mWm).getFocusedWindowLocked();
         }
     }
 }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index fa6de1a..ac1f376 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1673,4 +1673,9 @@
             return UNKNOWN;
         }
     }
+
+    /** @hide */
+    public static boolean isFailCauseExisting(@DataFailureCause int failCause) {
+        return sFailCauseMap.containsKey(failCause);
+    }
 }