Handling Launcher configuration change between touchDown and Launcher.onStart

If activity rotation is allowed, Launcher/recents can rotate while swipe animation
is running leading to inconsistencies between deviceProfile and rotation
> Using activity configuration to determine the rotation instead of using display rotation
> Removing rotation watcher when rotation is enabled as it is not used anymore

Bug: 158781568
Change-Id: I107d856cae80af111c0514656fac7ab1fa0c21cb
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index e825c5f..8d533bb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -275,8 +275,7 @@
         if (mActivity == activity) {
             return true;
         }
-        mTaskViewSimulator.setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
-                mDeviceState.getDisplayRotation());
+
         if (mActivity != null) {
             // The launcher may have been recreated as a result of device rotation.
             int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
@@ -329,6 +328,7 @@
         if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
             return;
         }
+        mTaskViewSimulator.setRecentsConfiguration(mActivity.getResources().getConfiguration());
 
         // If we've already ended the gesture and are going home, don't prepare recents UI,
         // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index ed07062..01936e4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -66,7 +66,7 @@
             }
         }
         RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState();
-        boolean canLauncherRotate = orientedState.canLauncherRotate();
+        boolean canLauncherRotate = orientedState.canRecentsActivityRotate();
         boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
 
         // Add overview actions to the menu when in in-place rotate landscape mode.
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 32da52e..46013d3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -22,6 +22,7 @@
 
 import android.animation.TimeInterpolator;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -125,6 +126,14 @@
     }
 
     /**
+     * @see com.android.quickstep.views.RecentsView#onConfigurationChanged(Configuration)
+     */
+    public void setRecentsConfiguration(Configuration configuration) {
+        mOrientationState.setActivityConfiguration(configuration);
+        mLayoutValid = false;
+    }
+
+    /**
      * @see com.android.quickstep.views.RecentsView#FULLSCREEN_PROGRESS
      */
     public float getFullScreenScale() {
@@ -205,7 +214,8 @@
     public void applyWindowToHomeRotation(Matrix matrix) {
         mMatrix.postTranslate(mDp.windowX, mDp.windowY);
         postDisplayRotation(deltaRotation(
-                mOrientationState.getLauncherRotation(), mOrientationState.getDisplayRotation()),
+                mOrientationState.getRecentsActivityRotation(),
+                mOrientationState.getDisplayRotation()),
                 mDp.widthPx, mDp.heightPx, matrix);
         matrix.postTranslate(-mRunningTargetWindowPosition.x, -mRunningTargetWindowPosition.y);
     }
@@ -226,7 +236,7 @@
             mPositionHelper.updateThumbnailMatrix(
                     mThumbnailPosition, mThumbnailData,
                     mTaskRect.width(), mTaskRect.height(),
-                    mDp, mOrientationState.getLauncherRotation());
+                    mDp, mOrientationState.getRecentsActivityRotation());
             mPositionHelper.getMatrix().invert(mInversePositionMatrix);
 
             PagedOrientationHandler poh = mOrientationState.getOrientationHandler();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index cb22570..92e3746 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -59,6 +59,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -393,6 +394,7 @@
         mActivity = BaseActivity.fromContext(context);
         mOrientationState = new RecentsOrientedState(
                 context, mSizeStrategy, this::animateRecentsRotationInPlace);
+        mOrientationState.setActivityConfiguration(context.getResources().getConfiguration());
 
         mFastFlingVelocity = getResources()
                 .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
@@ -1063,7 +1065,7 @@
     }
 
     private void animateRecentsRotationInPlace(int newRotation) {
-        if (mOrientationState.canLauncherRotate()) {
+        if (mOrientationState.canRecentsActivityRotate()) {
             // Let system take care of the rotation
             return;
         }
@@ -1646,29 +1648,41 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (mOrientationState.setActivityConfiguration(newConfig)) {
+            updateOrientationHandler();
+        }
+    }
+
     public void setLayoutRotation(int touchRotation, int displayRotation) {
         if (mOrientationState.update(touchRotation, displayRotation)) {
-            mOrientationHandler = mOrientationState.getOrientationHandler();
-            mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
-            setLayoutDirection(mIsRtl
-                    ? View.LAYOUT_DIRECTION_RTL
-                    : View.LAYOUT_DIRECTION_LTR);
-            mClearAllButton.setLayoutDirection(mIsRtl
-                    ? View.LAYOUT_DIRECTION_LTR
-                    : View.LAYOUT_DIRECTION_RTL);
-            mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
-            mActivity.getDragLayer().recreateControllers();
-            boolean isInLandscape = mOrientationState.getTouchRotation() != 0
-                    || mOrientationState.getLauncherRotation() != ROTATION_0;
-            mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
-                    !mOrientationState.canLauncherRotate() && isInLandscape);
-            resetPaddingFromTaskSize();
-            requestLayout();
-            // Reapply the current page to update page scrolls.
-            setCurrentPage(mCurrentPage);
+            updateOrientationHandler();
         }
     }
 
