Merge "Fixes statsd reports missing strings and SCS." into pi-dev
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index fbf690f..a8ad810 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -25,7 +25,6 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
-import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
 
@@ -108,6 +107,12 @@
     }
 
     public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
+        boolean isHorizontalDivision, Rect insets, int dockSide) {
+        this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets,
+            dockSide, false);
+    }
+
+    public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
             boolean isHorizontalDivision, Rect insets, int dockSide, boolean isMinimizedMode) {
         mMinFlingVelocityPxPerSecond =
                 MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density;
@@ -265,7 +270,11 @@
                 ? mDisplayHeight
                 : mDisplayWidth;
         int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
-        mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START,
+        int startPos = -mDividerSize;
+        if (dockedSide == DOCKED_RIGHT) {
+            startPos += mInsets.left;
+        }
+        mTargets.add(new SnapTarget(startPos, startPos, SnapTarget.FLAG_DISMISS_START,
                 0.35f));
         switch (mSnapMode) {
             case SNAP_MODE_16_9:
diff --git a/core/res/res/layout-television/autofill_save.xml b/core/res/res/layout-television/autofill_save.xml
index ebd2dec..e221008 100644
--- a/core/res/res/layout-television/autofill_save.xml
+++ b/core/res/res/layout-television/autofill_save.xml
@@ -62,8 +62,9 @@
                     android:textSize="24sp" />
             </LinearLayout>
 
-            <com.android.server.autofill.ui.CustomScrollView
+            <LinearLayout
                 android:id="@+id/autofill_save_custom_subtitle"
+                android:orientation="vertical"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="4dp"
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 6d677ab..8d89314 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -126,8 +126,10 @@
     private SnapTarget mSnapTargetBeforeMinimized;
 
     private int mDividerInsets;
+    private final Display mDefaultDisplay;
     private int mDisplayWidth;
     private int mDisplayHeight;
+    private int mDisplayRotation;
     private int mDividerWindowWidth;
     private int mDividerSize;
     private int mTouchElevation;
@@ -140,7 +142,7 @@
     private final Rect mDockedInsetRect = new Rect();
     private final Rect mOtherInsetRect = new Rect();
     private final Rect mLastResizeRect = new Rect();
-    private final Rect mDisplayRect = new Rect();
+    private final Rect mTmpRect = new Rect();
     private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
     private DividerWindowManager mWindowManager;
     private VelocityTracker mVelocityTracker;
@@ -274,6 +276,9 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, context.getDisplay(),
                 Choreographer.getInstance());
+        final DisplayManager displayManager =
+                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
     }
 
     @Override
@@ -373,7 +378,13 @@
         if (mStableInsets.isEmpty()) {
             SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
         }
-        repositionSnapTargetBeforeMinimized();
+
+        if (mState.mRatioPositionBeforeMinimized == 0) {
+            // Set the middle target as the initial state
+            mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
+        } else {
+            repositionSnapTargetBeforeMinimized();
+        }
     }
 
     public WindowManagerProxy getWindowManagerProxy() {
@@ -403,6 +414,11 @@
             mHandle.setTouching(true, animate);
         }
         mDockSide = mWindowManagerProxy.getDockSide();
