diff options
-rw-r--r-- | api/current.xml | 55 | ||||
-rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 40 | ||||
-rwxr-xr-x | core/java/android/view/WindowOrientationListener.java | 59 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 22 | ||||
-rwxr-xr-x | policy/src/com/android/internal/policy/impl/PhoneWindowManager.java | 82 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 7 |
6 files changed, 224 insertions, 41 deletions
diff --git a/api/current.xml b/api/current.xml index bffdccc..e465df5 100644 --- a/api/current.xml +++ b/api/current.xml @@ -46755,6 +46755,17 @@ visibility="public" > </field> +<field name="SCREEN_ORIENTATION_FULL_SENSOR" + type="int" + transient="false" + volatile="false" + value="10" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SCREEN_ORIENTATION_LANDSCAPE" type="int" transient="false" @@ -46788,6 +46799,28 @@ visibility="public" > </field> +<field name="SCREEN_ORIENTATION_REVERSE_LANDSCAPE" + type="int" + transient="false" + volatile="false" + value="8" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="SCREEN_ORIENTATION_REVERSE_PORTRAIT" + type="int" + transient="false" + volatile="false" + value="9" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SCREEN_ORIENTATION_SENSOR" type="int" transient="false" @@ -46799,6 +46832,28 @@ visibility="public" > </field> +<field name="SCREEN_ORIENTATION_SENSOR_LANDSCAPE" + type="int" + transient="false" + volatile="false" + value="6" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="SCREEN_ORIENTATION_SENSOR_PORTRAIT" + type="int" + transient="false" + volatile="false" + value="7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SCREEN_ORIENTATION_UNSPECIFIED" type="int" transient="false" diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 395c392..e26f160 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -194,10 +194,41 @@ public class ActivityInfo extends ComponentInfo public static final int SCREEN_ORIENTATION_SENSOR = 4; /** - * Constant corresponding to <code>sensor</code> in + * Constant corresponding to <code>nosensor</code> in * the {@link android.R.attr#screenOrientation} attribute. */ public static final int SCREEN_ORIENTATION_NOSENSOR = 5; + + /** + * Constant corresponding to <code>sensorLandscape</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6; + + /** + * Constant corresponding to <code>sensorPortrait</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7; + + /** + * Constant corresponding to <code>reverseLandscape</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8; + + /** + * Constant corresponding to <code>reversePortrait</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9; + + /** + * Constant corresponding to <code>fullSensor</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10; + /** * The preferred screen orientation this activity would like to run in. * From the {@link android.R.attr#screenOrientation} attribute, one of @@ -207,7 +238,12 @@ public class ActivityInfo extends ComponentInfo * {@link #SCREEN_ORIENTATION_USER}, * {@link #SCREEN_ORIENTATION_BEHIND}, * {@link #SCREEN_ORIENTATION_SENSOR}, - * {@link #SCREEN_ORIENTATION_NOSENSOR}. + * {@link #SCREEN_ORIENTATION_NOSENSOR}, + * {@link #SCREEN_ORIENTATION_SENSOR_LANDSCAPE}, + * {@link #SCREEN_ORIENTATION_SENSOR_PORTRAIT}, + * {@link #SCREEN_ORIENTATION_REVERSE_LANDSCAPE}, + * {@link #SCREEN_ORIENTATION_REVERSE_PORTRAIT}, + * {@link #SCREEN_ORIENTATION_FULL_SENSOR}. */ public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java index 8ffa158..3e2e92b 100755 --- a/core/java/android/view/WindowOrientationListener.java +++ b/core/java/android/view/WindowOrientationListener.java @@ -28,6 +28,11 @@ import android.util.Log; * A special helper class used by the WindowManager * for receiving notifications from the SensorManager when * the orientation of the device has changed. + * + * NOTE: If changing anything here, please run the API demo + * "App/Activity/Screen Orientation" to ensure that all orientation + * modes still work correctly. + * * @hide */ public abstract class WindowOrientationListener { @@ -103,6 +108,10 @@ public abstract class WindowOrientationListener { } } + public void setAllow180Rotation(boolean allowed) { + mSensorEventListener.setAllow180Rotation(allowed); + } + public int getCurrentRotation(int lastRotation) { if (mEnabled) { return mSensorEventListener.getCurrentRotation(lastRotation); @@ -151,19 +160,20 @@ public abstract class WindowOrientationListener { private static final int ROTATION_0 = 0; private static final int ROTATION_90 = 1; private static final int ROTATION_270 = 2; + private static final int ROTATION_180 = 3; // Mapping our internal aliases into actual Surface rotation values private static final int[] INTERNAL_TO_SURFACE_ROTATION = new int[] { - Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270}; + Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270, + Surface.ROTATION_180}; // Mapping Surface rotation values to internal aliases. - // We have no constant for Surface.ROTATION_180. That should never happen, but if it - // does, we'll arbitrarily choose a mapping. private static final int[] SURFACE_TO_INTERNAL_ROTATION = new int[] { - ROTATION_0, ROTATION_90, ROTATION_90, ROTATION_270}; + ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}; // Threshold ranges of orientation angle to transition into other orientation states. - // The first list is for transitions from ROTATION_0, the next for ROTATION_90, etc. + // The first list is for transitions from ROTATION_0, ROTATION_90, ROTATION_270, + // and then ROTATION_180. // ROTATE_TO defines the orientation each threshold range transitions to, and must be kept // in sync with this. // We generally transition about the halfway point between two states with a swing of 30 @@ -172,13 +182,32 @@ public abstract class WindowOrientationListener { {{60, 180}, {180, 300}}, {{0, 30}, {195, 315}, {315, 360}}, {{0, 45}, {45, 165}, {330, 360}}, - }; + // Handle situation where we are currently doing 180 rotation + // but that is no longer allowed. + {{0, 45}, {45, 135}, {135, 225}, {225, 315}, {315, 360}}, + }; // See THRESHOLDS private static final int[][] ROTATE_TO = new int[][] { {ROTATION_90, ROTATION_270}, {ROTATION_0, ROTATION_270, ROTATION_0}, {ROTATION_0, ROTATION_90, ROTATION_0}, + {ROTATION_0, ROTATION_90, ROTATION_0, ROTATION_270, ROTATION_0}, + }; + + // Thresholds that allow all 4 orientations. + private static final int[][][] THRESHOLDS_WITH_180 = new int[][][] { + {{60, 165}, {165, 195}, {195, 300}}, + {{0, 30}, {165, 195}, {195, 315}, {315, 360}}, + {{0, 45}, {45, 165}, {165, 195}, {330, 360}}, + {{0, 45}, {45, 135}, {225, 315}, {315, 360}}, + }; + // See THRESHOLDS_WITH_180 + private static final int[][] ROTATE_TO_WITH_180 = new int[][] { + {ROTATION_90, ROTATION_180, ROTATION_270}, + {ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0}, + {ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0}, + {ROTATION_0, ROTATION_90, ROTATION_270, ROTATION_0}, }; // Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e. @@ -188,7 +217,7 @@ public abstract class WindowOrientationListener { // Additional limits on tilt angle to transition to each new orientation. We ignore all // data with tilt beyond MAX_TILT, but we can set stricter limits on transitions to a // particular orientation here. - private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65}; + private static final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, 65, 65, 40}; // Between this tilt angle and MAX_TILT, we'll allow orientation changes, but we'll filter // with a higher time constant, making us less sensitive to change. This primarily helps @@ -228,6 +257,8 @@ public abstract class WindowOrientationListener { private static final float ACCELERATING_LOWPASS_ALPHA = computeLowpassAlpha(ACCELERATING_TIME_CONSTANT_MS); + private boolean mAllow180Rotation = false; + private WindowOrientationListener mOrientationListener; private int mRotation = ROTATION_0; // Current orientation state private float mTiltAngle = 0; // low-pass filtered @@ -249,6 +280,10 @@ public abstract class WindowOrientationListener { return (float) SAMPLING_PERIOD_MS / (timeConstantMs + SAMPLING_PERIOD_MS); } + void setAllow180Rotation(boolean allowed) { + mAllow180Rotation = allowed; + } + int getCurrentRotation(int lastRotation) { if (mTiltDistrust > 0) { // we really don't know the current orientation, so trust what's currently displayed @@ -259,7 +294,9 @@ public abstract class WindowOrientationListener { private void calculateNewRotation(float orientation, float tiltAngle) { if (localLOGV) Log.i(TAG, orientation + ", " + tiltAngle + ", " + mRotation); - int thresholdRanges[][] = THRESHOLDS[mRotation]; + final boolean allow180Rotation = mAllow180Rotation; + int thresholdRanges[][] = allow180Rotation + ? THRESHOLDS_WITH_180[mRotation] : THRESHOLDS[mRotation]; int row = -1; for (int i = 0; i < thresholdRanges.length; i++) { if (orientation >= thresholdRanges[i][0] && orientation < thresholdRanges[i][1]) { @@ -269,13 +306,15 @@ public abstract class WindowOrientationListener { } if (row == -1) return; // no matching transition - int rotation = ROTATE_TO[mRotation][row]; + int rotation = allow180Rotation + ? ROTATE_TO_WITH_180[mRotation][row] : ROTATE_TO[mRotation][row]; if (tiltAngle > MAX_TRANSITION_TILT[rotation]) { // tilted too far flat to go to this rotation return; } - if (localLOGV) Log.i(TAG, " new rotation = " + rotation); + if (localLOGV) Log.i(TAG, "orientation " + orientation + " gives new rotation = " + + rotation); mRotation = rotation; mOrientationListener.onOrientationChanged(INTERNAL_TO_SURFACE_ROTATION[mRotation]); } diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index a8c00a6..298463a 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -495,10 +495,10 @@ orientation will changed based on how the user rotates the device --> <enum name="unspecified" value="-1" /> <!-- Would like to have the screen in a landscape orientation: that - is, with the display wider than it is tall. --> + is, with the display wider than it is tall, ignoring sensor data. --> <enum name="landscape" value="0" /> <!-- Would like to have the screen in a portrait orientation: that - is, with the display taller than it is wide. --> + is, with the display taller than it is wide, ignoring sensor data. --> <enum name="portrait" value="1" /> <!-- Use the user's current preferred orientation of the handset. --> <enum name="user" value="2" /> @@ -511,6 +511,24 @@ <!-- Always ignore orientation determined by orientation sensor: the display will not rotate when the user moves the device. --> <enum name="nosensor" value="5" /> + <!-- Would like to have the screen in landscape orientation, but can + use the sensor to change which direction the screen is facing. --> + <enum name="sensorLandscape" value="6" /> + <!-- Would like to have the screen in portrait orientation, but can + use the sensor to change which direction the screen is facing. --> + <enum name="sensorPortait" value="7" /> + <!-- Would like to have the screen in landscape orientation, turned in + the opposite direction from normal landscape. --> + <enum name="reverseLandscape" value="8" /> + <!-- Would like to have the screen in portrait orientation, turned in + the opposite direction from normal portrait. --> + <enum name="reversePortait" value="9" /> + <!-- Orientation is determined by a physical orientation sensor: + the display will rotate based on how the user moves the device. + This allows any of the 4 possible rotations, regardless of what + the device will normally do (for example some devices won't + normally use 180 degree rotation). --> + <enum name="fullSensor" value="10" /> </attr> <!-- Specify one or more configuration changes that the activity will diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 538dae9..f21d357 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -288,7 +288,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLandscapeRotation = -1; // default landscape rotation int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation - int mPortraitRotation = -1; + int mPortraitRotation = -1; // default portrait rotation + int mUpsideDownRotation = -1; // "other" portrait rotation // Nothing to see here, move along... int mFancyRotationAnimation; @@ -353,26 +354,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean useSensorForOrientationLp(int appOrientation) { // The app says use the sensor. - if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) { + if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { return true; } // The user preference says we can rotate, and the app is willing to rotate. - // Note we include SCREEN_ORIENTATION_LANDSCAPE since we can use the sensor to choose - // between the two possible landscape rotations. if (mAccelerometerDefault != 0 && (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) { + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) { return true; } - // We're in a dock that has a rotation affinity, an the app is willing to rotate. + // We're in a dock that has a rotation affinity, and the app is willing to rotate. if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) { // Note we override the nosensor flag here. if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { + || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { return true; } } @@ -386,7 +386,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { * screen is switched off. */ boolean needSensorRunningLp() { - if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) { + if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR + || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR + || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT + || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) { // If the application has explicitly requested to follow the // orientation, then we need to turn the sensor or. return true; @@ -2060,21 +2063,42 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (d.getWidth() > d.getHeight()) { mPortraitRotation = Surface.ROTATION_90; mLandscapeRotation = Surface.ROTATION_0; + mUpsideDownRotation = Surface.ROTATION_270; mSeascapeRotation = Surface.ROTATION_180; } else { mPortraitRotation = Surface.ROTATION_0; mLandscapeRotation = Surface.ROTATION_90; + mUpsideDownRotation = Surface.ROTATION_180; mSeascapeRotation = Surface.ROTATION_270; } } synchronized (mLock) { - if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { - //always return portrait if orientation set to portrait - return mPortraitRotation; - } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { - return getCurrentLandscapeRotation(lastRotation); + switch (orientation) { + case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: + //always return portrait if orientation set to portrait + return mPortraitRotation; + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: + //always return landscape if orientation set to landscape + return mLandscapeRotation; + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: + //always return portrait if orientation set to portrait + return mUpsideDownRotation; + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: + //always return seascape if orientation set to reverse landscape + return mSeascapeRotation; + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: + //return either landscape rotation based on the sensor + mOrientationListener.setAllow180Rotation(false); + return getCurrentLandscapeRotation(lastRotation); + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + mOrientationListener.setAllow180Rotation(true); + return getCurrentPortraitRotation(lastRotation); } + + mOrientationListener.setAllow180Rotation( + orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); + // case for nosensor meaning ignore sensor and consider only lid // or orientation sensor disabled //or case.unspecified @@ -2094,18 +2118,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private int getCurrentLandscapeRotation(int lastRotation) { - // landscape-only apps can take either landscape rotation - if (useSensorForOrientationLp(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) { - int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation); - if (isLandscapeOrSeascape(sensorRotation)) { - return sensorRotation; - } + int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation); + if (isLandscapeOrSeascape(sensorRotation)) { + return sensorRotation; } // try to preserve the old rotation if it was landscape if (isLandscapeOrSeascape(lastRotation)) { return lastRotation; } - // default to one of the two landscape rotations + // default to one of the primary landscape rotation return mLandscapeRotation; } @@ -2113,6 +2134,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation; } + private int getCurrentPortraitRotation(int lastRotation) { + int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation); + if (isAnyPortrait(sensorRotation)) { + return sensorRotation; + } + // try to preserve the old rotation if it was portrait + if (isAnyPortrait(lastRotation)) { + return lastRotation; + } + // default to one of the primary portrait rotations + return mPortraitRotation; + } + + private boolean isAnyPortrait(int sensorRotation) { + return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation; + } + public boolean detectSafeMode() { try { int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 713524a..0de57ab 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -3066,11 +3066,8 @@ public class WindowManagerService extends IWindowManager.Stub } // If this application has requested an explicit orientation, // then use it. - if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || - or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || - or == ActivityInfo.SCREEN_ORIENTATION_SENSOR || - or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR || - or == ActivityInfo.SCREEN_ORIENTATION_USER) { + if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { return or; } findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND); |