+    private void updateOrientationHandler() {
+        mOrientationHandler = mOrientationState.getOrientationHandler();
+        mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
+        setLayoutDirection(mIsRtl
+                ? View.LAYOUT_DIRECTION_RTL
+                : View.LAYOUT_DIRECTION_LTR);
+        mClearAllButton.setLayoutDirection(mIsRtl
+                ? View.LAYOUT_DIRECTION_LTR
+                : View.LAYOUT_DIRECTION_RTL);
+        mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
+        mActivity.getDragLayer().recreateControllers();
+        boolean isInLandscape = mOrientationState.getTouchRotation() != 0
+                || mOrientationState.getRecentsActivityRotation() != ROTATION_0;
+        mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
+                !mOrientationState.canRecentsActivityRotate() && isInLandscape);
+        resetPaddingFromTaskSize();
+        requestLayout();
+        // Reapply the current page to update page scrolls.
+        setCurrentPage(mCurrentPage);
+    }
+
     public RecentsOrientedState getPagedViewOrientedState() {
         return mOrientationState;
     }
@@ -2234,7 +2248,7 @@
             getCurrentPageTaskView().setModalness(modalness);
         }
         // Only show actions view when it's modal for in-place landscape mode.
-        boolean inPlaceLandscape = !mOrientationState.canLauncherRotate()
+        boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate()
                 && mOrientationState.getTouchRotation() != ROTATION_0;
         mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
     }
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index cefab1b..ae19d73 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -58,21 +58,6 @@
     }
 
     /**
-     * Gets the scale that should be applied to the TaskView so that it matches the target
-     * TODO: Remove this method
-     */
-    public static float getTaskScale(RecentsOrientedState orientedState,
-            float srcWidth, float srcHeight, float targetWidth, float targetHeight) {
-        if (orientedState == null
-                || orientedState.isHomeRotationAllowed()
-                || orientedState.isDisplayPhoneNatural()) {
-            return srcWidth / targetWidth;
-        } else {
-            return srcHeight / targetHeight;
-        }
-    }
-
-    /**
      * Recursively sets view and all children enabled/disabled.
      * @param view Top most parent view to change.
      * @param enabled True = enable, False = disable.
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 90ee18f..b9953cb 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -33,6 +33,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Matrix;
@@ -47,6 +48,7 @@
 
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile;
@@ -56,6 +58,7 @@
 import com.android.launcher3.util.WindowBounds;
 import com.android.quickstep.BaseActivityInterface;
 import com.android.quickstep.SysUINavigationMode;
+import com.android.systemui.shared.system.ConfigurationCompat;
 
 import java.lang.annotation.Retention;
 import java.util.function.IntConsumer;
@@ -87,7 +90,7 @@
 
     private @SurfaceRotation int mTouchRotation = ROTATION_0;
     private @SurfaceRotation int mDisplayRotation = ROTATION_0;
-    private @SurfaceRotation int mLauncherRotation = ROTATION_0;
+    private @SurfaceRotation int mRecentsActivityRotation = ROTATION_0;
 
     // Launcher activity supports multiple orientation, but fallback activity does not
     private static final int FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY = 1 << 0;
@@ -130,6 +133,8 @@
     private int mFlags;
     private int mPreviousRotation = ROTATION_0;
 
+    @Nullable private Configuration mActivityConfiguration;
+
     /**
      * @param rotationChangeListener Callback for receiving rotation events when rotation watcher
      *                              is enabled
@@ -165,6 +170,15 @@
     }
 
     /**
+     * Sets the configuration for the recents activity, which could affect the activity's rotation
+     * @see #update(int, int)
+     */
+    public boolean setActivityConfiguration(Configuration activityConfiguration) {
+        mActivityConfiguration = activityConfiguration;
+        return update(mTouchRotation, mDisplayRotation);
+    }
+
+    /**
      * Sets if the host is in multi-window mode
      */
     public void setMultiWindowMode(boolean isMultiWindow) {
@@ -188,23 +202,19 @@
      */
     public boolean update(
             @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) {
-        if (!isMultipleOrientationSupportedByDevice()) {
-            return false;
-        }
-
-        int launcherRotation = inferLauncherRotation(displayRotation);
+        int recentsActivityRotation = inferRecentsActivityRotation(displayRotation);
         if (mDisplayRotation == displayRotation
                 && mTouchRotation == touchRotation
-                && mLauncherRotation == launcherRotation) {
+                && mRecentsActivityRotation == recentsActivityRotation) {
             return false;
         }
 
-        mLauncherRotation = launcherRotation;
+        mRecentsActivityRotation = recentsActivityRotation;
         mDisplayRotation = displayRotation;
         mTouchRotation = touchRotation;
         mPreviousRotation = touchRotation;
 
-        if (mLauncherRotation == mTouchRotation || canLauncherRotate()) {
+        if (mRecentsActivityRotation == mTouchRotation || canRecentsActivityRotate()) {
             mOrientationHandler = PagedOrientationHandler.PORTRAIT;
             if (DEBUG) {
                 Log.d(TAG, "current RecentsOrientedState: " + this);
@@ -226,9 +236,11 @@
     }
 
     @SurfaceRotation
-    private int inferLauncherRotation(@SurfaceRotation int displayRotation) {
-        if (!isMultipleOrientationSupportedByDevice() || isHomeRotationAllowed()) {
-            return displayRotation;
+    private int inferRecentsActivityRotation(@SurfaceRotation int displayRotation) {
+        if (isRecentsActivityRotationAllowed()) {
+            return mActivityConfiguration == null
+                    ? displayRotation
+                    : ConfigurationCompat.getWindowConfigurationRotation(mActivityConfiguration);
         } else {
             return ROTATION_0;
         }
@@ -236,7 +248,8 @@
 
     private void setFlag(int mask, boolean enabled) {
         boolean wasRotationEnabled = !TestProtocol.sDisableSensorRotation
-                && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED;
+                && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
+                && !canRecentsActivityRotate();
         if (enabled) {
             mFlags |= mask;
         } else {
@@ -244,7 +257,8 @@
         }
 
         boolean isRotationEnabled = !TestProtocol.sDisableSensorRotation
-                && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED;
+                && (mFlags & VALUE_ROTATION_WATCHER_ENABLED) == VALUE_ROTATION_WATCHER_ENABLED
+                && !canRecentsActivityRotate();
         if (wasRotationEnabled != isRotationEnabled) {
             UI_HELPER_EXECUTOR.execute(() -> {
                 if (isRotationEnabled) {
@@ -324,8 +338,8 @@
     }
 
     @SurfaceRotation
-    public int getLauncherRotation() {
-        return mLauncherRotation;
+    public int getRecentsActivityRotation() {
+        return mRecentsActivityRotation;
     }
 
     public boolean isMultipleOrientationSupportedByDevice() {
@@ -333,14 +347,19 @@
                 == MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE;
     }
 
-    public boolean isHomeRotationAllowed() {
-        return (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS | FLAG_MULTIWINDOW_ROTATION_ALLOWED))
-                != 0 ||
-                (mFlags & FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING) != 0;
+    public boolean isRecentsActivityRotationAllowed() {
+        return ((mFlags & MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
+                == MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE)
+                || (mFlags & (FLAG_HOME_ROTATION_ALLOWED_IN_PREFS
+                        | FLAG_MULTIWINDOW_ROTATION_ALLOWED
+                        | FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING)) != 0;
     }
 
-    public boolean canLauncherRotate() {
-        return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isHomeRotationAllowed();
+    /**
+     * Returns true if the activity can rotate, if allowed by system rotation settings
+     */
+    public boolean canRecentsActivityRotate() {
+        return (mFlags & FLAG_SYSTEM_ROTATION_ALLOWED) != 0 && isRecentsActivityRotationAllowed();
     }
 
     /**
@@ -508,8 +527,8 @@
                     extractObjectNameAndAddress(mOrientationHandler.toString())
                 + " mDisplayRotation=" + mDisplayRotation
                 + " mTouchRotation=" + mTouchRotation
-                + " mLauncherRotation=" + mLauncherRotation
-                + " mHomeRotation=" + isHomeRotationAllowed()
+                + " mRecentsActivityRotation=" + mRecentsActivityRotation
+                + " isRecentsActivityRotationAllowed=" + isRecentsActivityRotationAllowed()
                 + " mSystemRotation=" + systemRotationOn
                 + " mFlags=" + mFlags
                 + "]";
@@ -521,7 +540,8 @@
     public DeviceProfile getLauncherDeviceProfile() {
         InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext);
         // TODO also check the natural orientation is landscape or portrait
-        return  (mLauncherRotation == ROTATION_90 || mLauncherRotation == ROTATION_270)
+        return  (mRecentsActivityRotation == ROTATION_90
+                || mRecentsActivityRotation == ROTATION_270)
                 ? idp.landscapeProfile
                 : idp.portraitProfile;
     }