+
+        // Update snap algorithm if rotation has occurred
+        if (mDisplayRotation != mDefaultDisplay.getRotation()) {
+            updateDisplayInfo();
+        }
         initializeSnapAlgorithm();
         mWindowManagerProxy.setResizing(true);
         if (touching) {
@@ -453,7 +469,7 @@
     private void initializeSnapAlgorithm() {
         if (mSnapAlgorithm == null) {
             mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
-                    mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
+                    mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets, mDockSide);
         }
         if (mMinimizedSnapAlgorithm == null) {
             mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
@@ -620,7 +636,10 @@
                 } else {
                     saveTarget = snapTarget;
                 }
-                saveSnapTargetBeforeMinimized(saveTarget);
+                if (saveTarget.position != mSnapAlgorithm.getDismissEndTarget().position
+                        && saveTarget.position != mSnapAlgorithm.getDismissStartTarget().position) {
+                    saveSnapTargetBeforeMinimized(saveTarget);
+                }
             }
         };
         Runnable notCancelledEndAction = () -> {
@@ -764,6 +783,8 @@
             initializeSnapAlgorithm();
             if (mIsInMinimizeInteraction != minimized) {
                 if (minimized) {
+                    // Relayout to recalculate the divider shadow when minimizing
+                    requestLayout();
                     mIsInMinimizeInteraction = true;
                     resizeStack(mMinimizedSnapAlgorithm.getMiddleTarget());
                 } else {
@@ -913,11 +934,9 @@
     }
 
     private void updateDisplayInfo() {
-        final DisplayManager displayManager =
-                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mDisplayRotation = mDefaultDisplay.getRotation();
         final DisplayInfo info = new DisplayInfo();
-        display.getDisplayInfo(info);
+        mDefaultDisplay.getDisplayInfo(info);
         mDisplayWidth = info.logicalWidth;
         mDisplayHeight = info.logicalHeight;
         mSnapAlgorithm = null;
@@ -991,44 +1010,47 @@
         if (mHomeStackResizable && mIsInMinimizeInteraction) {
             calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
                     mDockedTaskRect);
+            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
+                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
 
             // Move a right-docked-app to line up with the divider while dragging it
             if (mDockSide == DOCKED_RIGHT) {
                 mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
                         - mDockedTaskRect.left + mDividerSize, 0);
+                mOtherTaskRect.offset(mStableInsets.left, 0);
             }
-            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
-                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
             mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedTaskRect,
                     mOtherTaskRect, null);
             return;
         }
 
         if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
-            if (mCurrentAnimator != null) {
-                calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
-            } else {
-                calculateBoundsForPosition(isHorizontalDivision() ? mDisplayHeight : mDisplayWidth,
-                        mDockSide, mDockedTaskRect);
-            }
+            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
 
             // Move a docked app if from the right in position with the divider up to insets
             if (mDockSide == DOCKED_RIGHT) {
-                mDockedTaskRect.offset(Math.max(position,
-                        mStableInsets.left) - mDockedTaskRect.left, 0);
+                mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
+                        - mDockedTaskRect.left + mDividerSize, 0);
+                mOtherTaskRect.offset(mStableInsets.left, 0);
             }
             calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
                     mOtherTaskRect);
             mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
                     mOtherTaskRect, null);
         } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
-            calculateBoundsForPosition(taskPosition,
-                    mDockSide, mDockedTaskRect);
+            calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
+            mDockedInsetRect.set(mDockedTaskRect);
             calculateBoundsForPosition(mExitStartPosition,
                     DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
             mOtherInsetRect.set(mOtherTaskRect);
             applyExitAnimationParallax(mOtherTaskRect, position);
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
+
+            // Move a right-docked-app to line up with the divider while dragging it
+            if (mDockSide == DOCKED_RIGHT) {
+                mDockedTaskRect.offset(position - mStableInsets.left + mDividerSize, 0);
+                mOtherTaskRect.offset(mStableInsets.left, 0);
+            }
+            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedInsetRect,
                     mOtherTaskRect, mOtherInsetRect);
         } else if (taskPosition != TASK_POSITION_SAME) {
             calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
@@ -1040,17 +1062,17 @@
                     restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
             calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
             calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
-            mDisplayRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+            mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
             alignTopLeft(mDockedRect, mDockedTaskRect);
             alignTopLeft(mOtherRect, mOtherTaskRect);
             mDockedInsetRect.set(mDockedTaskRect);
             mOtherInsetRect.set(mOtherTaskRect);
             if (dockSideTopLeft(mDockSide)) {
-                alignTopLeft(mDisplayRect, mDockedInsetRect);
-                alignBottomRight(mDisplayRect, mOtherInsetRect);
+                alignTopLeft(mTmpRect, mDockedInsetRect);
+                alignBottomRight(mTmpRect, mOtherInsetRect);
             } else {
-                alignBottomRight(mDisplayRect, mDockedInsetRect);
-                alignTopLeft(mDisplayRect, mOtherInsetRect);
+                alignBottomRight(mTmpRect, mDockedInsetRect);
+                alignTopLeft(mTmpRect, mOtherInsetRect);
             }
             applyDismissingParallax(mDockedTaskRect, mDockSide, taskSnapTarget, position,
                     taskPositionDocked);
@@ -1269,23 +1291,22 @@
             startDragging(false /* animate */, false /* touching */);
         }
         updateDockSide();
-        int position = DockedDividerUtils.calculatePositionForBounds(event.initialRect,
-                mDockSide, mDividerSize);
         mEntranceAnimationRunning = true;
 
-        resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
+        resizeStack(calculatePositionForInsetBounds(), mSnapAlgorithm.getMiddleTarget().position,
                 mSnapAlgorithm.getMiddleTarget());
     }
 
     public void onRecentsDrawn() {
+        updateDockSide();
+        final int position = calculatePositionForInsetBounds();
         if (mState.animateAfterRecentsDrawn) {
             mState.animateAfterRecentsDrawn = false;
-            updateDockSide();
 
             mHandler.post(() -> {
                 // Delay switching resizing mode because this might cause jank in recents animation
                 // that's longer than this animation.
-                stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
+                stopDragging(position, getSnapAlgorithm().getMiddleTarget(),
                         mLongPressEntraceAnimDuration, Interpolators.FAST_OUT_SLOW_IN,
                         200 /* endDelay */);
             });
@@ -1294,7 +1315,7 @@
             mState.growAfterRecentsDrawn = false;
             updateDockSide();
             EventBus.getDefault().send(new RecentsGrowingEvent());
-            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
+            stopDragging(position, getSnapAlgorithm().getMiddleTarget(), 336,
                     Interpolators.FAST_OUT_SLOW_IN);
         }
     }
@@ -1315,4 +1336,10 @@
                     0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
         }
     }
+
+    private int calculatePositionForInsetBounds() {
+        mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+        mTmpRect.inset(mStableInsets);
+        return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize);
+    }
 }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 2c0e97e..aa426d3 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -762,26 +762,16 @@
     }
 
     /**
-     * Action taken when GattService is turned on
+     * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
      */
-    private void onBluetoothGattServiceUp() {
+    private void continueFromBleOnState() {
         if (DBG) {
-            Slog.d(TAG, "BluetoothGatt Service is Up");
+            Slog.d(TAG, "continueFromBleOnState()");
         }
         try {
             mBluetoothLock.readLock().lock();
             if (mBluetooth == null) {
-                if (DBG) {
-                    Slog.w(TAG, "onBluetoothServiceUp: mBluetooth is null!");
-                }
-                return;
-            }
-            int st = mBluetooth.getState();
-            if (st != BluetoothAdapter.STATE_BLE_ON) {
-                if (DBG) {
-                    Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: "
-                            + BluetoothAdapter.nameForState(st));
-                }
+                Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
                 return;
             }
             if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
@@ -1637,7 +1627,7 @@
                         if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
                             mBluetoothGatt =
                                     IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
-                            onBluetoothGattServiceUp();
+                            continueFromBleOnState();
                             break;
                         } // else must be SERVICE_IBLUETOOTH
 
@@ -2054,21 +2044,16 @@
                 if (DBG) {
                     Slog.d(TAG, "Bluetooth is in LE only mode");
                 }
-                if (mBluetoothGatt != null) {
-                    if (DBG) {
-                        Slog.d(TAG, "Calling BluetoothGattServiceUp");
-                    }
-                    onBluetoothGattServiceUp();
+                if (mBluetoothGatt != null || !mContext.getPackageManager()
+                            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+                    continueFromBleOnState();
                 } else {
                     if (DBG) {
                         Slog.d(TAG, "Binding Bluetooth GATT service");
                     }
-                    if (mContext.getPackageManager()
-                            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
-                        Intent i = new Intent(IBluetoothGatt.class.getName());
-                        doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
-                                UserHandle.CURRENT);
-                    }
+                    Intent i = new Intent(IBluetoothGatt.class.getName());
+                    doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
+                            UserHandle.CURRENT);
                 }
                 sendBleStateChanged(prevState, newState);
                 //Don't broadcase this as std intent
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 27eae57..698b6f7 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -800,6 +800,20 @@
         }
     }
 
