summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java31
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java144
3 files changed, 168 insertions, 8 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2ec4906f082b..d3d4ec3a62c0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6802,6 +6802,37 @@ public final class Settings {
public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled";
/**
+ * Control if rotation suggestions are sent to System UI when in rotation locked mode.
+ * Done to enable screen rotation while the the screen rotation is locked. Enabling will
+ * poll the accelerometer in rotation locked mode.
+ *
+ * If 0, then rotation suggestions are not sent to System UI. If 1, suggestions are sent.
+ *
+ * @hide
+ */
+
+ public static final String SHOW_ROTATION_SUGGESTIONS = "show_rotation_suggestions";
+
+ /**
+ * The disabled state of SHOW_ROTATION_SUGGESTIONS.
+ * @hide
+ */
+ public static final int SHOW_ROTATION_SUGGESTIONS_DISABLED = 0x0;
+
+ /**
+ * The enabled state of SHOW_ROTATION_SUGGESTIONS.
+ * @hide
+ */
+ public static final int SHOW_ROTATION_SUGGESTIONS_ENABLED = 0x1;
+
+ /**
+ * The default state of SHOW_ROTATION_SUGGESTIONS.
+ * @hide
+ */
+ public static final int SHOW_ROTATION_SUGGESTIONS_DEFAULT =
+ SHOW_ROTATION_SUGGESTIONS_DISABLED;
+
+ /**
* Read only list of the service components that the current user has explicitly allowed to
* see and assist with all of the user's notifications.
*
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7cfedc8a1f52..00eb778c5a4c 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -512,6 +512,7 @@ public class SettingsBackupTest {
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
Settings.Secure.SETTINGS_CLASSNAME,
Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, // candidate?
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
Settings.Secure.SMS_DEFAULT_APPLICATION,
Settings.Secure.TRUST_AGENTS_INITIALIZED,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 076c0e4d2d4a..3283c289e789 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -698,6 +698,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Behavior of Back button while in-call and screen on
int mIncallBackBehavior;
+ // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
+ int mShowRotationSuggestions;
+
Display mDisplay;
int mLandscapeRotation = 0; // default landscape rotation
@@ -952,6 +955,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
+ UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.POLICY_CONTROL), false, this,
UserHandle.USER_ALL);
@@ -985,23 +991,41 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
class MyOrientationListener extends WindowOrientationListener {
- private final Runnable mUpdateRotationRunnable = new Runnable() {
+
+ private SparseArray<Runnable> mRunnableCache;
+
+ MyOrientationListener(Context context, Handler handler) {
+ super(context, handler);
+ mRunnableCache = new SparseArray<>(5);
+ }
+
+ private class UpdateRunnable implements Runnable {
+ private final int mRotation;
+ UpdateRunnable(int rotation) {
+ mRotation = rotation;
+ }
+
@Override
public void run() {
// send interaction hint to improve redraw performance
mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
- updateRotation(false);
+ if (showRotationChoice(mCurrentAppOrientation, mRotation)) {
+ sendProposedRotationChangeToStatusBarInternal(mRotation);
+ } else {
+ updateRotation(false);
+ }
}
- };
-
- MyOrientationListener(Context context, Handler handler) {
- super(context, handler);
}
@Override
public void onProposedRotationChanged(int rotation) {
if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
- mHandler.post(mUpdateRotationRunnable);
+ Runnable r = mRunnableCache.get(rotation, null);
+ if (r == null){
+ r = new UpdateRunnable(rotation);
+ mRunnableCache.put(rotation, r);
+ }
+ mHandler.post(r);
}
}
MyOrientationListener mOrientationListener;
@@ -1106,7 +1130,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// orientation for a little bit, which can cause orientation
// changes to lag, so we'd like to keep it always on. (It will
// still be turned off when the screen is off.)
- return false;
+
+ // When locked we can provide rotation suggestions users can approve to change the
+ // current screen rotation. To do this the sensor needs to be running.
+ return mSupportAutoRotation &&
+ mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
}
return mSupportAutoRotation;
}
@@ -2295,6 +2323,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
UserHandle.USER_CURRENT);
+ // Configure rotation suggestions.
+ int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
+ UserHandle.USER_CURRENT);
+ if (mShowRotationSuggestions != showRotationSuggestions) {
+ mShowRotationSuggestions = showRotationSuggestions;
+ updateOrientationListenerLp(); // Enable, disable the orientation listener
+ }
+
// Configure wake gesture.
boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
Settings.Secure.WAKE_GESTURE_ENABLED, 0,
@@ -6224,6 +6262,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/**
+ * Notify the StatusBar that system rotation suggestion has changed.
+ */
+ private void sendProposedRotationChangeToStatusBarInternal(int rotation) {
+ StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
+ if (statusBar != null) {
+ statusBar.onProposedRotationChanged(rotation);
+ }
+ }
+
+ /**
* Returns true if the key can have global actions attached to it.
* We reserve all power management keys for the system since they require
* very careful handling.
@@ -7165,6 +7213,86 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mOrientationListener.setCurrentRotation(rotation);
}
+ public boolean showRotationChoice(int orientation, final int preferredRotation) {
+ // Rotation choice is only shown when the user is in locked mode.
+ if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
+
+ // We should only show a rotation choice if:
+ // 1. The rotation isn't forced by the lid, dock, demo, hdmi, vr, etc mode
+ // 2. The user choice won't be ignored due to screen orientation settings
+
+ // Determine if the rotation currently forced
+ if (mForceDefaultOrientation) {
+ return false; // Rotation is forced to default orientation
+
+ } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
+ return false; // Rotation is forced mLidOpenRotation
+
+ } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && !mCarDockEnablesAccelerometer) {
+ return false; // Rotation forced to mCarDockRotation
+
+ } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
+ || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+ && !mDeskDockEnablesAccelerometer) {
+ return false; // Rotation forced to mDeskDockRotation
+
+ } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
+ return false; // Rotation forced to mDemoHdmiRotation
+
+ } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+ && mUndockedHdmiRotation >= 0) {
+ return false; // Rotation forced to mUndockedHdmiRotation
+
+ } else if (mDemoRotationLock) {
+ return false; // Rotation forced to mDemoRotation
+
+ } else if (mPersistentVrModeEnabled) {
+ return false; // Rotation forced to mPortraitRotation
+
+ } else if (!mSupportAutoRotation) {
+ return false;
+ }
+
+ // Determine if the orientation will ignore user choice
+ switch (orientation) {
+ case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+ case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+ case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+ case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+ case ActivityInfo.SCREEN_ORIENTATION_LOCKED:
+ return false; // Forced into a particular rotation, no user choice
+
+ case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+ case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+ case ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR:
+ case ActivityInfo.SCREEN_ORIENTATION_SENSOR:
+ return false; // Sensor overrides user choice
+
+ case ActivityInfo.SCREEN_ORIENTATION_NOSENSOR:
+ // TODO Can sensor be used to indirectly determine the orientation?
+ return false;
+
+ case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+ // If the user has locked sensor-based rotation, this behaves the same as landscape
+ return false; // User has locked the rotation, will behave as LANDSCAPE
+ case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+ // If the user has locked sensor-based rotation, this behaves the same as portrait
+ return false; // User has locked the rotation, will behave as PORTRAIT
+ case ActivityInfo.SCREEN_ORIENTATION_USER:
+ // Works with any rotation except upside down
+ return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
+ case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+ // Works with any of the 4 rotations
+ return preferredRotation >= 0;
+
+ default:
+ // TODO: how to handle SCREEN_ORIENTATION_BEHIND, UNSET?
+ // For UNSPECIFIED use preferred orientation matching SCREEN_ORIENTATION_USER
+ return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
+ }
+ }
+
private boolean isLandscapeOrSeascape(int rotation) {
return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
}