Updating Launcher rotation logic
When auto-rotate is on, launcher allways allows rotation. This allows uses to use
locked rotation feature is available on the device
When auto-rotate is off, workspace does not allow rotation, but overview in quickstep
will allow rotation
Bug: 73872056
Change-Id: Ie12365c268fd5e4958634ed97b5a33dcadc691e2
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 38235f4..a1176f1 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -18,8 +18,7 @@
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER;
@@ -53,7 +52,6 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
@@ -116,6 +114,7 @@
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.states.InternalStateHandler;
+import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -272,10 +271,9 @@
private final PointF mLastDispatchTouchEvent = new PointF();
public ViewGroupFocusHelper mFocusHandler;
- private boolean mRotationEnabled = false;
private boolean mAppLaunchSuccess;
- private RotationPrefChangeHandler mRotationPrefChangeHandler;
+ private RotationHelper mRotationHelper;
private ActionMode mCurrentActionMode;
@Override
@@ -327,20 +325,10 @@
setupViews();
mPopupDataProvider = new PopupDataProvider(this);
- mRotationEnabled = getResources().getBoolean(R.bool.allow_rotation);
- // In case we are on a device with locked rotation, we should look at preferences to check
- // if the user has specifically allowed rotation.
- if (!mRotationEnabled) {
- mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext());
- mRotationPrefChangeHandler = new RotationPrefChangeHandler();
- mSharedPrefs.registerOnSharedPreferenceChangeListener(mRotationPrefChangeHandler);
- }
+ mRotationHelper = new RotationHelper(this);
boolean internalStateHandled = InternalStateHandler.handleCreate(this, getIntent());
if (internalStateHandled) {
- // Temporarily enable the rotation
- mRotationEnabled = true;
-
if (savedInstanceState != null) {
// InternalStateHandler has already set the appropriate state.
// We dont need to do anything.
@@ -372,7 +360,6 @@
// For handling default keys
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
- updateRequestedOrientation();
setContentView(mLauncherView);
getRootView().dispatchInsets();
@@ -391,17 +378,11 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
}
+ mRotationHelper.initialize();
TraceHelper.endSection("Launcher-onCreate");
}
- public void updateRequestedOrientation() {
- // On large interfaces, or on devices that a user has specifically enabled screen rotation,
- // we want the screen to auto-rotate based on the current orientation
- setRequestedOrientation(mRotationEnabled
- ? SCREEN_ORIENTATION_UNSPECIFIED : SCREEN_ORIENTATION_NOSENSOR);
- }
-
@Override
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
@@ -442,6 +423,10 @@
mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout());
}
+ public RotationHelper getRotationHelper() {
+ return mRotationHelper;
+ }
+
@Override
public void onThemeChanged() {
recreate();
@@ -1381,10 +1366,7 @@
mModel.stopLoader();
LauncherAppState.getInstance(this).setLauncher(null);
}
-
- if (mRotationPrefChangeHandler != null) {
- mSharedPrefs.unregisterOnSharedPreferenceChangeListener(mRotationPrefChangeHandler);
- }
+ mRotationHelper.destroy();
try {
mAppWidgetHost.stopListening();
@@ -2727,10 +2709,6 @@
mModel.refreshAndBindWidgetsAndShortcuts(packageUser);
}
- public boolean isRotationEnabled () {
- return mRotationEnabled;
- }
-
/**
* $ adb shell dumpsys activity com.android.launcher3.Launcher [--all]
*/
@@ -2868,18 +2846,6 @@
return ((Launcher) ((ContextWrapper) context).getBaseContext());
}
- private class RotationPrefChangeHandler implements OnSharedPreferenceChangeListener {
-
- @Override
- public void onSharedPreferenceChanged(
- SharedPreferences sharedPreferences, String key) {
- if (Utilities.ALLOW_ROTATION_PREFERENCE_KEY.equals(key)) {
- // Recreate the activity so that it initializes the rotation preference again.
- recreate();
- }
- }
- }
-
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 54df1da..4e6bcdc 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -20,12 +20,13 @@
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import android.view.View;
import android.view.animation.Interpolator;
-import com.android.launcher3.uioverrides.AllAppsState;
import com.android.launcher3.states.SpringLoadedState;
+import com.android.launcher3.uioverrides.AllAppsState;
import com.android.launcher3.uioverrides.FastOverviewState;
import com.android.launcher3.uioverrides.OverviewState;
import com.android.launcher3.uioverrides.UiFactory;
@@ -211,6 +212,8 @@
public void onStateTransitionEnd(Launcher launcher) {
if (this == NORMAL) {
UiFactory.resetOverview(launcher);
+ // Clear any rotation locks when going to normal state
+ launcher.getRotationHelper().setCurrentStateRequest(REQUEST_NONE);
}
}
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index d40ac8f..6a4e93b 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -65,7 +65,6 @@
*/
public static class LauncherSettingsFragment extends PreferenceFragment {
- private SystemDisplayRotationLockObserver mRotationLockObserver;
private IconBadgingObserver mIconBadgingObserver;
@Override
@@ -76,22 +75,6 @@
ContentResolver resolver = getActivity().getContentResolver();
- // Setup allow rotation preference
- Preference rotationPref = findPreference(Utilities.ALLOW_ROTATION_PREFERENCE_KEY);
- if (getResources().getBoolean(R.bool.allow_rotation)) {
- // Launcher supports rotation by default. No need to show this setting.
- getPreferenceScreen().removePreference(rotationPref);
- } else {
- mRotationLockObserver = new SystemDisplayRotationLockObserver(rotationPref, resolver);
-
- // Register a content observer to listen for system setting changes while
- // this UI is active.
- mRotationLockObserver.register(Settings.System.ACCELEROMETER_ROTATION);
-
- // Initialize the UI once
- rotationPref.setDefaultValue(Utilities.getAllowRotationDefaultValue(getActivity()));
- }
-
ButtonPreference iconBadgingPref =
(ButtonPreference) findPreference(ICON_BADGING_PREFERENCE_KEY);
if (!Utilities.ATLEAST_OREO) {
@@ -119,10 +102,6 @@
@Override
public void onDestroy() {
- if (mRotationLockObserver != null) {
- mRotationLockObserver.unregister();
- mRotationLockObserver = null;
- }
if (mIconBadgingObserver != null) {
mIconBadgingObserver.unregister();
mIconBadgingObserver = null;
@@ -132,28 +111,6 @@
}
/**
- * Content observer which listens for system auto-rotate setting changes, and enables/disables
- * the launcher rotation setting accordingly.
- */
- private static class SystemDisplayRotationLockObserver extends SettingsObserver.System {
-
- private final Preference mRotationPref;
-
- public SystemDisplayRotationLockObserver(
- Preference rotationPref, ContentResolver resolver) {
- super(resolver);
- mRotationPref = rotationPref;
- }
-
- @Override
- public void onSettingChanged(boolean enabled) {
- mRotationPref.setEnabled(enabled);
- mRotationPref.setSummary(enabled
- ? R.string.allow_rotation_desc : R.string.allow_rotation_blocked_desc);
- }
- }
-
- /**
* Content observer which listens for system badging setting changes,
* and updates the launcher badging setting subtext accordingly.
*/
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 31dab97..cabccbf 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -125,29 +125,10 @@
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
- public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
-
public static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
- public static boolean isAllowRotationPrefEnabled(Context context) {
- return getPrefs(context).getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
- getAllowRotationDefaultValue(context));
- }
-
- public static boolean getAllowRotationDefaultValue(Context context) {
- if (ATLEAST_NOUGAT) {
- // If the device was scaled, used the original dimensions to determine if rotation
- // is allowed of not.
- Resources res = context.getResources();
- int originalSmallestWidth = res.getConfiguration().smallestScreenWidthDp
- * res.getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEVICE_STABLE;
- return originalSmallestWidth >= 600;
- }
- return false;
- }
-
/**
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
* coordinates.
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index db199c1..95e1034 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -16,6 +16,11 @@
package com.android.launcher3.dragndrop;
+import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
+import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
+import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
+import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
+
import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.appwidget.AppWidgetManager;
@@ -23,7 +28,6 @@
import android.content.ClipDescription;
import android.content.Intent;
import android.content.pm.LauncherApps.PinItemRequest;
-import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.PointF;
@@ -43,7 +47,6 @@
import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompatVO;
import com.android.launcher3.model.WidgetItem;
@@ -55,11 +58,6 @@
import com.android.launcher3.widget.WidgetHostViewLoader;
import com.android.launcher3.widget.WidgetImageView;
-import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
-import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
-import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
-
@TargetApi(Build.VERSION_CODES.O)
public class AddItemActivity extends BaseActivity implements OnLongClickListener, OnTouchListener {
@@ -154,15 +152,7 @@
.setPackage(getPackageName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- if (!getResources().getBoolean(R.bool.allow_rotation) &&
- !Utilities.isAllowRotationPrefEnabled(this) &&
- (getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE && !isInMultiWindowMode())) {
- // If we are starting the drag in landscape even though home is locked in portrait,
- // restart the home activity to temporarily allow rotation.
- homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- }
-
+ listener.initWhenReady();
startActivity(homeIntent,
ActivityOptions.makeCustomAnimation(this, 0, android.R.anim.fade_out).toBundle());
mFinishOnPause = true;
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 9638a75..df4a7c1 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -17,6 +17,8 @@
package com.android.launcher3.dragndrop;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
+import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
import android.content.ClipDescription;
import android.content.Intent;
@@ -79,6 +81,7 @@
AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
launcher.getStateManager().goToState(NORMAL, alreadyOnHome /* animated */);
launcher.getDragLayer().setOnDragListener(this);
+ launcher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
mLauncher = launcher;
mDragController = launcher.getDragController();
@@ -157,6 +160,7 @@
}
private void postCleanup() {
+ clearReference();
if (mLauncher != null) {
// Remove any drag params from the launcher intent since the drag operation is complete.
Intent newIntent = new Intent(mLauncher.getIntent());
@@ -164,16 +168,12 @@
mLauncher.setIntent(newIntent);
}
- new Handler(Looper.getMainLooper()).post(new Runnable() {
- @Override
- public void run() {
- removeListener();
- }
- });
+ new Handler(Looper.getMainLooper()).post(this::removeListener);
}
public void removeListener() {
if (mLauncher != null) {
+ mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE);
mLauncher.getDragLayer().setOnDragListener(null);
}
}
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
new file mode 100644
index 0000000..8f83648
--- /dev/null
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 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.states;
+
+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_UNSPECIFIED;
+import static android.provider.Settings.System.ACCELEROMETER_ROTATION;
+import static android.provider.Settings.System.getUriFor;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+
+import com.android.launcher3.R;
+
+/**
+ * Utility class to manage launcher rotation
+ */
+public class RotationHelper extends ContentObserver {
+
+ public static final int REQUEST_NONE = 0;
+ public static final int REQUEST_ROTATE = 1;
+ public static final int REQUEST_LOCK = 2;
+
+ private final Activity mActivity;
+ private final ContentResolver mCr;
+
+ private final boolean mIgnoreAutoRotateSettings;
+ private boolean mAutoRotateEnabled;
+
+ /**
+ * Rotation request made by {@link InternalStateHandler}. This supersedes any other request.
+ */
+ private int mStateHandlerRequest = REQUEST_NONE;
+ /**
+ * Rotation request made by a Launcher State
+ */
+ private int mCurrentStateRequest = REQUEST_NONE;
+
+ // This is used to defer setting rotation flags until the activity is being created
+ private boolean mInitialized;
+ public boolean mDestroyed;
+
+ private int mLastActivityFlags = -1;
+
+ public RotationHelper(Activity activity) {
+ super(new Handler());
+ mActivity = activity;
+
+ // On large devices we do not handle auto-rotate differently.
+ mIgnoreAutoRotateSettings = mActivity.getResources().getBoolean(R.bool.allow_rotation);
+ if (!mIgnoreAutoRotateSettings) {
+ mCr = mActivity.getContentResolver();
+ mCr.registerContentObserver(getUriFor(ACCELEROMETER_ROTATION), false, this);
+ mAutoRotateEnabled = Settings.System.getInt(mCr, ACCELEROMETER_ROTATION, 1) == 1;
+ } else {
+ mCr = null;
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mAutoRotateEnabled = Settings.System.getInt(mCr, ACCELEROMETER_ROTATION, 1) == 1;
+ notifyChange();
+ }
+
+ public void setStateHandlerRequest(int request) {
+ if (mStateHandlerRequest != request) {
+ mStateHandlerRequest = request;
+ notifyChange();
+ }
+ }
+
+ public void setCurrentStateRequest(int request) {
+ if (mCurrentStateRequest != request) {
+ mCurrentStateRequest = request;
+ notifyChange();
+ }
+ }
+
+ public void initialize() {
+ if (!mInitialized) {
+ mInitialized = true;
+ notifyChange();
+ }
+ }
+
+ public void destroy() {
+ if (!mDestroyed) {
+ mDestroyed = true;
+ if (mCr != null) {
+ mCr.unregisterContentObserver(this);
+ }
+ }
+ }
+
+ private void notifyChange() {
+ if (!mInitialized || mDestroyed) {
+ return;
+ }
+
+ final int activityFlags;
+ if (mStateHandlerRequest != REQUEST_NONE) {
+ activityFlags = mStateHandlerRequest == REQUEST_LOCK ?
+ SCREEN_ORIENTATION_LOCKED : SCREEN_ORIENTATION_UNSPECIFIED;
+ } else if (mCurrentStateRequest == REQUEST_LOCK) {
+ activityFlags = SCREEN_ORIENTATION_LOCKED;
+ } else if (mIgnoreAutoRotateSettings || mCurrentStateRequest == REQUEST_ROTATE) {
+ activityFlags = SCREEN_ORIENTATION_UNSPECIFIED;
+ } else if (mAutoRotateEnabled) {
+ // If auto rotation is on, lock to device orientation
+ activityFlags = SCREEN_ORIENTATION_NOSENSOR;
+ } else {
+ // If auto rotation is off, allow rotation on the activity, in case the user is using
+ // forced rotation.
+ activityFlags = SCREEN_ORIENTATION_UNSPECIFIED;
+ }
+ if (activityFlags != mLastActivityFlags) {
+ mLastActivityFlags = activityFlags;
+ mActivity.setRequestedOrientation(mLastActivityFlags);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 4f8456f..89a9e2d 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -16,10 +16,9 @@
package com.android.launcher3.states;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
+import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
-import android.content.pm.ActivityInfo;
import android.graphics.Rect;
-import android.os.Handler;
import android.view.View;
import com.android.launcher3.DeviceProfile;
@@ -38,10 +37,6 @@
FLAG_DISABLE_ACCESSIBILITY | FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED |
FLAG_DISABLE_PAGE_CLIPPING | FLAG_PAGE_BACKGROUNDS;
- // Determines how long to wait after a rotation before restoring the screen orientation to
- // match the sensor state.
- private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500;
-
public SpringLoadedState(int id) {
super(id, ContainerType.OVERVIEW, SPRING_LOADED_TRANSITION_MS, STATE_FLAGS);
}
@@ -84,30 +79,16 @@
ws.showPageIndicatorAtCurrentScroll();
ws.getPageIndicator().setShouldAutoHide(false);
- // Lock the orientation:
- if (launcher.isRotationEnabled()) {
- launcher.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
- }
-
// Prevent any Un/InstallShortcutReceivers from updating the db while we are
// in spring loaded mode
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
+ launcher.getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
}
@Override
public void onStateDisabled(final Launcher launcher) {
launcher.getWorkspace().getPageIndicator().setShouldAutoHide(true);
- // Unlock rotation lock
- if (launcher.isRotationEnabled()) {
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- launcher.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- }
- }, RESTORE_SCREEN_ORIENTATION_DELAY);
- }
-
// Re-enable any Un/InstallShortcutReceiver and now process any queued items
InstallShortcutReceiver.disableAndFlushInstallQueue(
InstallShortcutReceiver.FLAG_DRAG_AND_DROP, launcher);