+    /**
+     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     */
+    public void deferUpdateImeTarget() {
+        mWindowContainerController.deferUpdateImeTarget();
+    }
+
+    /**
+     * See {@link DisplayWindowController#deferUpdateImeTarget()}
+     */
+    public void continueUpdateImeTarget() {
+        mWindowContainerController.continueUpdateImeTarget();
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
         final String myPrefix = prefix + " ";
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a85df03..c182502 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -639,6 +639,9 @@
                 // so that the divider matches and remove this logic.
                 // TODO: This is currently only called when entering split-screen while in another
                 // task, and from the tests
+                // TODO (b/78247419): Check if launcher and overview are same then move home stack
+                // instead of recents stack. Then fix the rotation animation from fullscreen to
+                // minimized mode
                 final ActivityStack recentStack = display.getOrCreateStack(
                         WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS,
                         true /* onTop */);
@@ -4592,46 +4595,58 @@
             }
         }
 
-        // Shift all activities with this task up to the top
-        // of the stack, keeping them in the same internal order.
-        insertTaskAtTop(tr, null);
+        try {
+            // Defer updating the IME target since the new IME target will try to get computed
+            // before updating all closing and opening apps, which can cause the ime target to
+            // get calculated incorrectly.
+            getDisplay().deferUpdateImeTarget();
 
-        // Don't refocus if invisible to current user
-        final ActivityRecord top = tr.getTopActivity();
-        if (top == null || !top.okToShowLocked()) {
-            if (top != null) {
-                mStackSupervisor.mRecentTasks.add(top.getTask());
+            // Shift all activities with this task up to the top
+            // of the stack, keeping them in the same internal order.
+            insertTaskAtTop(tr, null);
+
+            // Don't refocus if invisible to current user
+            final ActivityRecord top = tr.getTopActivity();
+            if (top == null || !top.okToShowLocked()) {
+                if (top != null) {
+                    mStackSupervisor.mRecentTasks.add(top.getTask());
+                }
+                ActivityOptions.abort(options);
+                return;
             }
-            ActivityOptions.abort(options);
-            return;
-        }
 
-        // Set focus to the top running activity of this stack.
-        final ActivityRecord r = topRunningActivityLocked();
-        mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
+            // Set focus to the top running activity of this stack.
+            final ActivityRecord r = topRunningActivityLocked();
+            mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
 
-        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
-        if (noAnimation) {
-            mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
-            if (r != null) {
-                mStackSupervisor.mNoAnimActivities.add(r);
+            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
+            if (noAnimation) {
+                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+                if (r != null) {
+                    mStackSupervisor.mNoAnimActivities.add(r);
+                }
+                ActivityOptions.abort(options);
+            } else {
+                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
             }
-            ActivityOptions.abort(options);
-        } else {
-            updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
-        }
-        // If a new task is moved to the front, then mark the existing top activity as supporting
-        // picture-in-picture while paused only if the task would not be considered an oerlay on top
-        // of the current activity (eg. not fullscreen, or the assistant)
-        if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
-                options)) {
-            topActivity.supportsEnterPipOnTaskSwitch = true;
-        }
+            // If a new task is moved to the front, then mark the existing top activity as
+            // supporting
 
-        mStackSupervisor.resumeFocusedStackTopActivityLocked();
-        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+            // picture-in-picture while paused only if the task would not be considered an oerlay
+            // on top
+            // of the current activity (eg. not fullscreen, or the assistant)
+            if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
+                    options)) {
+                topActivity.supportsEnterPipOnTaskSwitch = true;
+            }
 
