diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-09-21 21:09:10 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-09-21 21:09:10 -0700 |
commit | a829e16681903e6a41901145195f88bf9d952f88 (patch) | |
tree | 90f699d2b69269fa00fff654f92ddb3f0a7d64f7 | |
parent | df8e00ff335be747ec3b99038734d2c6bec6499f (diff) | |
parent | 01a98ddbdfbaf1f0d2bc602537e6e314364902a3 (diff) | |
download | frameworks_base-a829e16681903e6a41901145195f88bf9d952f88.zip frameworks_base-a829e16681903e6a41901145195f88bf9d952f88.tar.gz frameworks_base-a829e16681903e6a41901145195f88bf9d952f88.tar.bz2 |
Merge "Handle orientation changes more systematically. Bug: 4981385"
12 files changed, 341 insertions, 387 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 335c66b..55c821d 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -163,15 +163,13 @@ interface IWindowManager // These can only be called with the SET_ORIENTATION permission. /** - * Change the current screen rotation, constants as per - * {@link android.view.Surface}. - * @param rotation the intended rotation. + * Update the current screen rotation based on the current state of + * the world. * @param alwaysSendConfiguration Flag to force a new configuration to * be evaluated. This can be used when there are other parameters in * configuration that are changing. - * @param animFlags Animation flags as per {@link android.view.Surface}. */ - void setRotation(int rotation, boolean alwaysSendConfiguration, int animFlags); + void updateRotation(boolean alwaysSendConfiguration); /** * Retrieve the current screen orientation, constants as per diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 3880bc4..64d3d31 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -207,9 +207,6 @@ public class Surface implements Parcelable { /** Enable dithering when compositing this surface @hide */ public static final int SURFACE_DITHER = 0x04; - - /** Disable the orientation animation @hide */ - public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; // The mSurfaceControl will only be present for Surfaces used by the window // server or system processes. When this class is parceled we defer to the @@ -393,7 +390,7 @@ public class Surface implements Parcelable { * set the orientation of the given display. * @param display * @param orientation - * @param flags + * @param flags Currently unused, set to 0. * @hide */ public static native void setOrientation(int display, int orientation, int flags); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index c07faf6..1dbb083 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -375,12 +375,6 @@ public interface WindowManagerPolicy { /** Screen turned off because of proximity sensor */ public final int OFF_BECAUSE_OF_PROX_SENSOR = 4; - /** - * Magic constant to {@link IWindowManager#setRotation} to not actually - * modify the rotation. - */ - public final int USE_LAST_ROTATION = -1000; - /** When not otherwise specified by the activity's screenOrientation, rotation should be * determined by the system (that is, using sensors). */ public final int USER_ROTATION_FREE = 0; @@ -856,22 +850,30 @@ public interface WindowManagerPolicy { public boolean inKeyguardRestrictedKeyInputMode(); /** - * Given an orientation constant - * ({@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE - * ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE} or - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_PORTRAIT - * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}), return a surface - * rotation. + * Given an orientation constant, returns the appropriate surface rotation, + * taking into account sensors, docking mode, rotation lock, and other factors. + * + * @param orientation An orientation constant, such as + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. + * @param lastRotation The most recently used rotation. + * @return The surface rotation to use. */ - public int rotationForOrientationLw(int orientation, int lastRotation, - boolean displayEnabled); - + public int rotationForOrientationLw(int orientation, int lastRotation); + /** - * Return the currently locked screen rotation, if any. Return - * Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, or - * Surface.ROTATION_270 if locked; return -1 if not locked. + * Given an orientation constant and a rotation, returns true if the rotation + * has compatible metrics to the requested orientation. For example, if + * the application requested landscape and got seascape, then the rotation + * has compatible metrics; if the application requested portrait and got landscape, + * then the rotation has incompatible metrics; if the application did not specify + * a preference, then anything goes. + * + * @param orientation An orientation constant, such as + * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. + * @param rotation The rotation to check. + * @return True if the rotation is compatible with the requested orientation. */ - public int getLockedRotationLw(); + public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation); /** * Called when the system is mostly done booting to determine whether diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java index 76b47ca..726bf4a 100755 --- a/core/java/android/view/WindowOrientationListener.java +++ b/core/java/android/view/WindowOrientationListener.java @@ -118,14 +118,13 @@ public abstract class WindowOrientationListener { /** * Gets the current orientation. - * @param lastRotation - * @return + * @return The current rotation, or -1 if unknown. */ - public int getCurrentRotation(int lastRotation) { + public int getCurrentRotation() { if (mEnabled) { - return mSensorEventListener.getCurrentRotation(lastRotation); + return mSensorEventListener.getCurrentRotation(); } - return lastRotation; + return -1; } /** @@ -342,8 +341,8 @@ public abstract class WindowOrientationListener { mOrientationListener = orientationListener; } - public int getCurrentRotation(int lastRotation) { - return mRotation != ROTATION_UNKNOWN ? mRotation : lastRotation; + public int getCurrentRotation() { + return mRotation; // may be -1, if unknown } @Override diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 6b31ca4..e0f4cf9 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -88,11 +88,6 @@ public: eElectronBeamAnimationOff = 0x10 }; - // flags for setOrientation - enum { - eOrientationAnimationDisable = 0x00000001 - }; - /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission */ @@ -112,7 +107,8 @@ public: virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0; virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0; - /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission */ + /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission + * No flags are currently defined. Set flags to 0. */ virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0; /* signal that we're done booting. diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index c8c0041..a2d983f 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -385,9 +385,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mPortraitRotation = 0; // default portrait rotation int mUpsideDownRotation = 0; // "other" portrait rotation - // Nothing to see here, move along... - int mFancyRotationAnimation; - // What we do when the user long presses on home private int mLongPressOnHomeBehavior = -1; @@ -439,12 +436,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void onChange(boolean selfChange) { updateSettings(); - try { - mWindowManager.setRotation(USE_LAST_ROTATION, false, - mFancyRotationAnimation); - } catch (RemoteException e) { - // Ignore - } + updateRotation(false); } } @@ -457,45 +449,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onOrientationChanged(int rotation) { // Send updates based on orientation value if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation); - try { - mWindowManager.setRotation(rotation, false, - mFancyRotationAnimation); - } catch (RemoteException e) { - // Ignore - - } - } + updateRotation(false); + } } MyOrientationListener mOrientationListener; - boolean useSensorForOrientationLp(int appOrientation) { - // The app says use the 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. - if (mAccelerometerDefault != 0 && - (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER - || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) { - return true; - } - // 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) { - return true; - } - } - // Else, don't use the sensor. - return false; - } - /* * We always let the sensor be switched on by default except when * the user has explicitly disabled sensor based rotation or when the @@ -826,8 +784,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mIncallPowerBehavior = Settings.Secure.getInt(resolver, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); - mFancyRotationAnimation = Settings.System.getInt(resolver, - "fancy_rotation_anim", 0) != 0 ? 0x80 : 0; int accelerometerDefault = Settings.System.getInt(resolver, Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION); @@ -882,7 +838,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateScreenSaverTimeoutLocked(); } if (updateRotation) { - updateRotation(0); + updateRotation(true); } if (addView != null) { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( @@ -1025,8 +981,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void adjustConfigurationLw(Configuration config) { readLidState(); - - mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN); + updateKeyboardVisibility(); if (config.keyboard == Configuration.KEYBOARD_NOKEYS) { config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; @@ -2295,8 +2250,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { // lid changed state mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED; + updateKeyboardVisibility(); + boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen); - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); if (awakeNow) { // If the lid is opening and we don't have to keep the // keyguard up, then we can turn on the screen @@ -2325,7 +2282,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { void setHdmiPlugged(boolean plugged) { if (mHdmiPlugged != plugged) { mHdmiPlugged = plugged; - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); Intent intent = new Intent(ACTION_HDMI_PLUGGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); @@ -2802,7 +2759,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (RemoteException e) { } } - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotation(true); updateOrientationListenerLp(); } }; @@ -2914,10 +2871,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } - - public int rotationForOrientationLw(int orientation, int lastRotation, - boolean displayEnabled) { + @Override + public int rotationForOrientationLw(int orientation, int lastRotation) { if (false) { Slog.v(TAG, "rotationForOrientationLw(orient=" + orientation + ", last=" + lastRotation @@ -2928,128 +2884,129 @@ public class PhoneWindowManager implements WindowManagerPolicy { } synchronized (mLock) { + int sensorRotation = mOrientationListener.getCurrentRotation(); // may be -1 + + int preferredRotation = -1; + if (mHdmiPlugged) { + // Ignore sensor when plugged into HDMI. + preferredRotation = mLandscapeRotation; + } else if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) { + // Ignore sensor when lid switch is open and rotation is forced. + preferredRotation = mLidOpenRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR + && ((mCarDockEnablesAccelerometer && sensorRotation >= 0) + || mCarDockRotation >= 0)) { + // Ignore sensor when in car dock unless explicitly enabled. + // This case can override the behavior of NOSENSOR, and can also + // enable 180 degree rotation while docked. + preferredRotation = mCarDockEnablesAccelerometer && sensorRotation >= 0 + ? sensorRotation : mCarDockRotation; + } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK + && ((mDeskDockEnablesAccelerometer && sensorRotation >= 0) + || mDeskDockRotation >= 0)) { + // Ignore sensor when in desk dock unless explicitly enabled. + // This case can override the behavior of NOSENSOR, and can also + // enable 180 degree rotation while docked. + preferredRotation = mDeskDockEnablesAccelerometer && sensorRotation >= 0 + ? sensorRotation : mDeskDockRotation; + } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { + // Ignore sensor when user locked rotation. + preferredRotation = mUserRotation; + } else if ((mAccelerometerDefault != 0 + && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER + || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR + || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE + || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { + // Otherwise, use sensor only if requested by the application or enabled + // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. + if (sensorRotation != Surface.ROTATION_180 + || mAllowAllRotations + || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { + preferredRotation = sensorRotation; + } else { + preferredRotation = lastRotation; + } + } + + // TODO: Sometimes, we might want to override the application-requested + // orientation, such as when HDMI is plugged in or when docked. + // We can do that by modifying the appropriate cases above to return + // the preferred orientation directly instead of continuing on down here. + switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: - //always return portrait if orientation set to portrait + // Always return portrait if orientation set to portrait. return mPortraitRotation; + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: - //always return landscape if orientation set to 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 + // 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 + // 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 - return getCurrentLandscapeRotation(lastRotation); - case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: - return getCurrentPortraitRotation(lastRotation); - } + // Return either landscape rotation. + if (isLandscapeOrSeascape(preferredRotation)) { + return preferredRotation; + } + if (isLandscapeOrSeascape(lastRotation)) { + return lastRotation; + } + return mLandscapeRotation; - // case for nosensor meaning ignore sensor and consider only lid - // or orientation sensor disabled - //or case.unspecified - if (mHdmiPlugged) { - return mLandscapeRotation; - } else if (mLidOpen == LID_OPEN) { - return mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - return mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - return mDeskDockRotation; - } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - return mUserRotation; - } else { - if (useSensorForOrientationLp(orientation)) { - // Disable 180 degree rotation unless allowed by default for the device - // or explicitly requested by the application. - int rotation = mOrientationListener.getCurrentRotation(lastRotation); - if (rotation == Surface.ROTATION_180 - && !mAllowAllRotations - && orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + // Return either portrait rotation. + if (isAnyPortrait(preferredRotation)) { + return preferredRotation; + } + if (isAnyPortrait(lastRotation)) { return lastRotation; } - return rotation; - } - return Surface.ROTATION_0; - } - } - } + return mPortraitRotation; - public int getLockedRotationLw() { - synchronized (mLock) { - if (false) { - // Not yet working. - if (mHdmiPlugged) { + default: + // For USER, UNSPECIFIED and NOSENSOR, just return the preferred + // orientation we already calculated. + if (preferredRotation >= 0) { + return preferredRotation; + } return Surface.ROTATION_0; - } else if (mLidOpen == LID_OPEN) { - return mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - return mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - return mDeskDockRotation; - } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - return mUserRotation; - } } - return -1; } } - private int getCurrentLandscapeRotation(int lastRotation) { - // if the user has locked rotation, we ignore the sensor - if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - if (isLandscapeOrSeascape(mUserRotation)) { - return mUserRotation; - } else { - // it seems odd to obey the sensor at all if rotation lock is enabled - return mLandscapeRotation; - } - } + @Override + public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { + switch (orientation) { + case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: + return isAnyPortrait(rotation); + + case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: + case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: + return isLandscapeOrSeascape(rotation); - 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: + return true; } - // default to one of the primary landscape rotation - return mLandscapeRotation; - } - - private boolean isLandscapeOrSeascape(int sensorRotation) { - return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation; } - private int getCurrentPortraitRotation(int lastRotation) { - // if the user has locked rotation, we ignore the sensor - if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) { - if (isAnyPortrait(mUserRotation)) { - return mUserRotation; - } else { - // it seems odd to obey the sensor at all if rotation lock is enabled - return mPortraitRotation; - } - } - - 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 isLandscapeOrSeascape(int rotation) { + return rotation == mLandscapeRotation || rotation == mSeascapeRotation; } - private boolean isAnyPortrait(int sensorRotation) { - return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation; + private boolean isAnyPortrait(int rotation) { + return rotation == mPortraitRotation || rotation == mUpsideDownRotation; } @@ -3298,26 +3255,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ public void enableScreenAfterBoot() { readLidState(); - updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateKeyboardVisibility(); + + updateRotation(true); } - void updateRotation(int animFlags) { + private void updateKeyboardVisibility() { mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN); - int rotation = Surface.ROTATION_0; - if (mHdmiPlugged) { - rotation = Surface.ROTATION_0; - } else if (mLidOpen == LID_OPEN) { - rotation = mLidOpenRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) { - rotation = mCarDockRotation; - } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) { - rotation = mDeskDockRotation; - } - //if lid is closed orientation will be portrait + } + + void updateRotation(boolean alwaysSendConfiguration) { try { //set orientation on WindowManager - mWindowManager.setRotation(rotation, true, - mFancyRotationAnimation | animFlags); + mWindowManager.updateRotation(alwaysSendConfiguration); } catch (RemoteException e) { // Ignore } diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index dd440bf..f2e7485 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -125,6 +125,12 @@ class DragState { mDragWindowHandle.frameTop = 0; mDragWindowHandle.frameRight = mService.mCurDisplayWidth; mDragWindowHandle.frameBottom = mService.mCurDisplayHeight; + + // Pause rotations before a drag. + if (WindowManagerService.DEBUG_ORIENTATION) { + Slog.d(WindowManagerService.TAG, "Pausing rotation during drag"); + } + mService.pauseRotationLocked(); } } @@ -142,6 +148,12 @@ class DragState { mDragWindowHandle = null; mDragApplicationHandle = null; + + // Resume rotations after a drag. + if (WindowManagerService.DEBUG_ORIENTATION) { + Slog.d(WindowManagerService.TAG, "Resuming rotation after drag"); + } + mService.resumeRotationLocked(); } } @@ -257,13 +269,6 @@ class DragState { // free our resources and drop all the object references mService.mDragState.reset(); mService.mDragState = null; - - if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation"); - boolean changed = mService.setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - if (changed) { - mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } } void notifyMoveLw(float x, float y) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index ff75cfd..02b246a 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -427,14 +427,11 @@ public class WindowManagerService extends IWindowManager.Stub int mAppDisplayWidth = 0; int mAppDisplayHeight = 0; int mRotation = 0; - int mRequestedRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mAltOrientation = false; - int mLastRotationFlags; ArrayList<IRotationWatcher> mRotationWatchers = new ArrayList<IRotationWatcher>(); - int mDeferredRotation; - int mDeferredRotationAnimFlags; + int mDeferredRotationPauseCount; boolean mLayoutNeeded = true; boolean mAnimationPending = false; @@ -3414,9 +3411,7 @@ public class WindowManagerService extends IWindowManager.Stub //send a message to Policy indicating orientation change to take //action like disabling/enabling sensors etc., mPolicy.setCurrentOrientationLw(req); - if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE, - inTransaction)) { + if (updateRotationUncheckedLocked(inTransaction)) { changed = true; } } @@ -4823,8 +4818,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, - mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); + updateRotationUnchecked(false); } public void showBootMessage(final CharSequence msg, final boolean always) { @@ -5043,6 +5037,10 @@ public class WindowManagerService extends IWindowManager.Stub return bm; } + /** + * Freeze rotation changes. (Enable "rotation lock".) + * Persists across reboots. + */ public void freezeRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "freezeRotation()")) { @@ -5052,9 +5050,13 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation); mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation); - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + updateRotationUnchecked(false); } + /** + * Thaw rotation changes. (Disable "rotation lock".) + * Persists across reboots. + */ public void thawRotation() { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, "thawRotation()")) { @@ -5064,30 +5066,56 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation); mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used - setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0); + updateRotationUnchecked(false); } - public void setRotation(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "setRotation()")) { - throw new SecurityException("Requires SET_ORIENTATION permission"); - } + /** + * Recalculate the current rotation. + * + * Called by the window manager policy whenever the state of the system changes + * such that the current rotation might need to be updated, such as when the + * device is docked or rotated into a new posture. + */ + public void updateRotation(boolean alwaysSendConfiguration) { + updateRotationUnchecked(alwaysSendConfiguration); + } - setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags); + /** + * Temporarily pauses rotation changes until resumed. + * + * This can be used to prevent rotation changes from occurring while the user is + * performing certain operations, such as drag and drop. + * + * This call nests and must be matched by an equal number of calls to {@link #resumeRotation}. + */ + void pauseRotationLocked() { + mDeferredRotationPauseCount += 1; + } + + /** + * Resumes normal rotation changes after being paused. + */ + void resumeRotationLocked() { + if (mDeferredRotationPauseCount > 0) { + mDeferredRotationPauseCount -= 1; + if (mDeferredRotationPauseCount == 0) { + boolean changed = updateRotationUncheckedLocked(false); + if (changed) { + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + } + } } - public void setRotationUnchecked(int rotation, - boolean alwaysSendConfiguration, int animFlags) { - if(DEBUG_ORIENTATION) Slog.v(TAG, - "setRotationUnchecked(rotation=" + rotation + - " alwaysSendConfiguration=" + alwaysSendConfiguration + - " animFlags=" + animFlags); + public void updateRotationUnchecked( + boolean alwaysSendConfiguration) { + if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked(" + + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")"); long origId = Binder.clearCallingIdentity(); boolean changed; synchronized(mWindowMap) { - changed = setRotationUncheckedLocked(rotation, animFlags, false); + changed = updateRotationUncheckedLocked(false); } if (changed || alwaysSendConfiguration) { @@ -5098,152 +5126,113 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Apply a new rotation to the screen, respecting the requests of - * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply - * re-evaluate the desired rotation. - * - * Returns null if the rotation has been changed. In this case YOU - * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN. + * Updates the current rotation. + * + * Returns true if the rotation has been changed. In this case YOU + * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN. */ - public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) { - if (mDragState != null - || (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating())) { - // Potential rotation during a drag or while waiting for a previous orientation - // change to finish (rotation animation will be dismissed). - // Don't do the rotation now, but make a note to perform the rotation later. - if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation."); - if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) { - mDeferredRotation = rotation; - mDeferredRotationAnimFlags = animFlags; - } + public boolean updateRotationUncheckedLocked(boolean inTransaction) { + if (mDeferredRotationPauseCount > 0) { + // Rotation updates have been paused temporarily. Defer the update until + // updates have been resumed. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused."); return false; } - boolean changed; - if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) { - if (mDeferredRotation != WindowManagerPolicy.USE_LAST_ROTATION) { - rotation = mDeferredRotation; - mRequestedRotation = rotation; - mLastRotationFlags = mDeferredRotationAnimFlags; - } - rotation = mRequestedRotation; - } else { - mRequestedRotation = rotation; - mLastRotationFlags = animFlags; - } - mDeferredRotation = WindowManagerPolicy.USE_LAST_ROTATION; - if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation); - rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, - mRotation, mDisplayEnabled); - if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation); - - int desiredRotation = rotation; - int lockedRotation = mPolicy.getLockedRotationLw(); - if (lockedRotation >= 0 && rotation != lockedRotation) { - // We are locked in a rotation but something is requesting - // a different rotation... we will either keep the locked - // rotation if it results in the same orientation, or have to - // switch into an emulated orientation mode. - - // First, we know that our rotation is actually going to be - // the locked rotation. - rotation = lockedRotation; - - // Now the difference between the desired and lockedRotation - // may mean that the orientation is different... if that is - // not the case, we can just make the desired rotation be the - // same as the new locked rotation. - switch (lockedRotation) { - case Surface.ROTATION_0: - if (rotation == Surface.ROTATION_180) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_90: - if (rotation == Surface.ROTATION_270) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_180: - if (rotation == Surface.ROTATION_0) { - desiredRotation = lockedRotation; - } - break; - case Surface.ROTATION_270: - if (rotation == Surface.ROTATION_90) { - desiredRotation = lockedRotation; - } - break; - } + if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { + // Rotation updates cannot be performed while the previous rotation change + // animation is still in progress. Skip this update. We will try updating + // again after the animation is finished and the display is unfrozen. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress."); + return false; } - changed = mDisplayEnabled && mRotation != rotation; - if (mAltOrientation != (rotation != desiredRotation)) { - changed = true; - mAltOrientation = rotation != desiredRotation; + if (!mDisplayEnabled) { + // No point choosing a rotation if the display is not enabled. + if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled."); + return false; } - if (changed) { - if (DEBUG_ORIENTATION) Slog.v(TAG, - "Rotation changed to " + rotation - + " from " + mRotation - + " (forceApp=" + mForcedAppOrientation - + ", req=" + mRequestedRotation + ")"); - mRotation = rotation; - mWindowsFreezingScreen = true; - mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); - mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), - 2000); - mWaitingForConfig = true; - mLayoutNeeded = true; - startFreezingDisplayLocked(inTransaction); - //Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); - mInputManager.setDisplayOrientation(0, rotation); - if (mDisplayEnabled) { - // NOTE: We disable the rotation in the emulator because - // it doesn't support hardware OpenGL emulation yet. - if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null - && mScreenRotationAnimation.hasScreenshot()) { - Surface.freezeDisplay(0); - if (!inTransaction) { - if (SHOW_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION setRotationUnchecked"); - Surface.openTransaction(); - } - try { - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.setRotation(rotation); - } - } finally { - if (!inTransaction) { - Surface.closeTransaction(); - if (SHOW_TRANSACTIONS) Slog.i(TAG, - "<<< CLOSE TRANSACTION setRotationUnchecked"); - } - } - Surface.setOrientation(0, rotation, animFlags); - Surface.unfreezeDisplay(0); - } else { - Surface.setOrientation(0, rotation, animFlags); - } - rebuildBlackFrame(inTransaction); - } + // TODO: Implement forced rotation changes. + // Set mAltOrientation to indicate that the application is receiving + // an orientation that has different metrics than it expected. + // eg. Portrait instead of Landscape. - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mSurface != null) { - w.mOrientationChanging = true; - } + int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation); + boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw( + mForcedAppOrientation, rotation); + + if (DEBUG_ORIENTATION) { + Slog.v(TAG, "Application requested orientation " + + mForcedAppOrientation + ", got rotation " + rotation + + " which has " + (altOrientation ? "incompatible" : "compatible") + + " metrics"); + } + + if (mRotation == rotation && mAltOrientation == altOrientation) { + // No change. + return false; + } + + if (DEBUG_ORIENTATION) { + Slog.v(TAG, + "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "") + + " from " + mRotation + (mAltOrientation ? " (alt)" : "") + + ", forceApp=" + mForcedAppOrientation); + } + + mRotation = rotation; + mAltOrientation = altOrientation; + + mWindowsFreezingScreen = true; + mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); + mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000); + mWaitingForConfig = true; + mLayoutNeeded = true; + startFreezingDisplayLocked(inTransaction); + mInputManager.setDisplayOrientation(0, rotation); + + // NOTE: We disable the rotation in the emulator because + // it doesn't support hardware OpenGL emulation yet. + if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null + && mScreenRotationAnimation.hasScreenshot()) { + Surface.freezeDisplay(0); + if (!inTransaction) { + if (SHOW_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION setRotationUnchecked"); + Surface.openTransaction(); } - for (int i=mRotationWatchers.size()-1; i>=0; i--) { - try { - mRotationWatchers.get(i).onRotationChanged(rotation); - } catch (RemoteException e) { + try { + if (mScreenRotationAnimation != null) { + mScreenRotationAnimation.setRotation(rotation); + } + } finally { + if (!inTransaction) { + Surface.closeTransaction(); + if (SHOW_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION setRotationUnchecked"); } } - } //end if changed + Surface.setOrientation(0, rotation); + Surface.unfreezeDisplay(0); + } else { + Surface.setOrientation(0, rotation); + } + rebuildBlackFrame(inTransaction); - return changed; + for (int i=mWindows.size()-1; i>=0; i--) { + WindowState w = mWindows.get(i); + if (w.mSurface != null) { + w.mOrientationChanging = true; + } + } + for (int i=mRotationWatchers.size()-1; i>=0; i--) { + try { + mRotationWatchers.get(i).onRotationChanged(rotation); + } catch (RemoteException e) { + } + } + return true; } public int getRotation() { @@ -8601,8 +8590,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - boolean changed = setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); + boolean changed = updateRotationUncheckedLocked(false); if (changed) { mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } else { @@ -9029,8 +9017,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - configChanged |= setRotationUncheckedLocked( - WindowManagerPolicy.USE_LAST_ROTATION, 0, false); + configChanged |= updateRotationUncheckedLocked(false); } if (configChanged) { @@ -9403,12 +9390,10 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); pw.print(" mRotation="); pw.print(mRotation); - pw.print(" mRequestedRotation="); pw.print(mRequestedRotation); pw.print(" mAltOrientation="); pw.println(mAltOrientation); pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation); pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); - pw.print(" mDeferredRotation="); pw.print(mDeferredRotation); - pw.print(", mDeferredRotationAnimFlags="); pw.println(mDeferredRotationAnimFlags); + pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); pw.print(" mAnimationPending="); pw.print(mAnimationPending); pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale); pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0ef03bb..09097ee 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -566,7 +566,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const int dpy = 0; const int orientation = mCurrentState.orientation; - const uint32_t type = mCurrentState.orientationType; + // Currently unused: const uint32_t flags = mCurrentState.orientationFlags; GraphicPlane& plane(graphicPlane(dpy)); plane.setOrientation(orientation); @@ -1299,7 +1299,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy, Mutex::Autolock _l(mStateLock); if (mCurrentState.orientation != orientation) { if (uint32_t(orientation)<=eOrientation270 || orientation==42) { - mCurrentState.orientationType = flags; + mCurrentState.orientationFlags = flags; mCurrentState.orientation = orientation; setTransactionFlags(eTransactionNeeded); mTransactionCV.wait(mStateLock); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d7f005f..43191b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -245,7 +245,7 @@ private: } LayerVector layersSortedByZ; uint8_t orientation; - uint8_t orientationType; + uint8_t orientationFlags; uint8_t freezeDisplay; }; diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index f015378..5df018e 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -412,9 +412,31 @@ public class WindowManagerPermissionTests extends TestCase { @SmallTest public void testSET_ORIENTATION() { try { - mWm.setRotation(0, true, 0); + mWm.updateRotation(true); mWm.getSwitchState(0); - fail("IWindowManager.setRotation did not throw SecurityException as" + fail("IWindowManager.updateRotation did not throw SecurityException as" + + " expected"); + } catch (SecurityException e) { + // expected + } catch (RemoteException e) { + fail("Unexpected remote exception"); + } + + try { + mWm.freezeRotation(); + mWm.getSwitchState(0); + fail("IWindowManager.freezeRotation did not throw SecurityException as" + + " expected"); + } catch (SecurityException e) { + // expected + } catch (RemoteException e) { + fail("Unexpected remote exception"); + } + + try { + mWm.thawRotation(); + mWm.getSwitchState(0); + fail("IWindowManager.thawRotation did not throw SecurityException as" + " expected"); } catch (SecurityException e) { // expected diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java index 3d1fa7a..940b290 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java @@ -396,7 +396,7 @@ public class BridgeWindowManager implements IWindowManager { } - public void setRotation(int arg0, boolean arg1, int arg2) throws RemoteException { + public void updateRotation(boolean arg0) throws RemoteException { // TODO Auto-generated method stub } |