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
This commit is contained in:
Vinit Nayak 2020-04-01 12:37:40 -07:00
parent a976a2212d
commit 326d93bd56
15 changed files with 294 additions and 123 deletions

View File

@ -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);
}
}

View File

@ -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(

View File

@ -325,13 +325,14 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
mAppWindowAnimationHelper.updateHomeBounds(getStackBounds(dp));
}
int displayRotation = 0;
if (mOrientedState != null) {
if (mOrientedState != null && !mOrientedState.areMultipleLayoutOrientationsDisabled()) {
// TODO(b/150300347): The first recents animation after launcher is started with the
// foreground app not in landscape will look funky until that bug is fixed
displayRotation = mOrientedState.getDisplayRotation();
RectF tempRectF = new RectF(TEMP_RECT);
mOrientedState.mapRectFromNormalOrientation(tempRectF, dp.widthPx, dp.heightPx);
mOrientedState.mapRectFromRotation(displayRotation,
tempRectF, dp.widthPx, dp.heightPx);
tempRectF.roundOut(TEMP_RECT);
}
mAppWindowAnimationHelper.updateTargetRect(TEMP_RECT);

View File

@ -160,9 +160,9 @@ public class AppWindowAnimationHelper {
}
private float getSrcToTargetScale() {
if (mOrientedState == null ||
(mOrientedState.getDisplayRotation() == Surface.ROTATION_0
|| mOrientedState.getDisplayRotation() == Surface.ROTATION_180)) {
if (mOrientedState == null
|| mOrientedState.isHomeRotationAllowed()
|| mOrientedState.isDisplayPhoneNatural()) {
return mSourceRect.width() / mTargetRect.width();
} else {
return mSourceRect.height() / mTargetRect.height();
@ -277,8 +277,9 @@ public class AppWindowAnimationHelper {
mCurrentRect.offset(params.mOffset, 0);
} else {
int displayRotation = mOrientedState.getDisplayRotation();
int launcherRotation = mOrientedState.getLauncherRotation();
mOrientedState.getOrientationHandler().offsetTaskRect(mCurrentRect,
params.mOffset, displayRotation);
params.mOffset, displayRotation, launcherRotation);
}
}

View File

@ -88,10 +88,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
}
};
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<BaseQuickstepLauncher>
super.onAttachedToWindow();
PluginManagerWrapper.INSTANCE.get(getContext()).addPluginListener(
mRecentsExtraCardPluginListener, RecentsExtraCard.class);
mActivity.getRotationHelper().addForcedRotationCallback(mForcedRotationChangedListener);
}
@Override
@ -352,7 +347,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
super.onDetachedFromWindow();
PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(
mRecentsExtraCardPluginListener);
mActivity.getRotationHelper().removeForcedRotationCallback(mForcedRotationChangedListener);
}
@Override

View File

@ -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<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> extends PagedView impl
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
mIPinnedStackAnimationListener);
setActionsView();
mOrientationState.init();
}
@Override
@ -496,6 +501,7 @@ public abstract class RecentsView<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> 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<T extends BaseActivity> extends PagedView impl
public Consumer<MotionEvent> 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<T extends BaseActivity> 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);

View File

@ -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;
}
}

View File

@ -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
*/

View File

@ -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<ForcedRotationChangedListener> 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);
}
}

View File

@ -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
}
}

View File

@ -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) {

View File

@ -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<T> {
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

View File

@ -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) {

View File

@ -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) {

View File

@ -124,7 +124,6 @@ public class FloatingIconView extends FrameLayout implements
super.onAttachedToWindow();
if (!mIsOpening) {
getViewTreeObserver().addOnGlobalLayoutListener(this);
mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
}
}