-        mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
+            mStackSupervisor.resumeFocusedStackTopActivityLocked();
+            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
+
+            mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
+        } finally {
+            getDisplay().continueUpdateImeTarget();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 5e29d10..bbdc924 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -339,7 +339,8 @@
 
                     // Collect information about the target of the Intent.
                     ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
-                            null, userId, realCallingUid);
+                            null, userId, ActivityStarter.computeResolveFilterUid(
+                                    callingUid, realCallingUid));
                     // TODO: New, check if this is correct
                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 3b18d32..bbf6e6c 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -791,7 +791,8 @@
                 callingUid = realCallingUid;
                 callingPid = realCallingPid;
 
-                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0, realCallingUid);
+                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
+                        computeResolveFilterUid(callingUid, realCallingUid));
                 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                         null /*profilerInfo*/);
 
@@ -955,6 +956,16 @@
         final int realCallingPid = Binder.getCallingPid();
         final int realCallingUid = Binder.getCallingUid();
 
+        int callingPid;
+        if (callingUid >= 0) {
+            callingPid = -1;
+        } else if (caller == null) {
+            callingPid = realCallingPid;
+            callingUid = realCallingUid;
+        } else {
+            callingPid = callingUid = -1;
+        }
+
         // Save a copy in case ephemeral needs it
         final Intent ephemeralIntent = new Intent(intent);
         // Don't modify the client's object!
@@ -973,7 +984,7 @@
         }
 
         ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
-                0 /* matchFlags */, realCallingUid);
+                0 /* matchFlags */, computeResolveFilterUid(callingUid, realCallingUid));
         if (rInfo == null) {
             UserInfo userInfo = mSupervisor.getUserInfo(userId);
             if (userInfo != null && userInfo.isManagedProfile()) {
@@ -995,7 +1006,7 @@
                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                             PackageManager.MATCH_DIRECT_BOOT_AWARE
                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                            realCallingUid);
+                            computeResolveFilterUid(callingUid, realCallingUid));
                 }
             }
         }
@@ -1003,16 +1014,6 @@
         ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
 
         synchronized (mService) {
-            int callingPid;
-            if (callingUid >= 0) {
-                callingPid = -1;
-            } else if (caller == null) {
-                callingPid = realCallingPid;
-                callingUid = realCallingUid;
-            } else {
-                callingPid = callingUid = -1;
-            }
-
             final ActivityStack stack = mSupervisor.mFocusedStack;
             stack.mConfigWillChange = globalConfig != null
                     && mService.getGlobalConfiguration().diff(globalConfig) != 0;
@@ -1077,7 +1078,8 @@
                         callingPid = Binder.getCallingPid();
                         componentSpecified = true;
                         rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
-                                0 /* matchFlags */, realCallingUid);
+                                0 /* matchFlags */, computeResolveFilterUid(callingUid,
+                                        realCallingUid));
                         aInfo = rInfo != null ? rInfo.activityInfo : null;
                         if (aInfo != null) {
                             aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -1164,6 +1166,19 @@
         }
     }
 
+    /**
+     * Compute the logical UID based on which the package manager would filter
+     * app components i.e. based on which the instant app policy would be applied
+     * because it is the logical calling UID.
+     *
+     * @param customCallingUid The UID on whose behalf to make the call.
+     * @param actualCallingUid The UID actually making the call.
+     * @return The logical UID making the call.
+     */
+    static int computeResolveFilterUid(int customCallingUid, int actualCallingUid) {
+        return customCallingUid >= 0 ? customCallingUid : actualCallingUid;
+    }
+
     private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 8ad8256..18c0957 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -64,6 +64,7 @@
 import android.os.IProgressListener;
 import android.os.IRemoteCallback;
 import android.os.IUserManager;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteCallbackList;
@@ -962,6 +963,11 @@
                     updateStartedUserArrayLU();
                     needStart = true;
                     updateUmState = true;
+                } else if (uss.state == UserState.STATE_SHUTDOWN && !isCallingOnHandlerThread()) {
+                    Slog.i(TAG, "User #" + userId
+                            + " is shutting down - will start after full stop");
+                    mHandler.post(() -> startUser(userId, foreground, unlockListener));
+                    return true;
                 }
                 final Integer userIdInt = userId;
                 mUserLru.remove(userIdInt);
