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:
parent
a976a2212d
commit
326d93bd56
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -124,7 +124,6 @@ public class FloatingIconView extends FrameLayout implements
|
|||
super.onAttachedToWindow();
|
||||
if (!mIsOpening) {
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(this);
|
||||
mLauncher.getRotationHelper().setCurrentTransitionRequest(REQUEST_LOCK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue