From 326d93bd562029c3ec313fc934fa2aba6b6e3555 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 1 Apr 2020 12:37:40 -0700 Subject: [PATCH] Re-enable home screen rotation Launcher home screen rotation now works with fixed transform. When using Quickstep while holding the phone from an orientation different than the orientation of the touch, the overview shown will be that of the phone orientation, not the touch orientation. Easier to see this be quickswitching from portrait to landscape app, turning phone, then going to overview from the original region you swiped. Fixes: 150214193 Test: Created test apps and fixed them to various rotations to test. Change-Id: Ic6565cd0ed33c951f45ccb97278045c6070e438e --- .../RecentsViewStateController.java | 6 +- .../uioverrides/states/OverviewState.java | 1 - .../android/quickstep/BaseSwipeUpHandler.java | 5 +- .../util/AppWindowAnimationHelper.java | 9 +- .../quickstep/views/LauncherRecentsView.java | 6 - .../android/quickstep/views/RecentsView.java | 44 ++++-- .../OrientationTouchTransformer.java | 16 +-- .../quickstep/util/RecentsOrientedState.java | 135 +++++++++++++++++- .../launcher3/states/RotationHelper.java | 125 +++++++--------- .../touch/HomeRotatedPageHandler.java | 49 +++++++ .../touch/LandscapePagedViewHandler.java | 7 +- .../touch/PagedOrientationHandler.java | 4 +- .../touch/PortraitPagedViewHandler.java | 7 +- .../touch/SeascapePagedViewHandler.java | 2 +- .../launcher3/views/FloatingIconView.java | 1 - 15 files changed, 294 insertions(+), 123 deletions(-) create mode 100644 src/com/android/launcher3/touch/HomeRotatedPageHandler.java diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 3d6e519d3f..2b13a1e756 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -26,6 +26,7 @@ import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import android.annotation.TargetApi; import android.os.Build; import android.util.FloatProperty; +import android.view.Surface; import android.view.View; import android.view.animation.Interpolator; @@ -91,8 +92,9 @@ public final class RecentsViewStateController extends buttonAlpha, LINEAR); View actionsView = mLauncher.getActionsView(); - if (actionsView != null) { - propertySetter.setFloat(actionsView, VIEW_ALPHA, buttonAlpha, actionInterpolator); + int launcherRotation = mRecentsView.getPagedViewOrientedState().getLauncherRotation(); + if (actionsView != null && launcherRotation == Surface.ROTATION_0) { + propertySetter.setViewAlpha(actionsView, buttonAlpha, actionInterpolator); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java index bcfb11c090..fc28da3f5d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -144,7 +144,6 @@ public class OverviewState extends LauncherState { @Override public void onStateTransitionEnd(Launcher launcher) { - launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE); DiscoveryBounce.showForOverviewIfNeeded(launcher); RecentsView recentsView = launcher.getOverviewPanel(); AccessibilityManagerCompat.sendCustomAccessibilityEvent( diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index fadde374ba..e7202e8e12 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -325,13 +325,14 @@ public abstract class BaseSwipeUpHandler } }; - private RotationHelper.ForcedRotationChangedListener mForcedRotationChangedListener = - isForcedRotation -> LauncherRecentsView.this - .disableMultipleLayoutRotations(!isForcedRotation); - public LauncherRecentsView(Context context) { this(context, null); } @@ -344,7 +340,6 @@ public class LauncherRecentsView extends RecentsView super.onAttachedToWindow(); PluginManagerWrapper.INSTANCE.get(getContext()).addPluginListener( mRecentsExtraCardPluginListener, RecentsExtraCard.class); - mActivity.getRotationHelper().addForcedRotationCallback(mForcedRotationChangedListener); } @Override @@ -352,7 +347,6 @@ public class LauncherRecentsView extends RecentsView super.onDetachedFromWindow(); PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener( mRecentsExtraCardPluginListener); - mActivity.getRotationHelper().removeForcedRotationCallback(mForcedRotationChangedListener); } @Override 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 a18f7bae05..e8d314dc95 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 @@ -50,6 +50,7 @@ import android.app.ActivityManager; 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.Rect; @@ -72,6 +73,7 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.OrientationEventListener; +import android.view.Surface; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; @@ -128,6 +130,7 @@ import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.ConfigurationCompat; import com.android.systemui.shared.system.LauncherEventUtil; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; @@ -172,7 +175,7 @@ public abstract class RecentsView extends PagedView impl } }; - protected final RecentsOrientedState mOrientationState = new RecentsOrientedState(); + protected RecentsOrientedState mOrientationState; private OrientationEventListener mOrientationListener; private int mPreviousRotation; @@ -343,6 +346,7 @@ public abstract class RecentsView extends PagedView impl super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); setEnableFreeScroll(true); + mOrientationState = new RecentsOrientedState(context); mFastFlingVelocity = getResources() .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); @@ -482,6 +486,7 @@ public abstract class RecentsView extends PagedView impl SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener( mIPinnedStackAnimationListener); setActionsView(); + mOrientationState.init(); } @Override @@ -496,6 +501,7 @@ public abstract class RecentsView extends PagedView impl mIdp.removeOnChangeListener(this); SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null); mIPinnedStackAnimationListener.setActivity(null); + mOrientationState.destroy(); } @Override @@ -549,9 +555,7 @@ public abstract class RecentsView extends PagedView impl } public void setOverviewStateEnabled(boolean enabled) { - if (supportsVerticalLandscape() - && !TestProtocol.sDisableSensorRotation // Ignore hardware dependency for tests - && mOrientationListener.canDetectOrientation()) { + if (canEnableOverviewRotationAnimation()) { if (enabled) { mOrientationListener.enable(); } else { @@ -567,6 +571,13 @@ public abstract class RecentsView extends PagedView impl } } + private boolean canEnableOverviewRotationAnimation() { + return supportsVerticalLandscape() // not 3P launcher + && !TestProtocol.sDisableSensorRotation // Ignore hardware dependency for tests.. + && mOrientationListener.canDetectOrientation() // ..but does the hardware even work? + && !mOrientationState.canLauncherAutoRotate(); // launcher is going to rotate itself + } + public void onDigitalWellbeingToastShown() { if (!mDwbToastShown) { mDwbToastShown = true; @@ -584,6 +595,15 @@ public abstract class RecentsView extends PagedView impl } } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int windowConfigurationRotation = ConfigurationCompat + .getWindowConfigurationRotation(getResources().getConfiguration()); + setLayoutInternal(mOrientationState.getTouchRotation(), + mOrientationState.getDisplayRotation(), windowConfigurationRotation); + } + @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); @@ -778,7 +798,7 @@ public abstract class RecentsView extends PagedView impl for (int i = 0; i < taskCount; i++) { getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress); } - if (mActionsView != null) { + if (mActionsView != null && mOrientationState.getLauncherRotation() == Surface.ROTATION_0) { mActionsView.setVisibility(fullscreenProgress == 0 ? VISIBLE : INVISIBLE); } } @@ -1561,11 +1581,17 @@ public abstract class RecentsView extends PagedView impl } public void setLayoutRotation(int touchRotation, int displayRotation) { - if (mOrientationState.update(touchRotation, displayRotation)) { + int launcherRotation = mOrientationState.getLauncherRotation(); + setLayoutInternal(touchRotation, displayRotation, launcherRotation); + } + + private void setLayoutInternal(int touchRotation, int displayRotation, int launcherRotation) { + if (mOrientationState.update(touchRotation, displayRotation, launcherRotation)) { mOrientationHandler = mOrientationState.getOrientationHandler(); mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources()); setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated()); + mActivity.getDragLayer().recreateControllers(); requestLayout(); } } @@ -2022,7 +2048,8 @@ public abstract class RecentsView extends PagedView impl public Consumer getEventDispatcher(float navbarRotation) { float degreesRotated; if (navbarRotation == 0) { - degreesRotated = mOrientationState.getTouchRotationDegrees(); + degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 : + mOrientationHandler.getDegreesRotated(); } else { degreesRotated = -navbarRotation; } @@ -2035,7 +2062,8 @@ public abstract class RecentsView extends PagedView impl // PagedOrientationHandler return e -> { if (navbarRotation != 0 - && !mOrientationState.areMultipleLayoutOrientationsDisabled()) { + && !mOrientationState.areMultipleLayoutOrientationsDisabled() + && !mOrientationState.getOrientationHandler().isLayoutNaturalToLauncher()) { mOrientationState.flipVertical(e); super.onTouchEvent(e); mOrientationState.flipVertical(e); diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java index 495c09297e..2e99500435 100644 --- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java +++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java @@ -22,6 +22,7 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_POINTER_DOWN; import static android.view.MotionEvent.ACTION_UP; +import static com.android.launcher3.states.RotationHelper.deltaRotation; import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation; import android.content.res.Resources; @@ -138,7 +139,8 @@ class OrientationTouchTransformer { * @param info The current displayInfo */ void enableMultipleRegions(boolean enableMultipleRegions, DefaultDisplay.Info info) { - mEnableMultipleRegions = enableMultipleRegions; + mEnableMultipleRegions = enableMultipleRegions && + mMode != SysUINavigationMode.Mode.TWO_BUTTONS; if (!enableMultipleRegions) { mQuickStepStartingRotation = -1; resetSwipeRegions(info); @@ -364,16 +366,4 @@ class OrientationTouchTransformer { return false; } } - - /** - * @return how many factors {@param newRotation} is rotated 90 degrees clockwise. - * E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise... - * A value of 0 means no rotation has been applied - */ - @SurfaceRotation - private static int deltaRotation(int oldRotation, int newRotation) { - int delta = newRotation - oldRotation; - if (delta < 0) delta += 4; - return delta; - } } diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index f72e4588ca..eefe8ac04b 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -16,20 +16,36 @@ package com.android.quickstep.util; +import static android.Manifest.permission.WRITE_SECURE_SETTINGS; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.hardware.camera2.params.OutputConfiguration.ROTATION_180; +import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; +import static com.android.launcher3.config.FeatureFlags.FLAG_ENABLE_FIXED_ROTATION_TRANSFORM; +import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY; +import static com.android.launcher3.states.RotationHelper.FIXED_ROTATION_TRANSFORM_SETTING_NAME; +import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.content.ContentResolver; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.database.ContentObserver; import android.graphics.Matrix; import android.graphics.RectF; +import android.os.Handler; +import android.provider.Settings; +import android.util.Log; import android.view.MotionEvent; import android.view.Surface; import androidx.annotation.IntDef; +import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.touch.PortraitPagedViewHandler; @@ -44,8 +60,17 @@ import java.lang.annotation.Retention; * This class has initial default state assuming the device and foreground app have * no ({@link Surface#ROTATION_0} rotation. */ -public final class RecentsOrientedState { +public final class RecentsOrientedState implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = "RecentsOrientedState"; + private static final boolean DEBUG = false; + + private ContentObserver mSystemAutoRotateObserver = new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + updateAutoRotateSetting(); + } + }; @Retention(SOURCE) @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) public @interface SurfaceRotation {} @@ -54,15 +79,45 @@ public final class RecentsOrientedState { private @SurfaceRotation int mTouchRotation = ROTATION_0; private @SurfaceRotation int mDisplayRotation = ROTATION_0; + private @SurfaceRotation int mLauncherRotation = Surface.ROTATION_0; + /** * If {@code true} we default to {@link PortraitPagedViewHandler} and don't support any fake * launcher orientations. */ private boolean mDisableMultipleOrientations; + private boolean mIsHomeRotationAllowed; + private boolean mIsSystemRotationAllowed; + + private final ContentResolver mContentResolver; + private final SharedPreferences mSharedPrefs; + private final boolean mAllowConfigurationDefaultValue; + private final Matrix mTmpMatrix = new Matrix(); private final Matrix mTmpInverseMatrix = new Matrix(); + public RecentsOrientedState(Context context) { + mContentResolver = context.getContentResolver(); + mSharedPrefs = Utilities.getPrefs(context); + + Resources res = context.getResources(); + int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp + * res.getDisplayMetrics().densityDpi / DENSITY_DEVICE_STABLE; + mAllowConfigurationDefaultValue = originalSmallestWidth >= 600; + + boolean isForcedRotation = Utilities.getFeatureFlagsPrefs(context) + .getBoolean(FLAG_ENABLE_FIXED_ROTATION_TRANSFORM, true) + && !mAllowConfigurationDefaultValue; + UI_HELPER_EXECUTOR.execute(() -> { + if (context.checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED) { + Settings.Global.putInt(mContentResolver, FIXED_ROTATION_TRANSFORM_SETTING_NAME, + isForcedRotation ? 1 : 0); + } + }); + disableMultipleOrientations(!isForcedRotation); + } + /** * Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler} * @param touchRotation The rotation the nav bar region that is touched is in @@ -72,19 +127,33 @@ public final class RecentsOrientedState { * false otherwise */ public boolean update( - @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) { + @SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation, + int launcherRotation) { if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) { return false; } if (mDisableMultipleOrientations) { return false; } - if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation) { + if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation + && launcherRotation == mLauncherRotation) { return false; } + mLauncherRotation = launcherRotation; mDisplayRotation = displayRotation; mTouchRotation = touchRotation; + + if ((mIsHomeRotationAllowed && mIsSystemRotationAllowed) || + mLauncherRotation == mTouchRotation) { + // TODO(b/153476489) Need to determine when launcher is rotated + mOrientationHandler = PagedOrientationHandler.HOME_ROTATED; + if (DEBUG) { + Log.d(TAG, "Set Orientation Handler: " + mOrientationHandler); + } + return true; + } + if (mTouchRotation == ROTATION_90) { mOrientationHandler = PagedOrientationHandler.LANDSCAPE; } else if (mTouchRotation == ROTATION_270) { @@ -92,6 +161,9 @@ public final class RecentsOrientedState { } else { mOrientationHandler = PagedOrientationHandler.PORTRAIT; } + if (DEBUG) { + Log.d(TAG, "Set Orientation Handler: " + mOrientationHandler); + } return true; } @@ -99,8 +171,12 @@ public final class RecentsOrientedState { return mDisableMultipleOrientations; } + public boolean canLauncherAutoRotate() { + return mIsHomeRotationAllowed && mIsSystemRotationAllowed; + } + /** - * Setting this preference will render future calls to {@link #update(int, int)} as a no-op. + * Setting this preference renders future calls to {@link #update(int, int, int)} as a no-op. */ public void disableMultipleOrientations(boolean disable) { mDisableMultipleOrientations = disable; @@ -110,6 +186,39 @@ public final class RecentsOrientedState { } } + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { + updateHomeRotationSetting(); + } + + private void updateAutoRotateSetting() { + try { + mIsSystemRotationAllowed = Settings.System.getInt(mContentResolver, + Settings.System.ACCELEROMETER_ROTATION) == 1; + } catch (Settings.SettingNotFoundException e) { + Log.e(TAG, "autorotate setting not found", e); + } + } + + private void updateHomeRotationSetting() { + mIsHomeRotationAllowed = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, + mAllowConfigurationDefaultValue); + } + + public void init() { + mSharedPrefs.registerOnSharedPreferenceChangeListener(this); + mContentResolver.registerContentObserver( + Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), + false, mSystemAutoRotateObserver); + updateAutoRotateSetting(); + updateHomeRotationSetting(); + } + + public void destroy() { + mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); + mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver); + } + @SurfaceRotation public int getDisplayRotation() { return mDisplayRotation; @@ -120,6 +229,14 @@ public final class RecentsOrientedState { return mTouchRotation; } + public boolean isHomeRotationAllowed() { + return mIsHomeRotationAllowed; + } + + public int getLauncherRotation() { + return mLauncherRotation; + } + public int getTouchRotationDegrees() { switch (mTouchRotation) { case ROTATION_90: @@ -166,8 +283,12 @@ public final class RecentsOrientedState { } public void mapRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) { + mapRectFromRotation(mDisplayRotation, src, screenWidth, screenHeight); + } + + public void mapRectFromRotation(int rotation, RectF src, int screenWidth, int screenHeight) { mTmpMatrix.reset(); - postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix); + postDisplayRotation(rotation, screenWidth, screenHeight, mTmpMatrix); mTmpMatrix.mapRect(src); } @@ -192,6 +313,10 @@ public final class RecentsOrientedState { } } + public boolean isDisplayPhoneNatural() { + return mDisplayRotation == Surface.ROTATION_0 || mDisplayRotation == Surface.ROTATION_180; + } + /** * Posts the transformation on the matrix representing the provided display rotation */ diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java index 2e0521f34c..3640d8bbde 100644 --- a/src/com/android/launcher3/states/RotationHelper.java +++ b/src/com/android/launcher3/states/RotationHelper.java @@ -15,47 +15,44 @@ */ package com.android.launcher3.states; -import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE; -import static com.android.launcher3.config.FeatureFlags.FLAG_ENABLE_FIXED_ROTATION_TRANSFORM; -import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; - import android.app.Activity; import android.content.ContentResolver; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.Resources; +import android.database.ContentObserver; +import android.os.Handler; import android.provider.Settings; +import android.util.Log; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.UiThreadHelper; -import java.util.ArrayList; -import java.util.List; - /** * Utility class to manage launcher rotation */ public class RotationHelper implements OnSharedPreferenceChangeListener { + private static final String TAG = "RotationHelper"; + public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation"; public static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform"; private final ContentResolver mContentResolver; + private boolean mSystemAutoRotateEnabled; - /** - * Listener to receive changes when {@link #FIXED_ROTATION_TRANSFORM_SETTING_NAME} flag changes. - */ - public interface ForcedRotationChangedListener { - void onForcedRotationChanged(boolean isForcedRotation); - } + private ContentObserver mSystemAutoRotateObserver = new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + updateAutoRotateSetting(); + } + }; public static boolean getAllowRotationDefaultValue() { // If the device's pixel density was scaled (usually via settings for A11y), use the @@ -72,12 +69,9 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { private final Activity mActivity; private final SharedPreferences mSharedPrefs; - private final SharedPreferences mFeatureFlagsPrefs; private boolean mIgnoreAutoRotateSettings; - private boolean mAutoRotateEnabled; - private boolean mForcedRotation; - private List mForcedRotationChangedListeners = new ArrayList<>(); + private boolean mHomeRotationEnabled; /** * Rotation request made by @@ -108,67 +102,35 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { if (!mIgnoreAutoRotateSettings) { mSharedPrefs = Utilities.getPrefs(mActivity); mSharedPrefs.registerOnSharedPreferenceChangeListener(this); - mAutoRotateEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, + mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, getAllowRotationDefaultValue()); } else { mSharedPrefs = null; } mContentResolver = activity.getContentResolver(); - mFeatureFlagsPrefs = Utilities.getFeatureFlagsPrefs(mActivity); - mFeatureFlagsPrefs.registerOnSharedPreferenceChangeListener(this); - updateForcedRotation(true); } - /** - * @param setValueFromPrefs If true, then {@link #mForcedRotation} will get set to the value - * from the home developer settings. Otherwise it will not. - * This is primarily to allow tests to set their own conditions. - */ - private void updateForcedRotation(boolean setValueFromPrefs) { - boolean isForcedRotation = mFeatureFlagsPrefs - .getBoolean(FLAG_ENABLE_FIXED_ROTATION_TRANSFORM, true) - && !getAllowRotationDefaultValue(); - if (mForcedRotation == isForcedRotation) { - return; + private void updateAutoRotateSetting() { + int autoRotateEnabled = 0; + try { + autoRotateEnabled = Settings.System.getInt(mContentResolver, + Settings.System.ACCELEROMETER_ROTATION); + } catch (Settings.SettingNotFoundException e) { + Log.e(TAG, "autorotate setting not found", e); } - if (setValueFromPrefs) { - mForcedRotation = isForcedRotation; - } - UI_HELPER_EXECUTOR.execute(() -> { - if (mActivity.checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED) { - Settings.Global.putInt(mContentResolver, FIXED_ROTATION_TRANSFORM_SETTING_NAME, - mForcedRotation ? 1 : 0); - } - }); - for (ForcedRotationChangedListener listener : mForcedRotationChangedListeners) { - listener.onForcedRotationChanged(mForcedRotation); - } - } - /** - * will not be called when first registering the listener. - */ - public void addForcedRotationCallback(ForcedRotationChangedListener listener) { - mForcedRotationChangedListeners.add(listener); - } - - public void removeForcedRotationCallback(ForcedRotationChangedListener listener) { - mForcedRotationChangedListeners.remove(listener); + mSystemAutoRotateEnabled = autoRotateEnabled == 1; } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { - if (FLAG_ENABLE_FIXED_ROTATION_TRANSFORM.equals(s)) { - updateForcedRotation(true); - return; - } - - boolean wasRotationEnabled = mAutoRotateEnabled; - mAutoRotateEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, + boolean wasRotationEnabled = mHomeRotationEnabled; + mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, getAllowRotationDefaultValue()); - if (mAutoRotateEnabled != wasRotationEnabled) { + if (mHomeRotationEnabled != wasRotationEnabled) { notifyChange(); + updateAutoRotateSetting(); } } @@ -197,10 +159,6 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { public void forceAllowRotationForTesting(boolean allowRotation) { mIgnoreAutoRotateSettings = allowRotation || mActivity.getResources().getBoolean(R.bool.allow_rotation); - // TODO(b/150214193) Tests currently expect launcher to be able to be rotated - // Modify tests for this new behavior - mForcedRotation = !allowRotation; - updateForcedRotation(false); notifyChange(); } @@ -208,6 +166,11 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { if (!mInitialized) { mInitialized = true; notifyChange(); + + mContentResolver.registerContentObserver( + Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), + false, mSystemAutoRotateObserver); + updateAutoRotateSetting(); } } @@ -217,8 +180,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { if (mSharedPrefs != null) { mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); } - mForcedRotationChangedListeners.clear(); - mFeatureFlagsPrefs.unregisterOnSharedPreferenceChangeListener(this); + mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver); } } @@ -228,10 +190,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { } final int activityFlags; - if (mForcedRotation) { - // TODO(b/150214193) Properly address this - activityFlags = SCREEN_ORIENTATION_PORTRAIT; - } else if (mStateHandlerRequest != REQUEST_NONE) { + if (mStateHandlerRequest != REQUEST_NONE) { activityFlags = mStateHandlerRequest == REQUEST_LOCK ? SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED; } else if (mCurrentTransitionRequest != REQUEST_NONE) { @@ -240,7 +199,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { } else if (mCurrentStateRequest == REQUEST_LOCK) { activityFlags = SCREEN_ORIENTATION_LOCKED; } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE - || mAutoRotateEnabled) { + || mHomeRotationEnabled) { activityFlags = SCREEN_ORIENTATION_UNSPECIFIED; } else { // If auto rotation is off, allow rotation on the activity, in case the user is using @@ -253,11 +212,23 @@ public class RotationHelper implements OnSharedPreferenceChangeListener { } } + /** + * @return how many factors {@param newRotation} is rotated 90 degrees clockwise. + * E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise... + * A value of 0 means no rotation has been applied + */ + public static int deltaRotation(int oldRotation, int newRotation) { + int delta = newRotation - oldRotation; + if (delta < 0) delta += 4; + return delta; + } + @Override public String toString() { return String.format("[mStateHandlerRequest=%d, mCurrentStateRequest=%d," - + " mLastActivityFlags=%d, mIgnoreAutoRotateSettings=%b, mAutoRotateEnabled=%b]", + + " mLastActivityFlags=%d, mIgnoreAutoRotateSettings=%b, mHomeRotationEnabled=%b," + + " mSystemAutoRotateEnabled=%b]", mStateHandlerRequest, mCurrentStateRequest, mLastActivityFlags, - mIgnoreAutoRotateSettings, mAutoRotateEnabled); + mIgnoreAutoRotateSettings, mHomeRotationEnabled, mSystemAutoRotateEnabled); } } diff --git a/src/com/android/launcher3/touch/HomeRotatedPageHandler.java b/src/com/android/launcher3/touch/HomeRotatedPageHandler.java new file mode 100644 index 0000000000..710b676880 --- /dev/null +++ b/src/com/android/launcher3/touch/HomeRotatedPageHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.touch; + +import android.graphics.RectF; +import android.view.Surface; + +public class HomeRotatedPageHandler extends PortraitPagedViewHandler { + @Override + public void offsetTaskRect(RectF rect, float value, int displayRotation, int launcherRotation) { + if (launcherRotation == Surface.ROTATION_0) { + super.offsetTaskRect(rect, value, displayRotation, launcherRotation); + } else if (launcherRotation == Surface.ROTATION_90) { + if (displayRotation == Surface.ROTATION_0) { + rect.offset(0, value); + } else if (displayRotation == Surface.ROTATION_90) { + rect.offset(value, 0); + } else if (displayRotation == Surface.ROTATION_180) { + rect.offset(-value, 0); + } else { + rect.offset(-value, 0); + } + } else if (launcherRotation == Surface.ROTATION_270) { + if (displayRotation == Surface.ROTATION_0) { + rect.offset(0, -value); + } else if (displayRotation == Surface.ROTATION_90) { + rect.offset(value, 0); + } else if (displayRotation == Surface.ROTATION_180) { + rect.offset(0, -value); + } else { + rect.offset(value, 0); + } + } // TODO (b/149609488) handle 180 case as well + } +} diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index bab574774a..f9f3bf4bc1 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -77,6 +77,11 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { return displacement > 0; } + @Override + public boolean isLayoutNaturalToLauncher() { + return false; + } + @Override public void adjustFloatingIconStartVelocity(PointF velocity) { float oldX = velocity.x; @@ -182,7 +187,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { } @Override - public void offsetTaskRect(RectF rect, float value, int displayRotation) { + public void offsetTaskRect(RectF rect, float value, int displayRotation, int launcherRotation) { if (displayRotation == Surface.ROTATION_0) { rect.offset(0, value); } else if (displayRotation == Surface.ROTATION_90) { diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 50606ec8ae..ba4c064f5b 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -42,6 +42,7 @@ public interface PagedOrientationHandler { PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler(); PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler(); PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler(); + PagedOrientationHandler HOME_ROTATED = new HomeRotatedPageHandler(); interface Int2DAction { void call(T target, int x, int y); @@ -79,7 +80,7 @@ public interface PagedOrientationHandler { void setMaxScroll(AccessibilityEvent event, int maxScroll); boolean getRecentsRtlSetting(Resources resources); float getDegreesRotated(); - void offsetTaskRect(RectF rect, float value, int delta); + void offsetTaskRect(RectF rect, float value, int delta, int launcherRotation); int getPrimaryValue(int x, int y); int getSecondaryValue(int x, int y); void delegateScrollTo(PagedView pagedView, int secondaryScroll, int primaryScroll); @@ -89,6 +90,7 @@ public interface PagedOrientationHandler { void scrollerStartScroll(OverScroller scroller, int newPosition); void getCurveProperties(PagedView view, Rect insets, CurveProperties out); boolean isGoingUp(float displacement); + boolean isLayoutNaturalToLauncher(); /** * Maps the velocity from the coordinate plane of the foreground app to that diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 245138f7a1..7c44ebab0c 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -77,6 +77,11 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { return displacement < 0; } + @Override + public boolean isLayoutNaturalToLauncher() { + return true; + } + @Override public void adjustFloatingIconStartVelocity(PointF velocity) { //no-op @@ -180,7 +185,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } @Override - public void offsetTaskRect(RectF rect, float value, int displayRotation) { + public void offsetTaskRect(RectF rect, float value, int displayRotation, int launcherRotation) { if (displayRotation == Surface.ROTATION_0) { rect.offset(value, 0); } else if (displayRotation == Surface.ROTATION_90) { diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java index eebd87fc86..5ce8a5763e 100644 --- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java @@ -36,7 +36,7 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { } @Override - public void offsetTaskRect(RectF rect, float value, int displayRotation) { + public void offsetTaskRect(RectF rect, float value, int displayRotation, int launcherRotation) { if (displayRotation == Surface.ROTATION_0) { rect.offset(0, value); } else if (displayRotation == Surface.ROTATION_90) { diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index e114cf8499..5b3840f756 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -124,7 +124,6 @@ public class FloatingIconView extends FrameLayout implements super.onAttachedToWindow(); if (!mIsOpening) { getViewTreeObserver().addOnGlobalLayoutListener(this); - mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK); } }