@@ -1086,6 +1092,10 @@
         return true;
     }
 
+    private boolean isCallingOnHandlerThread() {
+        return Looper.myLooper() == mHandler.getLooper();
+    }
+
     /**
      * Start user, if its not already running, and bring it to foreground.
      */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c0dc750..f3423c6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -390,6 +390,11 @@
      */
     int mLayoutSeq = 0;
 
+    /**
+     * Specifies the count to determine whether to defer updating the IME target until ready.
+     */
+    private int mDeferUpdateImeTargetCount;
+
     /** Temporary float array to retrieve 3x3 matrix values. */
     private final float[] mTmpFloats = new float[9];
 
@@ -2454,6 +2459,12 @@
             return null;
         }
 
+        final WindowState curTarget = mService.mInputMethodTarget;
+        if (!canUpdateImeTarget()) {
+            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
+            return curTarget;
+        }
+
         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
         // same display. Or even when the current IME/target are not on the same screen as the next
         // IME/target. For now only look for input windows on the main screen.
@@ -2477,16 +2488,13 @@
         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
                 "Proposed new IME target: " + target);
 
-        // Now, a special case -- if the last target's window is in the process of exiting, and is
-        // above the new target, keep on the last target to avoid flicker. Consider for example a
-        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
-        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
-        // scrim.
-        final WindowState curTarget = mService.mInputMethodTarget;
+        // Now, a special case -- if the last target's window is in the process of exiting, and the
+        // new target is home, keep on the last target to avoid flicker. Home is a special case
+        // since its above other stacks in the ordering list, but layed out below the others.
         if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
-                && (target == null
-                    || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
-            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
+                && (target == null || target.isActivityTypeHome())) {
+            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is"
+                    + "closing, not changing");
             return curTarget;
         }
 
@@ -3958,4 +3966,33 @@
     void assignStackOrdering() {
         mTaskStackContainers.assignStackOrdering(getPendingTransaction());
     }
+
+    /**
+     * Increment the deferral count to determine whether to update the IME target.
+     */
+    void deferUpdateImeTarget() {
+        mDeferUpdateImeTargetCount++;
+    }
+
+    /**
+     * Decrement the deferral count to determine whether to update the IME target. If the count
+     * reaches 0, a new ime target will get computed.
+     */
+    void continueUpdateImeTarget() {
+        if (mDeferUpdateImeTargetCount == 0) {
+            return;
+        }
+
+        mDeferUpdateImeTargetCount--;
+        if (mDeferUpdateImeTargetCount == 0) {
+            computeImeTarget(true /* updateImeTarget */);
+        }
+    }
+
+    /**
+     * @return Whether a new IME target should be computed.
+     */
+    private boolean canUpdateImeTarget() {
+        return mDeferUpdateImeTargetCount == 0;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index ba8ec69..a1639c2 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -94,6 +94,31 @@
         }
     }
 
+    /**
+     * Starts deferring the ability to update the IME target. This is needed when a call will
+     * attempt to update the IME target before all information about the Windows have been updated.
+     */
+    public void deferUpdateImeTarget() {
+        synchronized (mWindowMap) {
+            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
+            if (dc != null) {
+                dc.deferUpdateImeTarget();
+            }
+        }
+    }
+
+    /**
+     * Resumes updating the IME target after deferring. See {@link #deferUpdateImeTarget()}
+     */
+    public void continueUpdateImeTarget() {
+        synchronized (mWindowMap) {
+            final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
+            if (dc != null) {
+                dc.continueUpdateImeTarget();
+            }
+        }
+    }
+
     @Override
     public String toString() {
         return "{DisplayWindowController displayId=" + mDisplayId + "}";
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c710c97..7883e2e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2726,7 +2726,7 @@
     }
 
     boolean isClosing() {
-        return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
+        return mAnimatingExit || (mAppToken.isAnimating() && mAppToken.hiddenRequested);
     }
 
     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {