Support rotation on secondary displays (3/N)
Move major operations of rotation/orientation from
PhoneWindowManager to DisplayRotation.
Create DisplayPolicy and move partial fields which
have dependency with rotation.
Bug: 111361251
Test: go/wm-smoke
Test: atest FrameworksServicesTests:AppWindowTokenTests
Test: atest FrameworksServicesTests:PhoneWindowManagerLayoutTest
Test: atest CtsActivityManagerDeviceTestCases:ActivityManagerMultiDisplayTests
Change-Id: I2dfd15ffcc41e10a9074087e6aa15975c92b4979
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 79d9b11..a8b92a6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -288,6 +288,7 @@
import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import com.android.server.wm.AppTransition;
import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.DisplayPolicy;
import com.android.server.wm.DisplayRotation;
import com.android.server.wm.WindowFrames;
import com.android.server.wm.WindowManagerInternal;
@@ -501,8 +502,6 @@
WindowState mStatusBar = null;
private final int[] mStatusBarHeightForRotation = new int[4];
WindowState mNavigationBar = null;
- boolean mHasNavigationBar = false;
- boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
@NavigationBarPosition
int mNavigationBarPosition = NAV_BAR_BOTTOM;
int[] mNavigationBarHeightForRotationDefault = new int[4];
@@ -557,8 +556,6 @@
volatile boolean mRecentsVisible;
volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
volatile boolean mPictureInPictureVisible;
- // Written by vr manager thread, only read in this class.
- volatile private boolean mPersistentVrModeEnabled;
volatile private boolean mDismissImeOnBackKeyPressed;
// Used to hold the last user key used to wake the device. This helps us prevent up events
@@ -568,40 +565,18 @@
int mRecentAppsHeldModifiers;
boolean mLanguageSwitchKeyPressed;
- int mLidState = LID_ABSENT;
int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
boolean mHaveBuiltInKeyboard;
boolean mSystemReady;
boolean mSystemBooted;
- boolean mHdmiPlugged;
HdmiControl mHdmiControl;
IUiModeManager mUiModeManager;
int mUiMode;
- int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
- int mLidOpenRotation;
- int mCarDockRotation;
- int mDeskDockRotation;
- int mUndockedHdmiRotation;
- int mDemoHdmiRotation;
- boolean mDemoHdmiRotationLock;
- int mDemoRotation;
- boolean mDemoRotationLock;
boolean mWakeGestureEnabledSetting;
MyWakeGestureListener mWakeGestureListener;
- // Default display does not rotate, apps that require non-default orientation will have to
- // have the orientation emulated.
- private boolean mForceDefaultOrientation = false;
-
- int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
- int mUserRotation = Surface.ROTATION_0;
-
- boolean mSupportAutoRotation;
- int mAllowAllRotations = -1;
- boolean mCarDockEnablesAccelerometer;
- boolean mDeskDockEnablesAccelerometer;
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
boolean mLidControlsScreenLock;
@@ -614,12 +589,6 @@
int mLongPressOnBackBehavior;
int mShortPressOnSleepBehavior;
int mShortPressOnWindowBehavior;
- volatile boolean mAwake;
- boolean mScreenOnEarly;
- boolean mScreenOnFully;
- ScreenOnListener mScreenOnListener;
- boolean mKeyguardDrawComplete;
- boolean mWindowManagerDrawComplete;
boolean mHasSoftInput = false;
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
@@ -728,16 +697,14 @@
// Behavior of Back button while in-call and screen on
int mIncallBackBehavior;
- // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
- int mShowRotationSuggestions;
-
// Whether system navigation keys are enabled
boolean mSystemNavigationKeysEnabled;
- // TODO(multi-display): Remove default when the dependencies are multi-display ready.
+ // TODO(b/111361251): Remove default when the dependencies are multi-display ready.
Display mDefaultDisplay;
DisplayRotation mDefaultDisplayRotation;
- MyOrientationListener mDefaultOrientationListener;
+ DisplayPolicy mDefaultDisplayPolicy;
+ WindowOrientationListener mDefaultOrientationListener;
// What we do when the user long presses on home
private int mLongPressOnHomeBehavior;
@@ -960,7 +927,7 @@
private UEventObserver mHDMIObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
- setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
+ mDefaultDisplayPolicy.setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
}
};
@@ -985,12 +952,6 @@
Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.ACCELEROMETER_ROTATION), false, this,
- UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.System.getUriFor(
- Settings.System.USER_ROTATION), false, this,
- UserHandle.USER_ALL);
- resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
@@ -1003,9 +964,6 @@
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.Secure.getUriFor(
Settings.Secure.VOLUME_HUSH_GESTURE), false, this,
UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -1040,68 +998,11 @@
}
}
- class MyOrientationListener extends WindowOrientationListener
- implements WindowManagerPolicy.RotationSource {
-
- private SparseArray<Runnable> mRunnableCache;
- private boolean mEnabled;
-
- 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);
- if (isRotationChoicePossible(mDefaultDisplayRotation.getCurrentAppOrientation())) {
- final boolean isValid = mDefaultDisplayRotation
- .isValidRotationChoice(mRotation);
- sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
- } else {
- updateRotation(false);
- }
- }
- }
-
- @Override
- public void onProposedRotationChanged(int rotation) {
- if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
- Runnable r = mRunnableCache.get(rotation, null);
- if (r == null){
- r = new UpdateRunnable(rotation);
- mRunnableCache.put(rotation, r);
- }
- mHandler.post(r);
- }
-
- @Override
- public void enable(boolean clearCurrentRotation) {
- super.enable(clearCurrentRotation);
- mEnabled = true;
- if(localLOGV) Slog.v(TAG, "Enabling listeners");
- }
-
- @Override
- public void disable() {
- super.disable();
- mEnabled = false;
- if(localLOGV) Slog.v(TAG, "Disabling listeners");
- }
- }
-
final IPersistentVrStateCallbacks mPersistentVrModeListener =
new IPersistentVrStateCallbacks.Stub() {
@Override
public void onPersistentVrStateChanged(boolean enabled) {
- mPersistentVrModeEnabled = enabled;
+ mDefaultDisplayPolicy.setPersistentVrModeEnabled(enabled);
}
};
@@ -1183,105 +1084,6 @@
}
}
- /*
- * We always let the sensor be switched on by default except when
- * the user has explicitly disabled sensor based rotation or when the
- * screen is switched off.
- */
- boolean needSensorRunningLp() {
- if (mSupportAutoRotation) {
- final int currentAppOrientation = mDefaultDisplayRotation.getCurrentAppOrientation();
- if (currentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
- || currentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
- || currentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
- || currentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
- // If the application has explicitly requested to follow the
- // orientation, then we need to turn the sensor on.
- return true;
- }
- }
- if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
- (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
- // enable accelerometer if we are docked in a dock that enables accelerometer
- // orientation management,
- return true;
- }
- if (mUserRotationMode == USER_ROTATION_LOCKED) {
- // If the setting for using the sensor by default is enabled, then
- // we will always leave it on. Note that the user could go to
- // a window that forces an orientation that does not use the
- // sensor and in theory we could turn it off... however, when next
- // turning it on we won't have a good value for the current
- // 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.)
-
- // 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;
- }
-
- @Override
- public void updateOrientationListener() {
- synchronized (mLock) {
- updateOrientationListenerLp();
- }
- }
-
- /*
- * Various use cases for invoking this function
- * screen turning off, should always disable listeners if already enabled
- * screen turned on and current app has sensor based orientation, enable listeners
- * if not already enabled
- * screen turned on and current app does not have sensor orientation, disable listeners if
- * already enabled
- * screen turning on and current app has sensor based orientation, enable listeners if needed
- * screen turning on and current app has nosensor based orientation, do nothing
- */
- void updateOrientationListenerLp() {
- if (!mDefaultOrientationListener.canDetectOrientation()) {
- // If sensor is turned off or nonexistent for some reason
- return;
- }
- // Could have been invoked due to screen turning on or off or
- // change of the currently visible window's orientation.
- if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
- + ", mAwake=" + mAwake + ", mCurrentAppOrientation="
- + mDefaultDisplayRotation.getCurrentAppOrientation()
- + ", mOrientationSensorEnabled=" + mDefaultOrientationListener.mEnabled
- + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
- + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
- boolean disable = true;
- // Note: We postpone the rotating of the screen until the keyguard as well as the
- // window manager have reported a draw complete or the keyguard is going away in dismiss
- // mode.
- if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete))) {
- if (needSensorRunningLp()) {
- disable = false;
- //enable listener if not already enabled
- if (!mDefaultOrientationListener.mEnabled) {
- // Don't clear the current sensor orientation if the keyguard is going away in
- // dismiss mode. This allows window manager to use the last sensor reading to
- // determine the orientation vs. falling back to the last known orientation if
- // the sensor reading was cleared which can cause it to relaunch the app that
- // will show in the wrong orientation first before correcting leading to app
- // launch delays.
- mDefaultOrientationListener.enable(true /* clearCurrentRotation */);
- }
- }
- }
- //check if sensors need to be disabled
- if (disable && mDefaultOrientationListener.mEnabled) {
- mDefaultOrientationListener.disable();
- }
- }
-
private void interceptBackKeyDown() {
MetricsLogger.count(mContext, "key_back_down", 1);
// Reset back key state for long press
@@ -1507,7 +1309,7 @@
}
private void powerPress(long eventTime, boolean interactive, int count) {
- if (mScreenOnEarly && !mScreenOnFully) {
+ if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
@@ -2007,6 +1809,14 @@
return mContext.getResources().getConfiguration().isScreenRound();
}
+ @Override
+ public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
+ mDefaultDisplay = displayContentInfo.getDisplay();
+ mDefaultDisplayRotation = displayContentInfo.getDisplayRotation();
+ mDefaultDisplayPolicy = mDefaultDisplayRotation.getDisplayPolicy();
+ mDefaultOrientationListener = mDefaultDisplayRotation.getOrientationListener();
+ }
+
/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
@@ -2063,15 +1873,6 @@
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
- final DisplayContentInfo displayContentInfo =
- windowManagerFuncs.getDefaultDisplayContentInfo();
- mDefaultDisplay = displayContentInfo.getDisplay();
- mDefaultDisplayRotation = displayContentInfo.getDisplayRotation();
- mDefaultOrientationListener = new MyOrientationListener(mContext, mHandler);
- try {
- mDefaultOrientationListener.setCurrentRotation(
- windowManager.getDefaultDisplayRotation());
- } catch (RemoteException ex) { }
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
mShortcutManager = new ShortcutManager(context);
@@ -2102,20 +1903,6 @@
mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mPowerKeyWakeLock");
mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
- mSupportAutoRotation = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_supportAutoRotation);
- mLidOpenRotation = readRotation(
- com.android.internal.R.integer.config_lidOpenRotation);
- mCarDockRotation = readRotation(
- com.android.internal.R.integer.config_carDockRotation);
- mDeskDockRotation = readRotation(
- com.android.internal.R.integer.config_deskDockRotation);
- mUndockedHdmiRotation = readRotation(
- com.android.internal.R.integer.config_undockedHdmiRotation);
- mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_carDockEnablesAccelerometer);
- mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
mLidKeyboardAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidKeyboardAccessibility);
mLidNavigationAccessibility = mContext.getResources().getInteger(
@@ -2189,8 +1976,8 @@
Intent intent = context.registerReceiver(mDockReceiver, filter);
if (intent != null) {
// Retrieve current sticky dock event broadcast.
- mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+ Intent.EXTRA_DOCK_STATE_UNDOCKED));
}
// register for dream-related broadcasts
@@ -2355,93 +2142,12 @@
com.android.internal.R.integer.config_navBarOpacityMode);
}
- @Override
- public void setInitialDisplaySize(DisplayRotation displayRotation, int width, int height,
- int density) {
- // This method might be called before the policy has been fully initialized
- // or for other displays we don't care about.
- // TODO(multi-display): Define policy for secondary displays.
- if (mContext == null || !displayRotation.isDefaultDisplay()) {
- return;
- }
-
- final int shortSize;
- final int longSize;
- if (width > height) {
- shortSize = height;
- longSize = width;
- } else {
- shortSize = width;
- longSize = height;
- }
-
- // SystemUI (status bar) layout policy
- final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
- final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
-
- // Allow the navigation bar to move on non-square small devices (phones).
- mNavigationBarCanMove = width != height && shortSizeDp < 600;
-
- final Resources res = mContext.getResources();
- mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
-
- // Allow a system property to override this. Used by the emulator.
- // See also hasNavigationBar().
- String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
- if ("1".equals(navBarOverride)) {
- mHasNavigationBar = false;
- } else if ("0".equals(navBarOverride)) {
- mHasNavigationBar = true;
- }
-
- // For demo purposes, allow the rotation of the HDMI display to be controlled.
- // By default, HDMI locks rotation to landscape.
- if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
- mDemoHdmiRotation = displayRotation.getPortraitRotation();
- } else {
- mDemoHdmiRotation = displayRotation.getLandscapeRotation();
- }
- mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
-
- // For demo purposes, allow the rotation of the remote display to be controlled.
- // By default, remote display locks rotation to landscape.
- if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
- mDemoRotation = displayRotation.getPortraitRotation();
- } else {
- mDemoRotation = displayRotation.getLandscapeRotation();
- }
- mDemoRotationLock = SystemProperties.getBoolean(
- "persist.demo.rotationlock", false);
-
- // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
- // http://developer.android.com/guide/practices/screens_support.html#range
- // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
- // so if the orientation is forced, we need to respect that no matter what.
- final boolean isCar = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
- // For TV, it's usually 960dp x 540dp, ignore the size limitation.
- // so if the orientation is forced, we need to respect that no matter what.
- final boolean isTv = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LEANBACK);
- mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- !"true".equals(SystemProperties.get("config.override_forced_orient"));
- }
-
/**
* @return whether the navigation bar can be hidden, e.g. the device has a
* navigation bar and touch exploration is not enabled
*/
private boolean canHideNavigationBar() {
- return mHasNavigationBar;
- }
-
- @Override
- public boolean isDefaultOrientationForced() {
- return mForceDefaultOrientation;
+ return mDefaultDisplayPolicy.hasNavigationBar();
}
public void updateSettings() {
@@ -2470,15 +2176,6 @@
.getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
}
- // 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,
@@ -2489,24 +2186,6 @@
updateWakeGestureListenerLp();
}
- // Configure rotation lock.
- int userRotation = Settings.System.getIntForUser(resolver,
- Settings.System.USER_ROTATION, Surface.ROTATION_0,
- UserHandle.USER_CURRENT);
- if (mUserRotation != userRotation) {
- mUserRotation = userRotation;
- updateRotation = true;
- }
- int userRotationMode = Settings.System.getIntForUser(resolver,
- Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
- WindowManagerPolicy.USER_ROTATION_FREE :
- WindowManagerPolicy.USER_ROTATION_LOCKED;
- if (mUserRotationMode != userRotationMode) {
- mUserRotationMode = userRotationMode;
- updateRotation = true;
- updateOrientationListenerLp();
- }
-
if (mSystemReady) {
int pointerLocation = Settings.System.getIntForUser(resolver,
Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
@@ -2547,8 +2226,8 @@
}
private boolean shouldEnableWakeGestureLp() {
- return mWakeGestureEnabledSetting && !mAwake
- && (!mLidControlsSleep || mLidState != LID_CLOSED)
+ return mWakeGestureEnabledSetting && !mDefaultDisplayPolicy.isAwake()
+ && (!mLidControlsSleep || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
&& mWakeGestureListener.isSupported();
}
@@ -2588,24 +2267,6 @@
}
}
- private int readRotation(int resID) {
- try {
- int rotation = mContext.getResources().getInteger(resID);
- switch (rotation) {
- case 0:
- return Surface.ROTATION_0;
- case 90:
- return Surface.ROTATION_90;
- case 180:
- return Surface.ROTATION_180;
- case 270:
- return Surface.ROTATION_270;
- }
- } catch (Resources.NotFoundException e) {
- // fall through
- }
- return -1;
- }
/** {@inheritDoc} */
@Override
@@ -2834,7 +2495,7 @@
}
void readLidState() {
- mLidState = mWindowManagerFuncs.getLidState();
+ mDefaultDisplayPolicy.setLidState(mWindowManagerFuncs.getLidState());
}
private void readCameraLensCoverState() {
@@ -2842,11 +2503,12 @@
}
private boolean isHidden(int accessibilityMode) {
+ final int lidState = mDefaultDisplayPolicy.getLidState();
switch (accessibilityMode) {
case 1:
- return mLidState == LID_CLOSED;
+ return lidState == LID_CLOSED;
case 2:
- return mLidState == LID_OPEN;
+ return lidState == LID_OPEN;
default:
return false;
}
@@ -2886,7 +2548,7 @@
public void onConfigurationChanged(DisplayContentInfo displayContentInfo) {
final DisplayRotation displayRotation = displayContentInfo.getDisplayRotation();
// TODO(multi-display): Define policy for secondary displays.
- if (!displayRotation.isDefaultDisplay()) {
+ if (!displayRotation.isDefaultDisplay) {
return;
}
@@ -2962,10 +2624,10 @@
int displayId, DisplayCutout displayCutout) {
int width = fullWidth;
// TODO(multi-display): Support navigation bar on secondary displays.
- if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+ if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
// For a basic navigation bar, when we are in landscape mode we place
// the navigation bar to the side.
- if (mNavigationBarCanMove && fullWidth > fullHeight) {
+ if (mDefaultDisplayPolicy.navigationBarCanMove() && fullWidth > fullHeight) {
width -= getNavigationBarWidth(rotation, uiMode);
}
}
@@ -2988,10 +2650,10 @@
int displayId, DisplayCutout displayCutout) {
int height = fullHeight;
// TODO(multi-display): Support navigation bar on secondary displays.
- if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+ if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
// For a basic navigation bar, when we are in portrait mode we place
// the navigation bar to the bottom.
- if (!mNavigationBarCanMove || fullWidth < fullHeight) {
+ if (!mDefaultDisplayPolicy.navigationBarCanMove() || fullWidth < fullHeight) {
height -= getNavigationBarHeight(rotation, uiMode);
}
}
@@ -3079,8 +2741,8 @@
// In that case, we want to continue hiding the IME until the windows have completed
// drawing. This way, we know that the IME can be safely shown since the other windows are
// now shown.
- final boolean hideIme =
- win.isInputMethodWindow() && (mAodShowing || !mWindowManagerDrawComplete);
+ final boolean hideIme = win.isInputMethodWindow()
+ && (mAodShowing || !mDefaultDisplayPolicy.isWindowManagerDrawComplete());
return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider || hideIme;
}
@@ -3458,7 +3120,7 @@
@Override
public void selectRotationAnimationLw(int anim[]) {
// If the screen is off or non-interactive, force a jumpcut.
- final boolean forceJumpcut = !mScreenOnFully || !okToAnimate();
+ final boolean forceJumpcut = !mDefaultDisplayPolicy.isScreenOnFully() || !okToAnimate();
if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
+ mTopFullscreenOpaqueWindowState + " rotationAnimation="
+ (mTopFullscreenOpaqueWindowState == null ?
@@ -3865,7 +3527,7 @@
// If the device is in VR mode and keys are "internal" (e.g. on the side of the
// device), then drop the volume keys and don't forward it to the application/dispatch
// the audio event.
- if (mPersistentVrModeEnabled) {
+ if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
final InputDevice d = event.getDevice();
if (d != null && !d.isExternal()) {
return -1;
@@ -4955,7 +4617,7 @@
@NavigationBarPosition
private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
- if (mNavigationBarCanMove && displayWidth > displayHeight) {
+ if (mDefaultDisplayPolicy.navigationBarCanMove() && displayWidth > displayHeight) {
if (displayRotation == Surface.ROTATION_270) {
return NAV_BAR_LEFT;
} else {
@@ -5089,7 +4751,7 @@
mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
- final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
+ final boolean hasNavBar = (isDefaultDisplay && mDefaultDisplayPolicy.hasNavigationBar()
&& mNavigationBar != null && mNavigationBar.isVisibleLw());
final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
@@ -5898,11 +5560,11 @@
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
// lid changed state
final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
- if (newLidState == mLidState) {
+ if (newLidState == mDefaultDisplayPolicy.getLidState()) {
return;
}
- mLidState = newLidState;
+ mDefaultDisplayPolicy.setLidState(newLidState);
applyLidSwitchState();
updateRotation(true);
@@ -5937,17 +5599,6 @@
mCameraLensCoverState = lensCoverState;
}
- void setHdmiPlugged(boolean plugged) {
- if (mHdmiPlugged != plugged) {
- mHdmiPlugged = plugged;
- updateRotation(true, true);
- Intent intent = new Intent(ACTION_HDMI_PLUGGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
- }
-
void initializeHdmiState() {
final int oldMask = StrictMode.allowThreadDiskReadsMask();
try {
@@ -5987,8 +5638,7 @@
}
// This dance forces the code in setHdmiPlugged to run.
// Always do this so the sticky intent is stuck (to false) if there is no hdmi.
- mHdmiPlugged = !plugged;
- setHdmiPlugged(!mHdmiPlugged);
+ mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
}
@@ -6428,16 +6078,6 @@
}
/**
- * Notify the StatusBar that system rotation suggestion has changed.
- */
- private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
- StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
- if (statusBar != null) {
- statusBar.onProposedRotationChanged(rotation, isValid);
- }
- }
-
- /**
* 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.
@@ -6466,7 +6106,7 @@
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE:
- return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ return mDefaultDisplayPolicy.getDockMode() != Intent.EXTRA_DOCK_STATE_UNDOCKED;
// ignore media and camera keys
case KeyEvent.KEYCODE_MUTE:
@@ -6665,8 +6305,8 @@
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
- mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+ Intent.EXTRA_DOCK_STATE_UNDOCKED));
} else {
try {
IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
@@ -6676,9 +6316,7 @@
}
}
updateRotation(true);
- synchronized (mLock) {
- updateOrientationListenerLp();
- }
+ mDefaultDisplayRotation.updateOrientationListener();
}
};
@@ -6706,6 +6344,7 @@
// and then updates our own bookkeeping based on the now-
// current user.
mSettingsObserver.onChange(false);
+ mDefaultDisplayRotation.onUserSwitch();
// force a re-application of focused window sysui visibility.
// the window may never have been shown for this user
@@ -6779,15 +6418,16 @@
mGoingToSleep = false;
mRequestedOrGoingToSleep = false;
+ mDefaultDisplayPolicy.setAwake(false);
// We must get this work done here because the power manager will drop
// the wake lock and let the system suspend once this function returns.
synchronized (mLock) {
- mAwake = false;
updateWakeGestureListenerLp();
- updateOrientationListenerLp();
updateLockScreenTimeout();
}
+ mDefaultDisplayRotation.updateOrientationListener();
+
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onFinishedGoingToSleep(why,
mCameraGestureTriggeredDuringGoingToSleep);
@@ -6801,17 +6441,17 @@
EventLog.writeEvent(70000, 1);
if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
+ mDefaultDisplayPolicy.setAwake(true);
+
// Since goToSleep performs these functions synchronously, we must
// do the same here. We cannot post this work to a handler because
// that might cause it to become reordered with respect to what
// may happen in a future call to goToSleep.
synchronized (mLock) {
- mAwake = true;
-
updateWakeGestureListenerLp();
- updateOrientationListenerLp();
updateLockScreenTimeout();
}
+ mDefaultDisplayRotation.updateOrientationListener();
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedWakingUp();
@@ -6848,16 +6488,14 @@
}
private void finishKeyguardDrawn() {
- synchronized (mLock) {
- if (!mScreenOnEarly || mKeyguardDrawComplete) {
- return; // We are not awake yet or we have already informed of this event.
- }
+ if (!mDefaultDisplayPolicy.finishKeyguardDrawn()) {
+ return;
+ }
- mKeyguardDrawComplete = true;
+ synchronized (mLock) {
if (mKeyguardDelegate != null) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
}
- mWindowManagerDrawComplete = false;
}
// ... eventually calls finishWindowsDrawn which will finalize our screen turn on
@@ -6872,18 +6510,13 @@
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
updateScreenOffSleepToken(true);
+ mDefaultDisplayPolicy.screenTurnedOff();
synchronized (mLock) {
- mScreenOnEarly = false;
- mScreenOnFully = false;
- mKeyguardDrawComplete = false;
- mWindowManagerDrawComplete = false;
- mScreenOnListener = null;
- updateOrientationListenerLp();
-
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onScreenTurnedOff();
}
}
+ mDefaultDisplayRotation.updateOrientationListener();
reportScreenStateToVrManager(false);
}
@@ -6900,13 +6533,9 @@
if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
updateScreenOffSleepToken(false);
- synchronized (mLock) {
- mScreenOnEarly = true;
- mScreenOnFully = false;
- mKeyguardDrawComplete = false;
- mWindowManagerDrawComplete = false;
- mScreenOnListener = screenOnListener;
+ mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
+ synchronized (mLock) {
if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
@@ -6949,46 +6578,29 @@
}
private void finishWindowsDrawn() {
- synchronized (mLock) {
- if (!mScreenOnEarly || mWindowManagerDrawComplete) {
- return; // Screen is not turned on or we did already handle this case earlier.
- }
-
- mWindowManagerDrawComplete = true;
+ if (!mDefaultDisplayPolicy.finishWindowsDrawn()) {
+ return;
}
finishScreenTurningOn();
}
private void finishScreenTurningOn() {
- synchronized (mLock) {
- // We have just finished drawing screen content. Since the orientation listener
- // gets only installed when all windows are drawn, we try to install it again.
- updateOrientationListenerLp();
+ // We have just finished drawing screen content. Since the orientation listener
+ // gets only installed when all windows are drawn, we try to install it again.
+ mDefaultDisplayRotation.updateOrientationListener();
+
+ final ScreenOnListener listener = mDefaultDisplayPolicy.getScreenOnListener();
+ if (!mDefaultDisplayPolicy.finishScreenTurningOn()) {
+ return; // Spurious or not ready yet.
}
- final ScreenOnListener listener;
+
final boolean enableScreen;
+ final boolean awake = mDefaultDisplayPolicy.isAwake();
synchronized (mLock) {
- if (DEBUG_WAKEUP) Slog.d(TAG,
- "finishScreenTurningOn: mAwake=" + mAwake
- + ", mScreenOnEarly=" + mScreenOnEarly
- + ", mScreenOnFully=" + mScreenOnFully
- + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
- + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
- if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
- || (mAwake && !mKeyguardDrawComplete)) {
- return; // spurious or not ready yet
- }
-
- if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
- listener = mScreenOnListener;
- mScreenOnListener = null;
- mScreenOnFully = true;
-
// Remember the first time we draw the keyguard so we know when we're done with
// the main part of booting and can enable the screen and hide boot messages.
- if (!mKeyguardDrawnOnce && mAwake) {
+ if (!mKeyguardDrawnOnce && awake) {
mKeyguardDrawnOnce = true;
enableScreen = true;
if (mBootMessageNeedsHiding) {
@@ -7029,14 +6641,12 @@
@Override
public boolean isScreenOn() {
- synchronized (mLock) {
- return mScreenOnEarly;
- }
+ return mDefaultDisplayPolicy.isScreenOnEarly();
}
@Override
public boolean okToAnimate() {
- return mAwake && !mGoingToSleep;
+ return mDefaultDisplayPolicy.isAwake() && !mGoingToSleep;
}
/** {@inheritDoc} */
@@ -7146,7 +6756,7 @@
outInsets.setEmpty();
// Only navigation bar
- if (mHasNavigationBar) {
+ if (mDefaultDisplayPolicy.hasNavigationBar()) {
int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
if (position == NAV_BAR_BOTTOM) {
outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
@@ -7180,7 +6790,8 @@
public boolean isDockSideAllowed(int dockSide, int originalDockSide, int displayWidth,
int displayHeight, int displayRotation) {
final int barPosition = navigationBarPosition(displayWidth, displayHeight, displayRotation);
- return isDockSideAllowed(dockSide, originalDockSide, barPosition, mNavigationBarCanMove);
+ return isDockSideAllowed(dockSide, originalDockSide, barPosition,
+ mDefaultDisplayPolicy.navigationBarCanMove());
}
@VisibleForTesting
@@ -7217,186 +6828,6 @@
}
@Override
- public int rotationForOrientationLw(DisplayRotation displayRotation, int orientation,
- int lastRotation) {
- if (false) {
- Slog.v(TAG, "rotationForOrientationLw(orient="
- + orientation + ", last=" + lastRotation
- + "); user=" + mUserRotation + " "
- + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
- ? "USER_ROTATION_LOCKED" : "")
- );
- }
-
- if (mForceDefaultOrientation) {
- return Surface.ROTATION_0;
- }
-
- synchronized (mLock) {
- int sensorRotation = displayRotation.getSensorRotation(); // may be -1
- if (sensorRotation < 0) {
- sensorRotation = lastRotation;
- }
-
- final int preferredRotation;
- if (!displayRotation.isDefaultDisplay()) {
- // For secondary displays we ignore things like displays sensors, docking mode and
- // rotation lock, and always prefer a default rotation.
- preferredRotation = Surface.ROTATION_0;
- } else if (mLidState == 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 || 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 : mCarDockRotation;
- } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
- && (mDeskDockEnablesAccelerometer || 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 : mDeskDockRotation;
- } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
- // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
- // Note that the dock orientation overrides the HDMI orientation.
- preferredRotation = mDemoHdmiRotation;
- } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
- && mUndockedHdmiRotation >= 0) {
- // Ignore sensor when plugged into HDMI and an undocked orientation has
- // been specified in the configuration (only for legacy devices without
- // full multi-display support).
- // Note that the dock orientation overrides the HDMI orientation.
- preferredRotation = mUndockedHdmiRotation;
- } else if (mDemoRotationLock) {
- // Ignore sensor when demo rotation lock is enabled.
- // Note that the dock orientation and HDMI rotation lock override this.
- preferredRotation = mDemoRotation;
- } else if (mPersistentVrModeEnabled) {
- // While in VR, apps always prefer a portrait rotation. This does not change
- // any apps that explicitly set landscape, but does cause sensors be ignored,
- // and ignored any orientation lock that the user has set (this conditional
- // should remain above the ORIENTATION_LOCKED conditional below).
- preferredRotation = displayRotation.getPortraitRotation();
- } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
- // Application just wants to remain locked in the last rotation.
- preferredRotation = lastRotation;
- } else if (!mSupportAutoRotation) {
- // If we don't support auto-rotation then bail out here and ignore
- // the sensor and any rotation lock settings.
- preferredRotation = -1;
- } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
- && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
- || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
- || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
- || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
- || 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 (mAllowAllRotations < 0) {
- // Can't read this during init() because the context doesn't
- // have display metrics at that time so we cannot determine
- // tablet vs. phone then.
- mAllowAllRotations = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
- }
- if (sensorRotation != Surface.ROTATION_180
- || mAllowAllRotations == 1
- || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
- || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
- preferredRotation = sensorRotation;
- } else {
- preferredRotation = lastRotation;
- }
- } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
- && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
- // Apply rotation lock. Does not apply to NOSENSOR.
- // The idea is that the user rotation expresses a weak preference for the direction
- // of gravity and as NOSENSOR is never affected by gravity, then neither should
- // NOSENSOR be affected by rotation lock (although it will be affected by docks).
- preferredRotation = mUserRotation;
- } else {
- // No overriding preference.
- // We will do exactly what the application asked us to do.
- preferredRotation = -1;
- }
-
- return displayRotation.rotationForOrientation(orientation, lastRotation,
- preferredRotation);
- }
- }
-
- @Override
- public WindowManagerPolicy.RotationSource getRotationSource(int displayId) {
- // TODO(multi-display): Distinguish sensor for different displays.
- return displayId == DEFAULT_DISPLAY ? mDefaultOrientationListener : null;
- }
-
- public boolean isRotationChoicePossible(int orientation) {
- // Rotation choice is only shown when the user is in locked mode.
- if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
-
- // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
- // demo, hdmi, vr, etc mode
-
- // Determine if the rotation is 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;
- }
-
- // Ensure that some rotation choice is possible for the given orientation
- switch (orientation) {
- case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
- case ActivityInfo.SCREEN_ORIENTATION_USER:
- case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
- case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
- case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
- // NOSENSOR description is ambiguous, in reality WM ignores user choice
- return true;
- }
-
- // Rotation is forced, should be controlled by system
- return false;
- }
-
- @Override
public int getUserRotationMode() {
return Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
@@ -7468,8 +6899,8 @@
readCameraLensCoverState();
updateUiMode();
+ mDefaultDisplayRotation.updateOrientationListener();
synchronized (mLock) {
- updateOrientationListenerLp();
mSystemReady = true;
mHandler.post(new Runnable() {
@Override
@@ -7507,9 +6938,7 @@
@Override
public boolean canDismissBootAnimation() {
- synchronized (mLock) {
- return mKeyguardDrawComplete;
- }
+ return mDefaultDisplayPolicy.isKeyguardDrawComplete();
}
ProgressDialog mBootMsgDialog = null;
@@ -7609,7 +7038,7 @@
}
}
- if (mAwake && mNotifyUserActivity) {
+ if (mDefaultDisplayPolicy.isAwake() && mNotifyUserActivity) {
mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
USER_ACTIVITY_NOTIFICATION_DELAY);
mNotifyUserActivity = false;
@@ -7652,7 +7081,7 @@
private void updateLockScreenTimeout() {
synchronized (mScreenLockTimeout) {
- boolean enable = (mAllowLockscreenWhenOn && mAwake &&
+ final boolean enable = (mAllowLockscreenWhenOn && mDefaultDisplayPolicy.isAwake() &&
mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
if (mLockScreenTimerActive != enable) {
if (enable) {
@@ -7707,10 +7136,11 @@
}
private void applyLidSwitchState() {
- if (mLidState == LID_CLOSED && mLidControlsSleep) {
+ final int lidState = mDefaultDisplayPolicy.getLidState();
+ if (lidState == LID_CLOSED && mLidControlsSleep) {
goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
+ } else if (lidState == LID_CLOSED && mLidControlsScreenLock) {
mWindowManagerFuncs.lockDeviceNow();
}
@@ -7732,17 +7162,8 @@
void updateRotation(boolean alwaysSendConfiguration) {
try {
- //set orientation on WindowManager
- mWindowManager.updateRotation(alwaysSendConfiguration, false);
- } catch (RemoteException e) {
- // Ignore
- }
- }
-
- void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
- try {
- //set orientation on WindowManager
- mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
+ // Set orientation on WindowManager.
+ mWindowManager.updateRotation(alwaysSendConfiguration, false /* forceRelayout */);
} catch (RemoteException e) {
// Ignore
}
@@ -7775,12 +7196,14 @@
if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
intent = mDeskDockIntent;
}
- } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
- && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
- || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
- // Always launch dock home from home when watch is docked, if it exists.
- intent = mDeskDockIntent;
+ } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH) {
+ final int dockMode = mDefaultDisplayPolicy.getDockMode();
+ if (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK) {
+ // Always launch dock home from home when watch is docked, if it exists.
+ intent = mDeskDockIntent;
+ }
} else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
intent = mVrHeadsetHomeIntent;
@@ -8221,7 +7644,8 @@
final long now = SystemClock.uptimeMillis();
final boolean pendingPanic = mPendingPanicGestureUptime != 0
&& now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
- if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
+ if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard()
+ && mDefaultDisplayPolicy.isKeyguardDrawComplete()) {
// The user performed the panic gesture recently, we're about to hide the bars,
// we're no longer on the Keyguard and the screen is ready. We can now request the bars.
mPendingPanicGestureUptime = 0;
@@ -8364,7 +7788,7 @@
// overridden by qemu.hw.mainkeys in the emulator.
@Override
public boolean hasNavigationBar() {
- return mHasNavigationBar;
+ return mDefaultDisplayPolicy.hasNavigationBar();
}
@Override
@@ -8423,7 +7847,7 @@
// If the navigation bar can't change sides, then it will
// jump when we change orientations and we don't rotate
// seamlessly.
- if (!mNavigationBarCanMove) {
+ if (!displayRotation.getDisplayPolicy().navigationBarCanMove()) {
return false;
}
int delta = newRotation - oldRotation;
@@ -8457,12 +7881,13 @@
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(LAST_SYSTEM_UI_FLAGS, mLastSystemUiFlags);
- proto.write(ROTATION_MODE, mUserRotationMode);
- proto.write(ROTATION, mUserRotation);
+ proto.write(ROTATION_MODE, mDefaultDisplayRotation.getUserRotationMode());
+ proto.write(ROTATION, mDefaultDisplayRotation.getUserRotation());
proto.write(ORIENTATION, mDefaultDisplayRotation.getCurrentAppOrientation());
- proto.write(SCREEN_ON_FULLY, mScreenOnFully);
- proto.write(KEYGUARD_DRAW_COMPLETE, mKeyguardDrawComplete);
- proto.write(WINDOW_MANAGER_DRAW_COMPLETE, mWindowManagerDrawComplete);
+ proto.write(SCREEN_ON_FULLY, mDefaultDisplayPolicy.isScreenOnFully());
+ proto.write(KEYGUARD_DRAW_COMPLETE, mDefaultDisplayPolicy.isKeyguardDrawComplete());
+ proto.write(WINDOW_MANAGER_DRAW_COMPLETE,
+ mDefaultDisplayPolicy.isWindowManagerDrawComplete());
if (mFocusedApp != null) {
proto.write(FOCUSED_APP_TOKEN, mFocusedApp.toString());
}
@@ -8498,13 +7923,8 @@
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
pw.print(" mSystemReady="); pw.print(mSystemReady);
pw.print(" mSystemBooted="); pw.println(mSystemBooted);
- pw.print(prefix); pw.print("mLidState=");
- pw.print(WindowManagerFuncs.lidStateToString(mLidState));
- pw.print(" mLidOpenRotation=");
- pw.println(Surface.rotationToString(mLidOpenRotation));
pw.print(prefix); pw.print("mCameraLensCoverState=");
- pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
- pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+ pw.println(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
|| mForceClearedSystemUiFlags != 0) {
pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
@@ -8522,26 +7942,9 @@
pw.println(mWakeGestureEnabledSetting);
pw.print(prefix);
- pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation);
- pw.print(" mOrientationSensorEnabled=");
- pw.println(mDefaultOrientationListener.mEnabled);
- pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode));
- pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode));
- pw.print(prefix); pw.print("mEnableCarDockHomeCapture=");
- pw.print(mEnableCarDockHomeCapture);
- pw.print(" mCarDockRotation=");
- pw.print(Surface.rotationToString(mCarDockRotation));
- pw.print(" mDeskDockRotation=");
- pw.println(Surface.rotationToString(mDeskDockRotation));
- pw.print(prefix); pw.print("mUserRotationMode=");
- pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
- pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation));
- pw.print(" mAllowAllRotations=");
- pw.println(allowAllRotationsToString(mAllowAllRotations));
- pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
- pw.print(mCarDockEnablesAccelerometer);
- pw.print(" mDeskDockEnablesAccelerometer=");
- pw.println(mDeskDockEnablesAccelerometer);
+ pw.print("mUiMode=");
+ pw.print(Configuration.uiModeToString(mUiMode));
+ pw.print("mEnableCarDockHomeCapture="); pw.println(mEnableCarDockHomeCapture);
pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
pw.print(mLidKeyboardAccessibility);
pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
@@ -8591,12 +7994,6 @@
pw.print(" mEndcallBehavior=");
pw.println(endcallBehaviorToString(mEndcallBehavior));
pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
- pw.print(prefix);
- pw.print("mAwake="); pw.print(mAwake);
- pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
- pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
- pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
- pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
@@ -8651,11 +8048,6 @@
pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
- pw.print(prefix); pw.print("mDemoHdmiRotation=");
- pw.print(Surface.rotationToString(mDemoHdmiRotation));
- pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
- pw.print(prefix); pw.print("mUndockedHdmiRotation=");
- pw.println(Surface.rotationToString(mUndockedHdmiRotation));
if (mHasFeatureLeanback) {
pw.print(prefix);
pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
@@ -8687,19 +8079,6 @@
mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
}
- private static String allowAllRotationsToString(int allowAll) {
- switch (allowAll) {
- case -1:
- return "unknown";
- case 0:
- return "false";
- case 1:
- return "true";
- default:
- return Integer.toString(allowAll);
- }
- }
-
private static String endcallBehaviorToString(int behavior) {
StringBuilder sb = new StringBuilder();
if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 70b2165..cc39217 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -691,6 +691,11 @@
public final int USER_ROTATION_LOCKED = 1;
/**
+ * Set the default display content to provide basic functions for the policy.
+ */
+ public void setDefaultDisplay(DisplayContentInfo displayContentInfo);
+
+ /**
* Perform initialization of the policy.
*
* @param context The system context we are running in.
@@ -699,18 +704,6 @@
WindowManagerFuncs windowManagerFuncs);
/**
- * @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true.
- */
- public boolean isDefaultOrientationForced();
-
- /**
- * Called by window manager once it has the initial, default native
- * display dimensions.
- */
- public void setInitialDisplaySize(DisplayRotation displayRotation, int width, int height,
- int density);
-
- /**
* Check permissions when adding a window.
*
* @param attrs The window's LayoutParams.
@@ -1433,28 +1426,6 @@
public boolean isShowingDreamLw();
/**
- * 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.
- * @param defaultDisplay Flag indicating whether the rotation is computed for the default
- * display. Currently for all non-default displays sensors, docking mode,
- * rotation lock and other factors are ignored.
- * @return The surface rotation to use.
- */
- public int rotationForOrientationLw(DisplayRotation displayRotation,
- @ActivityInfo.ScreenOrientation int orientation, int lastRotation);
-
- public void updateOrientationListener();
-
- /**
- * Get rotation source for the given display id.
- */
- public RotationSource getRotationSource(int displayId);
-
- /**
* Called when the system is mostly done booting to set whether
* the system should go into safe mode.
*/
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 1508c9e..d5adb5e 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -204,6 +204,10 @@
}
}
+ public Handler getHandler() {
+ return mHandler;
+ }
+
/**
* Sets the current rotation.
*
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 605705e..ec2584b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -235,7 +235,8 @@
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final Display mDisplay;
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- final DisplayRotation mDisplayRotation;
+ private final DisplayPolicy mDisplayPolicy;
+ private DisplayRotation mDisplayRotation;
DisplayFrames mDisplayFrames;
/**
@@ -306,8 +307,11 @@
private boolean mLayoutNeeded;
int pendingLayoutChanges;
int mDeferredRotationPauseCount;
+
// TODO(multi-display): remove some of the usages.
+ @VisibleForTesting
boolean isDefaultDisplay;
+
/**
* Flag indicating whether WindowManager should override info for this display in
* DisplayManager.
@@ -764,7 +768,13 @@
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
initializeDisplayBaseInfo();
- mDisplayRotation = new DisplayRotation(this, mService.mPolicy, mService.mContext);
+ mDisplayPolicy = new DisplayPolicy(service);
+ mDisplayRotation = new DisplayRotation(service, this);
+ if (isDefaultDisplay) {
+ // The policy may be invoked right after here, so it requires the necessary default
+ // fields of this display content.
+ mService.mPolicy.setDefaultDisplay(this);
+ }
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
@@ -921,11 +931,20 @@
return mDisplayMetrics;
}
+ DisplayPolicy getDisplayPolicy() {
+ return mDisplayPolicy;
+ }
+
@Override
public DisplayRotation getDisplayRotation() {
return mDisplayRotation;
}
+ @VisibleForTesting
+ void setDisplayRotation(DisplayRotation displayRotation) {
+ mDisplayRotation = displayRotation;
+ }
+
int getRotation() {
return mRotation;
}
@@ -979,10 +998,7 @@
mDeferredRotationPauseCount--;
if (mDeferredRotationPauseCount == 0) {
- final boolean changed = updateRotationUnchecked();
- if (changed) {
- mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
- }
+ updateRotationAndSendNewConfigIfNeeded();
}
}
@@ -998,8 +1014,7 @@
final int oldRotation = getRotation();
final boolean oldAltOrientation = getAltOrientation();
- final int rotation = mService.mPolicy.rotationForOrientationLw(
- mDisplayRotation, lastOrientation, oldRotation);
+ final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
lastOrientation, rotation);
if (oldRotation == rotation && oldAltOrientation == altOrientation) {
@@ -1009,6 +1024,19 @@
}
/**
+ * Update rotation of the display and send configuration if the rotation is changed.
+ *
+ * @return {@code true} if the rotation has been changed and the new config is sent.
+ */
+ boolean updateRotationAndSendNewConfigIfNeeded() {
+ final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
+ if (changed) {
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
+ }
+ return changed;
+ }
+
+ /**
* Update rotation of the display.
*
* @return {@code true} if the rotation has been changed. In this case YOU MUST CALL
@@ -1066,8 +1094,7 @@
final int oldRotation = mRotation;
final int lastOrientation = mLastOrientation;
final boolean oldAltOrientation = mAltOrientation;
- final int rotation = mService.mPolicy.rotationForOrientationLw(mDisplayRotation,
- lastOrientation, oldRotation);
+ final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
+ mDisplayId + " based on lastOrientation=" + lastOrientation
+ " and oldRotation=" + oldRotation);
@@ -1220,7 +1247,24 @@
}
void configureDisplayPolicy() {
- mDisplayRotation.configure();
+ final int width = mBaseDisplayWidth;
+ final int height = mBaseDisplayHeight;
+ final int shortSize;
+ final int longSize;
+ if (width > height) {
+ shortSize = height;
+ longSize = width;
+ } else {
+ shortSize = width;
+ longSize = height;
+ }
+
+ final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+ final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+
+ mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
+ mDisplayPolicy.configure(width, height, shortSizeDp);
+
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
}
@@ -2394,6 +2438,8 @@
pw.println();
mDisplayFrames.dump(prefix, pw);
pw.println();
+ mDisplayPolicy.dump(prefix, pw);
+ pw.println();
mDisplayRotation.dump(prefix, pw);
pw.println();
mInputMonitor.dump(pw, " ");
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
new file mode 100644
index 0000000..9151ddf
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -0,0 +1,260 @@
+/*
+ * 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.server.wm;
+
+import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
+import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
+import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
+
+import java.io.PrintWriter;
+
+/**
+ * The policy that provides the basic behaviors and states of a display to show UI.
+ */
+public class DisplayPolicy {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
+
+ private final WindowManagerService mService;
+ private final Object mLock;
+
+ private final boolean mCarDockEnablesAccelerometer;
+ private final boolean mDeskDockEnablesAccelerometer;
+
+ private volatile int mLidState = LID_ABSENT;
+ private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+ private volatile boolean mHdmiPlugged;
+
+ private volatile boolean mHasNavigationBar;
+ // Can the navigation bar ever move to the side?
+ private volatile boolean mNavigationBarCanMove;
+
+ // Written by vr manager thread, only read in this class.
+ private volatile boolean mPersistentVrModeEnabled;
+
+ private volatile boolean mAwake;
+ private volatile boolean mScreenOnEarly;
+ private volatile boolean mScreenOnFully;
+ private volatile ScreenOnListener mScreenOnListener;
+
+ private volatile boolean mKeyguardDrawComplete;
+ private volatile boolean mWindowManagerDrawComplete;
+
+ DisplayPolicy(WindowManagerService service) {
+ mService = service;
+ mLock = service.getWindowManagerLock();
+ mCarDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_carDockEnablesAccelerometer);
+ mDeskDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
+ }
+
+ void configure(int width, int height, int shortSizeDp) {
+ // Allow the navigation bar to move on non-square small devices (phones).
+ mNavigationBarCanMove = width != height && shortSizeDp < 600;
+
+ mHasNavigationBar = mService.mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_showNavigationBar);
+
+ // Allow a system property to override this. Used by the emulator.
+ // See also hasNavigationBar().
+ String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+ if ("1".equals(navBarOverride)) {
+ mHasNavigationBar = false;
+ } else if ("0".equals(navBarOverride)) {
+ mHasNavigationBar = true;
+ }
+ }
+
+ public void setHdmiPlugged(boolean plugged) {
+ setHdmiPlugged(plugged, false /* force */);
+ }
+
+ public void setHdmiPlugged(boolean plugged, boolean force) {
+ if (force || mHdmiPlugged != plugged) {
+ mHdmiPlugged = plugged;
+ mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
+ final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
+ mService.mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ }
+
+ boolean isHdmiPlugged() {
+ return mHdmiPlugged;
+ }
+
+ boolean isCarDockEnablesAccelerometer() {
+ return mCarDockEnablesAccelerometer;
+ }
+
+ boolean isDeskDockEnablesAccelerometer() {
+ return mDeskDockEnablesAccelerometer;
+ }
+
+ public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
+ mPersistentVrModeEnabled = persistentVrModeEnabled;
+ }
+
+ public boolean isPersistentVrModeEnabled() {
+ return mPersistentVrModeEnabled;
+ }
+
+ public void setDockMode(int dockMode) {
+ mDockMode = dockMode;
+ }
+
+ public int getDockMode() {
+ return mDockMode;
+ }
+
+ public boolean hasNavigationBar() {
+ return mHasNavigationBar;
+ }
+
+ public boolean navigationBarCanMove() {
+ return mNavigationBarCanMove;
+ }
+
+ public void setLidState(int lidState) {
+ mLidState = lidState;
+ }
+
+ public int getLidState() {
+ return mLidState;
+ }
+
+ public void setAwake(boolean awake) {
+ mAwake = awake;
+ }
+
+ public boolean isAwake() {
+ return mAwake;
+ }
+
+ public boolean isScreenOnEarly() {
+ return mScreenOnEarly;
+ }
+
+ public boolean isScreenOnFully() {
+ return mScreenOnFully;
+ }
+
+ public boolean isKeyguardDrawComplete() {
+ return mKeyguardDrawComplete;
+ }
+
+ public boolean isWindowManagerDrawComplete() {
+ return mWindowManagerDrawComplete;
+ }
+
+ public ScreenOnListener getScreenOnListener() {
+ return mScreenOnListener;
+ }
+
+ public void screenTurnedOn(ScreenOnListener screenOnListener) {
+ synchronized (mLock) {
+ mScreenOnEarly = true;
+ mScreenOnFully = false;
+ mKeyguardDrawComplete = false;
+ mWindowManagerDrawComplete = false;
+ mScreenOnListener = screenOnListener;
+ }
+ }
+
+ public void screenTurnedOff() {
+ synchronized (mLock) {
+ mScreenOnEarly = false;
+ mScreenOnFully = false;
+ mKeyguardDrawComplete = false;
+ mWindowManagerDrawComplete = false;
+ mScreenOnListener = null;
+ }
+ }
+
+ /** Return false if we are not awake yet or we have already informed of this event. */
+ public boolean finishKeyguardDrawn() {
+ synchronized (mLock) {
+ if (!mScreenOnEarly || mKeyguardDrawComplete) {
+ return false;
+ }
+
+ mKeyguardDrawComplete = true;
+ mWindowManagerDrawComplete = false;
+ }
+ return true;
+ }
+
+ /** Return false if screen is not turned on or we did already handle this case earlier. */
+ public boolean finishWindowsDrawn() {
+ synchronized (mLock) {
+ if (!mScreenOnEarly || mWindowManagerDrawComplete) {
+ return false;
+ }
+
+ mWindowManagerDrawComplete = true;
+ }
+ return true;
+ }
+
+ /** Return false if it is not ready to turn on. */
+ public boolean finishScreenTurningOn() {
+ synchronized (mLock) {
+ if (DEBUG_SCREEN_ON) Slog.d(TAG,
+ "finishScreenTurningOn: mAwake=" + mAwake
+ + ", mScreenOnEarly=" + mScreenOnEarly
+ + ", mScreenOnFully=" + mScreenOnFully
+ + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+ + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+
+ if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
+ || (mAwake && !mKeyguardDrawComplete)) {
+ return false;
+ }
+
+ if (DEBUG_SCREEN_ON) Slog.i(TAG, "Finished screen turning on...");
+ mScreenOnListener = null;
+ mScreenOnFully = true;
+ }
+ return true;
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "DisplayPolicy");
+ pw.print(prefix + " mCarDockEnablesAccelerometer=" + mCarDockEnablesAccelerometer);
+ pw.println(" mDeskDockEnablesAccelerometer=" + mDeskDockEnablesAccelerometer);
+ pw.print(prefix + " mDockMode=" + Intent.dockStateToString(mDockMode));
+ pw.println(" mLidState=" + WindowManagerFuncs.lidStateToString(mLidState));
+ pw.print(prefix + " mAwake=" + mAwake);
+ pw.print(" mScreenOnEarly=" + mScreenOnEarly);
+ pw.println(" mScreenOnFully=" + mScreenOnFully);
+ pw.print(prefix + " mKeyguardDrawComplete=" + mKeyguardDrawComplete);
+ pw.println(" mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+ pw.println(prefix + " mHdmiPlugged=" + mHdmiPlugged);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 2074ecf..685c444 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -16,42 +16,140 @@
package com.android.server.wm;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.power.V1_0.PowerHint;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
import android.view.Surface;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.policy.WindowManagerPolicy.RotationSource;
+import com.android.server.policy.WindowOrientationListener;
+import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
/**
* Defines the mapping between orientation and rotation of a display.
+ * Non-public methods are assumed to run inside WM lock.
*/
public class DisplayRotation {
- private final DisplayContent mDisplayContent;
- private final WindowManagerPolicy mPolicy;
- private final Context mContext;
- private RotationSource mRotationSource;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayRotation" : TAG_WM;
- int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ private final WindowManagerService mService;
+ private final DisplayPolicy mDisplayPolicy;
+ private final Context mContext;
+ private final Object mLock;
+
+ public final boolean isDefaultDisplay;
+ private final boolean mSupportAutoRotation;
+ private final int mLidOpenRotation;
+ private final int mCarDockRotation;
+ private final int mDeskDockRotation;
+ private final int mUndockedHdmiRotation;
+
+ private OrientationListener mOrientationListener;
+ private StatusBarManagerInternal mStatusBarManagerInternal;
+ private SettingsObserver mSettingsObserver;
+
+ // Default display does not rotate, apps that require non-default orientation will have to
+ // have the orientation emulated.
+ private boolean mForceDefaultOrientation;
+
+ private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+ @VisibleForTesting
int mLandscapeRotation; // default landscape
+ @VisibleForTesting
int mSeascapeRotation; // "other" landscape, 180 degrees from mLandscapeRotation
+ @VisibleForTesting
int mPortraitRotation; // default portrait
+ @VisibleForTesting
int mUpsideDownRotation; // "other" portrait
- DisplayRotation(DisplayContent displayContent, WindowManagerPolicy policy, Context context) {
- mDisplayContent = displayContent;
- mPolicy = policy;
- mContext = context;
+ // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
+ private int mShowRotationSuggestions;
+
+ private int mAllowAllRotations = -1;
+ private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
+ private int mUserRotation = Surface.ROTATION_0;
+
+ private int mDemoHdmiRotation;
+ private int mDemoRotation;
+ private boolean mDemoHdmiRotationLock;
+ private boolean mDemoRotationLock;
+
+ DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
+ this(service, displayContent, displayContent.getDisplayPolicy(),
+ service.mContext, service.getWindowManagerLock());
}
- void configure() {
- mRotationSource = mPolicy.getRotationSource(mDisplayContent.getDisplayId());
+ @VisibleForTesting
+ DisplayRotation(WindowManagerService service, DisplayContent displayContent,
+ DisplayPolicy displayPolicy, Context context, Object lock) {
+ mService = service;
+ mDisplayPolicy = displayPolicy;
+ mContext = context;
+ mLock = lock;
+ isDefaultDisplay = displayContent.isDefaultDisplay;
- final int width = mDisplayContent.mBaseDisplayWidth;
- final int height = mDisplayContent.mBaseDisplayHeight;
+ mSupportAutoRotation = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_supportAutoRotation);
+ mLidOpenRotation = readRotation(
+ com.android.internal.R.integer.config_lidOpenRotation);
+ mCarDockRotation = readRotation(
+ com.android.internal.R.integer.config_carDockRotation);
+ mDeskDockRotation = readRotation(
+ com.android.internal.R.integer.config_deskDockRotation);
+ mUndockedHdmiRotation = readRotation(
+ com.android.internal.R.integer.config_undockedHdmiRotation);
+
+ if (isDefaultDisplay) {
+ final Handler uiHandler = UiThread.getHandler();
+ mOrientationListener = new OrientationListener(mContext, uiHandler);
+ mOrientationListener.setCurrentRotation(displayContent.getRotation());
+ mSettingsObserver = new SettingsObserver(uiHandler);
+ mSettingsObserver.observe();
+ }
+ }
+
+ private int readRotation(int resID) {
+ try {
+ final int rotation = mContext.getResources().getInteger(resID);
+ switch (rotation) {
+ case 0:
+ return Surface.ROTATION_0;
+ case 90:
+ return Surface.ROTATION_90;
+ case 180:
+ return Surface.ROTATION_180;
+ case 270:
+ return Surface.ROTATION_270;
+ }
+ } catch (Resources.NotFoundException e) {
+ // fall through
+ }
+ return -1;
+ }
+
+ void configure(int width, int height, int shortSizeDp, int longSizeDp) {
final Resources res = mContext.getResources();
if (width > height) {
mLandscapeRotation = Surface.ROTATION_0;
@@ -75,7 +173,60 @@
}
}
- mPolicy.setInitialDisplaySize(this, width, height, mDisplayContent.mBaseDisplayDensity);
+ // For demo purposes, allow the rotation of the HDMI display to be controlled.
+ // By default, HDMI locks rotation to landscape.
+ if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+ mDemoHdmiRotation = mPortraitRotation;
+ } else {
+ mDemoHdmiRotation = mLandscapeRotation;
+ }
+ mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
+
+ // For demo purposes, allow the rotation of the remote display to be controlled.
+ // By default, remote display locks rotation to landscape.
+ if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
+ mDemoRotation = mPortraitRotation;
+ } else {
+ mDemoRotation = mLandscapeRotation;
+ }
+ mDemoRotationLock = SystemProperties.getBoolean("persist.demo.rotationlock", false);
+
+ // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
+ // http://developer.android.com/guide/practices/screens_support.html#range
+ // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
+ // so if the orientation is forced, we need to respect that no matter what.
+ final boolean isCar = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
+ // For TV, it's usually 960dp x 540dp, ignore the size limitation.
+ // so if the orientation is forced, we need to respect that no matter what.
+ final boolean isTv = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_LEANBACK);
+ mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
+ res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ }
+
+ void setRotation(int rotation) {
+ if (mOrientationListener != null) {
+ mOrientationListener.setCurrentRotation(rotation);
+ }
+ }
+
+ void setCurrentOrientation(int newOrientation) {
+ if (newOrientation != mCurrentAppOrientation) {
+ mCurrentAppOrientation = newOrientation;
+ if (isDefaultDisplay) {
+ updateOrientationListenerLw();
+ }
+ }
+ }
+
+ /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
+ boolean isDefaultOrientationForced() {
+ return mForceDefaultOrientation;
}
public int getLandscapeRotation() {
@@ -98,31 +249,261 @@
return mCurrentAppOrientation;
}
- public int getSensorRotation() {
- return mRotationSource != null ? mRotationSource.getProposedRotation() : -1;
+ public DisplayPolicy getDisplayPolicy() {
+ return mDisplayPolicy;
}
- public boolean isDefaultDisplay() {
- return mDisplayContent.isDefaultDisplay;
+ public WindowOrientationListener getOrientationListener() {
+ return mOrientationListener;
}
- void setRotation(int rotation) {
- if (mRotationSource != null) {
- mRotationSource.setCurrentRotation(rotation);
+ public int getUserRotation() {
+ return mUserRotation;
+ }
+
+ public int getUserRotationMode() {
+ return mUserRotationMode;
+ }
+
+ public void updateOrientationListener() {
+ synchronized (mLock) {
+ updateOrientationListenerLw();
}
}
- void setCurrentOrientation(int newOrientation) {
- if (newOrientation != mCurrentAppOrientation) {
- mCurrentAppOrientation = newOrientation;
- // TODO(multi-display): Separate orientation listeners.
- if (mDisplayContent.isDefaultDisplay) {
- mPolicy.updateOrientationListener();
+ /**
+ * Various use cases for invoking this function:
+ * <li>Screen turning off, should always disable listeners if already enabled.</li>
+ * <li>Screen turned on and current app has sensor based orientation, enable listeners
+ * if not already enabled.</li>
+ * <li>Screen turned on and current app does not have sensor orientation, disable listeners
+ * if already enabled.</li>
+ * <li>Screen turning on and current app has sensor based orientation, enable listeners
+ * if needed.</li>
+ * <li>screen turning on and current app has nosensor based orientation, do nothing.</li>
+ */
+ private void updateOrientationListenerLw() {
+ if (mOrientationListener == null || !mOrientationListener.canDetectOrientation()) {
+ // If sensor is turned off or nonexistent for some reason.
+ return;
+ }
+
+ final boolean screenOnEarly = mDisplayPolicy.isScreenOnEarly();
+ final boolean awake = mDisplayPolicy.isAwake();
+ final boolean keyguardDrawComplete = mDisplayPolicy.isKeyguardDrawComplete();
+ final boolean windowManagerDrawComplete = mDisplayPolicy.isWindowManagerDrawComplete();
+
+ // Could have been invoked due to screen turning on or off or
+ // change of the currently visible window's orientation.
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "screenOnEarly=" + screenOnEarly
+ + ", awake=" + awake + ", currentAppOrientation=" + mCurrentAppOrientation
+ + ", orientationSensorEnabled=" + mOrientationListener.mEnabled
+ + ", keyguardDrawComplete=" + keyguardDrawComplete
+ + ", windowManagerDrawComplete=" + windowManagerDrawComplete);
+
+ boolean disable = true;
+ // Note: We postpone the rotating of the screen until the keyguard as well as the
+ // window manager have reported a draw complete or the keyguard is going away in dismiss
+ // mode.
+ if (screenOnEarly && awake && ((keyguardDrawComplete && windowManagerDrawComplete))) {
+ if (needSensorRunning()) {
+ disable = false;
+ // Enable listener if not already enabled.
+ if (!mOrientationListener.mEnabled) {
+ // Don't clear the current sensor orientation if the keyguard is going away in
+ // dismiss mode. This allows window manager to use the last sensor reading to
+ // determine the orientation vs. falling back to the last known orientation if
+ // the sensor reading was cleared which can cause it to relaunch the app that
+ // will show in the wrong orientation first before correcting leading to app
+ // launch delays.
+ mOrientationListener.enable(true /* clearCurrentRotation */);
+ }
}
}
+ // Check if sensors need to be disabled.
+ if (disable && mOrientationListener.mEnabled) {
+ mOrientationListener.disable();
+ }
}
- public int rotationForOrientation(int orientation, int lastRotation, int preferredRotation) {
+ /**
+ * We always let the sensor be switched on by default except when
+ * the user has explicitly disabled sensor based rotation or when the
+ * screen is switched off.
+ */
+ private boolean needSensorRunning() {
+ if (mSupportAutoRotation) {
+ 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 on.
+ return true;
+ }
+ }
+
+ final int dockMode = mDisplayPolicy.getDockMode();
+ if ((mDisplayPolicy.isCarDockEnablesAccelerometer()
+ && dockMode == Intent.EXTRA_DOCK_STATE_CAR)
+ || (mDisplayPolicy.isDeskDockEnablesAccelerometer()
+ && (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
+ // Enable accelerometer if we are docked in a dock that enables accelerometer
+ // orientation management.
+ return true;
+ }
+
+ if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+ // If the setting for using the sensor by default is enabled, then
+ // we will always leave it on. Note that the user could go to
+ // a window that forces an orientation that does not use the
+ // sensor and in theory we could turn it off... however, when next
+ // turning it on we won't have a good value for the current
+ // 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.)
+
+ // 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;
+ }
+
+ /**
+ * 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.
+ * @param defaultDisplay Flag indicating whether the rotation is computed for the default
+ * display. Currently for all non-default displays sensors, docking mode,
+ * rotation lock and other factors are ignored.
+ * @return The surface rotation to use.
+ */
+ int rotationForOrientation(int orientation, int lastRotation) {
+ if (DEBUG_ORIENTATION) {
+ Slog.v(TAG, "rotationForOrientation(orient="
+ + orientation + ", last=" + lastRotation
+ + "); user=" + mUserRotation + " "
+ + (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+ ? "USER_ROTATION_LOCKED" : "")
+ );
+ }
+
+ if (mForceDefaultOrientation) {
+ return Surface.ROTATION_0;
+ }
+
+ int sensorRotation = mOrientationListener != null
+ ? mOrientationListener.getProposedRotation() // may be -1
+ : -1;
+ if (sensorRotation < 0) {
+ sensorRotation = lastRotation;
+ }
+
+ final int lidState = mDisplayPolicy.getLidState();
+ final int dockMode = mDisplayPolicy.getDockMode();
+ final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+ final boolean carDockEnablesAccelerometer =
+ mDisplayPolicy.isCarDockEnablesAccelerometer();
+ final boolean deskDockEnablesAccelerometer =
+ mDisplayPolicy.isDeskDockEnablesAccelerometer();
+
+ final int preferredRotation;
+ if (!isDefaultDisplay) {
+ // For secondary displays we ignore things like displays sensors, docking mode and
+ // rotation lock, and always prefer a default rotation.
+ preferredRotation = Surface.ROTATION_0;
+ } else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+ // Ignore sensor when lid switch is open and rotation is forced.
+ preferredRotation = mLidOpenRotation;
+ } else if (dockMode == Intent.EXTRA_DOCK_STATE_CAR
+ && (carDockEnablesAccelerometer || 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 = carDockEnablesAccelerometer ? sensorRotation : mCarDockRotation;
+ } else if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+ && (deskDockEnablesAccelerometer || 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 = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
+ } else if (hdmiPlugged && mDemoHdmiRotationLock) {
+ // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
+ // Note that the dock orientation overrides the HDMI orientation.
+ preferredRotation = mDemoHdmiRotation;
+ } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+ && mUndockedHdmiRotation >= 0) {
+ // Ignore sensor when plugged into HDMI and an undocked orientation has
+ // been specified in the configuration (only for legacy devices without
+ // full multi-display support).
+ // Note that the dock orientation overrides the HDMI orientation.
+ preferredRotation = mUndockedHdmiRotation;
+ } else if (mDemoRotationLock) {
+ // Ignore sensor when demo rotation lock is enabled.
+ // Note that the dock orientation and HDMI rotation lock override this.
+ preferredRotation = mDemoRotation;
+ } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+ // While in VR, apps always prefer a portrait rotation. This does not change
+ // any apps that explicitly set landscape, but does cause sensors be ignored,
+ // and ignored any orientation lock that the user has set (this conditional
+ // should remain above the ORIENTATION_LOCKED conditional below).
+ preferredRotation = mPortraitRotation;
+ } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+ // Application just wants to remain locked in the last rotation.
+ preferredRotation = lastRotation;
+ } else if (!mSupportAutoRotation) {
+ // If we don't support auto-rotation then bail out here and ignore
+ // the sensor and any rotation lock settings.
+ preferredRotation = -1;
+ } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
+ || 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 (mAllowAllRotations < 0) {
+ // Can't read this during init() because the context doesn't
+ // have display metrics at that time so we cannot determine
+ // tablet vs. phone then.
+ mAllowAllRotations = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
+ }
+ if (sensorRotation != Surface.ROTATION_180
+ || mAllowAllRotations == 1
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+ || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
+ preferredRotation = sensorRotation;
+ } else {
+ preferredRotation = lastRotation;
+ }
+ } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+ && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+ // Apply rotation lock. Does not apply to NOSENSOR.
+ // The idea is that the user rotation expresses a weak preference for the direction
+ // of gravity and as NOSENSOR is never affected by gravity, then neither should
+ // NOSENSOR be affected by rotation lock (although it will be affected by docks).
+ preferredRotation = mUserRotation;
+ } else {
+ // No overriding preference.
+ // We will do exactly what the application asked us to do.
+ preferredRotation = -1;
+ }
+
switch (orientation) {
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
// Return portrait unless overridden.
@@ -184,6 +565,14 @@
}
}
+ private boolean isLandscapeOrSeascape(int rotation) {
+ return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
+ }
+
+ private boolean isAnyPortrait(int rotation) {
+ return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
+ }
+
/**
* Given an orientation constant and a rotation, returns true if the rotation
* has compatible metrics to the requested orientation. For example, if
@@ -214,7 +603,7 @@
}
}
- public boolean isValidRotationChoice(final int preferredRotation) {
+ private boolean isValidRotationChoice(final int preferredRotation) {
// Determine if the given app orientation is compatible with the provided rotation choice.
switch (mCurrentAppOrientation) {
case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
@@ -240,12 +629,143 @@
return false;
}
- private boolean isLandscapeOrSeascape(int rotation) {
- return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
+ private boolean isRotationChoicePossible(int orientation) {
+ // Rotation choice is only shown when the user is in locked mode.
+ if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
+
+ // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
+ // demo, hdmi, vr, etc mode.
+
+ // Determine if the rotation is currently forced.
+ if (mForceDefaultOrientation) {
+ return false; // Rotation is forced to default orientation.
+ }
+
+ final int lidState = mDisplayPolicy.getLidState();
+ if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+ return false; // Rotation is forced mLidOpenRotation.
+ }
+
+ final int dockMode = mDisplayPolicy.getDockMode();
+ final boolean carDockEnablesAccelerometer = false;
+ if (dockMode == Intent.EXTRA_DOCK_STATE_CAR && !carDockEnablesAccelerometer) {
+ return false; // Rotation forced to mCarDockRotation.
+ }
+
+ final boolean deskDockEnablesAccelerometer =
+ mDisplayPolicy.isDeskDockEnablesAccelerometer();
+ if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+ || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+ && !deskDockEnablesAccelerometer) {
+ return false; // Rotation forced to mDeskDockRotation.
+ }
+
+ final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+ if (hdmiPlugged && mDemoHdmiRotationLock) {
+ return false; // Rotation forced to mDemoHdmiRotation.
+
+ } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+ && mUndockedHdmiRotation >= 0) {
+ return false; // Rotation forced to mUndockedHdmiRotation.
+
+ } else if (mDemoRotationLock) {
+ return false; // Rotation forced to mDemoRotation.
+
+ } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+ return false; // Rotation forced to mPortraitRotation.
+
+ } else if (!mSupportAutoRotation) {
+ return false;
+ }
+
+ // Ensure that some rotation choice is possible for the given orientation.
+ switch (orientation) {
+ case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+ case ActivityInfo.SCREEN_ORIENTATION_USER:
+ case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+ case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+ case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+ // NOSENSOR description is ambiguous, in reality WM ignores user choice.
+ return true;
+ }
+
+ // Rotation is forced, should be controlled by system.
+ return false;
}
- private boolean isAnyPortrait(int rotation) {
- return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
+ /** Notify the StatusBar that system rotation suggestion has changed. */
+ private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
+ if (mStatusBarManagerInternal == null) {
+ mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
+ }
+ if (mStatusBarManagerInternal != null) {
+ mStatusBarManagerInternal.onProposedRotationChanged(rotation, isValid);
+ }
+ }
+
+ private static String allowAllRotationsToString(int allowAll) {
+ switch (allowAll) {
+ case -1:
+ return "unknown";
+ case 0:
+ return "false";
+ case 1:
+ return "true";
+ default:
+ return Integer.toString(allowAll);
+ }
+ }
+
+ public void onUserSwitch() {
+ if (mSettingsObserver != null) {
+ mSettingsObserver.onChange(false);
+ }
+ }
+
+ /** Return whether the rotation settings has changed. */
+ private boolean updateSettings() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ boolean shouldUpdateRotation = false;
+
+ synchronized (mLock) {
+ boolean shouldUpdateOrientationListener = false;
+
+ // Configure rotation suggestions.
+ final 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;
+ shouldUpdateOrientationListener = true;
+ }
+
+ // Configure rotation lock.
+ final int userRotation = Settings.System.getIntForUser(resolver,
+ Settings.System.USER_ROTATION, Surface.ROTATION_0,
+ UserHandle.USER_CURRENT);
+ if (mUserRotation != userRotation) {
+ mUserRotation = userRotation;
+ shouldUpdateRotation = true;
+ }
+
+ final int userRotationMode = Settings.System.getIntForUser(resolver,
+ Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0
+ ? WindowManagerPolicy.USER_ROTATION_FREE
+ : WindowManagerPolicy.USER_ROTATION_LOCKED;
+ if (mUserRotationMode != userRotationMode) {
+ mUserRotationMode = userRotationMode;
+ shouldUpdateOrientationListener = true;
+ shouldUpdateRotation = true;
+ }
+
+ if (shouldUpdateOrientationListener) {
+ updateOrientationListenerLw(); // Enable or disable the orientation listener.
+ }
+ }
+
+ return shouldUpdateRotation;
}
void dump(String prefix, PrintWriter pw) {
@@ -256,5 +776,106 @@
pw.println(" mSeascapeRotation=" + Surface.rotationToString(mSeascapeRotation));
pw.print(prefix + " mPortraitRotation=" + Surface.rotationToString(mPortraitRotation));
pw.println(" mUpsideDownRotation=" + Surface.rotationToString(mUpsideDownRotation));
+
+ pw.print(prefix + " mSupportAutoRotation=" + mSupportAutoRotation);
+ if (mOrientationListener != null) {
+ pw.print(" mOrientationSensorEnabled=" + mOrientationListener.mEnabled);
+ }
+ pw.println();
+
+ pw.print(prefix + " mCarDockRotation=" + Surface.rotationToString(mCarDockRotation));
+ pw.println(" mDeskDockRotation=" + Surface.rotationToString(mDeskDockRotation));
+ pw.print(prefix + " mUserRotationMode="
+ + WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
+ pw.print(" mUserRotation=" + Surface.rotationToString(mUserRotation));
+ pw.println(" mAllowAllRotations=" + allowAllRotationsToString(mAllowAllRotations));
+
+ pw.print(prefix + " mDemoHdmiRotation=" + Surface.rotationToString(mDemoHdmiRotation));
+ pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
+ pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
+ pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+ }
+
+ private class OrientationListener extends WindowOrientationListener {
+ final SparseArray<Runnable> mRunnableCache = new SparseArray<>(5);
+ boolean mEnabled;
+
+ OrientationListener(Context context, Handler handler) {
+ super(context, handler);
+ }
+
+ private class UpdateRunnable implements Runnable {
+ final int mRotation;
+
+ UpdateRunnable(int rotation) {
+ mRotation = rotation;
+ }
+
+ @Override
+ public void run() {
+ // Send interaction hint to improve redraw performance.
+ mService.mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
+ if (isRotationChoicePossible(mCurrentAppOrientation)) {
+ final boolean isValid = isValidRotationChoice(mRotation);
+ sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
+ } else {
+ mService.updateRotation(false /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ }
+ }
+ }
+
+ @Override
+ public void onProposedRotationChanged(int rotation) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
+ Runnable r = mRunnableCache.get(rotation, null);
+ if (r == null) {
+ r = new UpdateRunnable(rotation);
+ mRunnableCache.put(rotation, r);
+ }
+ getHandler().post(r);
+ }
+
+ @Override
+ public void enable(boolean clearCurrentRotation) {
+ super.enable(clearCurrentRotation);
+ mEnabled = true;
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Enabling listeners");
+ }
+
+ @Override
+ public void disable() {
+ super.disable();
+ mEnabled = false;
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Disabling listeners");
+ }
+ }
+
+ private class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.ACCELEROMETER_ROTATION), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.USER_ROTATION), false, this,
+ UserHandle.USER_ALL);
+ updateSettings();
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ if (updateSettings()) {
+ mService.updateRotation(true /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a2b3783..6578885 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2480,7 +2480,7 @@
dc.setLastOrientation(req);
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
- dc.mDisplayRotation.setCurrentOrientation(req);
+ dc.getDisplayRotation().setCurrentOrientation(req);
return dc.updateRotationUnchecked(forceUpdate);
}
return false;
@@ -3817,28 +3817,31 @@
long origId = Binder.clearCallingIdentity();
try {
- // TODO(multi-display): Update rotation for different displays separately.
- final boolean rotationChanged;
- final int displayId;
synchronized (mWindowMap) {
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
- rotationChanged = displayContent.updateRotationUnchecked();
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if (!rotationChanged || forceRelayout) {
- displayContent.setLayoutNeeded();
+ boolean layoutNeeded = false;
+ final int displayCount = mRoot.mChildren.size();
+ for (int i = 0; i < displayCount; ++i) {
+ final DisplayContent displayContent = mRoot.mChildren.get(i);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
+ final boolean rotationChanged = displayContent.updateRotationUnchecked();
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+
+ if (!rotationChanged || forceRelayout) {
+ displayContent.setLayoutNeeded();
+ layoutNeeded = true;
+ }
+ if (rotationChanged || alwaysSendConfiguration) {
+ mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+ .sendToTarget();
+ }
+ }
+
+ if (layoutNeeded) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"updateRotation: performSurfacePlacement");
mWindowPlacerLocked.performSurfacePlacement();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- displayId = displayContent.getDisplayId();
- }
-
- if (rotationChanged || alwaysSendConfiguration) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
- sendNewConfiguration(displayId);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -5775,7 +5778,7 @@
displayContent.updateDisplayInfo();
screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- mPolicy.isDefaultOrientationForced(), isSecure,
+ displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
this);
mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
screenRotationAnimation);
@@ -7126,11 +7129,7 @@
}
finishSeamlessRotation();
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent.updateRotationUnchecked()) {
- mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
- .sendToTarget();
- }
+ w.getDisplayContent().updateRotationAndSendNewConfigIfNeeded();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
index 46fcae7..ef87f9d 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
@@ -55,7 +55,7 @@
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.wm.DisplayFrames;
-import com.android.server.wm.TestDisplayContent;
+import com.android.server.wm.WindowTestUtils.TestDisplayContent;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before;
@@ -124,7 +124,6 @@
mNavigationBar.attrs.gravity = Gravity.BOTTOM;
mPolicy.addWindow(mNavigationBar);
- mPolicy.mHasNavigationBar = true;
mPolicy.mLastSystemUiFlags |= View.NAVIGATION_BAR_TRANSPARENT;
}
@@ -246,8 +245,10 @@
policy[0].mAccessibilityManager = new AccessibilityManager(context,
mock(IAccessibilityManager.class), UserHandle.USER_CURRENT);
policy[0].mSystemGestures = mock(SystemGesturesPointerEventListener.class);
- policy[0].mNavigationBarCanMove = true;
- policy[0].onConfigurationChanged(TestDisplayContent.create(policy[0], context));
+
+ final TestDisplayContent displayContent = TestDisplayContent.create(context);
+ policy[0].setDefaultDisplay(displayContent);
+ policy[0].onConfigurationChanged(displayContent);
});
return policy[0];
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index f6599dc..e8d8022 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -42,6 +42,10 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
/**
* Tests for the {@link AppWindowToken} class.
*
@@ -162,6 +166,9 @@
sWm.mDisplayReady = true;
sWm.mDisplayEnabled = true;
+ final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
+ mDisplayContent.setDisplayRotation(spiedRotation);
+
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
@@ -169,20 +176,21 @@
mToken.addWindow(appWindow);
// Set initial orientation and update.
- performRotation(Surface.ROTATION_90);
+ performRotation(spiedRotation, Surface.ROTATION_90);
appWindow.resizeReported = false;
// Update the rotation to perform 180 degree rotation and check that resize was reported.
- performRotation(Surface.ROTATION_270);
+ performRotation(spiedRotation, Surface.ROTATION_270);
assertTrue(appWindow.resizeReported);
+
appWindow.removeImmediately();
}
- private void performRotation(int rotationToReport) {
- ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport;
+ private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
+ doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
sWm.updateRotation(false, false);
- // Simulate animator finishing orientation change
- sWm.mRoot.mOrientationChangeComplete = true;
+ // Prevent the next rotation from being deferred by animation.
+ sWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/servicestests/src/com/android/server/wm/TestDisplayContent.java
deleted file mode 100644
index 09c6a07..0000000
--- a/services/tests/servicestests/src/com/android/server/wm/TestDisplayContent.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.server.wm;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.view.Display;
-import android.view.Surface;
-
-import com.android.server.policy.WindowManagerPolicy;
-
-public class TestDisplayContent extends DisplayContent {
-
- TestDisplayContent(Display display, WindowManagerService service,
- WallpaperController wallpaperController, DisplayWindowController controller) {
- super(display, service, wallpaperController, controller);
- }
-
- public static TestDisplayContent create(WindowManagerPolicy policy, Context context) {
- final TestDisplayContent displayContent = mock(TestDisplayContent.class);
- displayContent.isDefaultDisplay = true;
-
- final DisplayRotation displayRotation = new DisplayRotation(
- displayContent, policy, context);
- displayRotation.mPortraitRotation = Surface.ROTATION_0;
- displayRotation.mLandscapeRotation = Surface.ROTATION_90;
- displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
- displayRotation.mSeascapeRotation = Surface.ROTATION_270;
-
- when(displayContent.getDisplayRotation()).thenReturn(displayRotation);
-
- return displayContent;
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index e8f375d..735e284 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -72,15 +72,7 @@
}
- @Override
- public boolean isDefaultOrientationForced() {
- return false;
- }
-
- @Override
- public void setInitialDisplaySize(DisplayRotation displayRotation, int width, int height,
- int density) {
-
+ public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
}
@Override
@@ -389,13 +381,6 @@
public void onKeyguardOccludedChangedLw(boolean occluded) {
}
- @Override
- public int rotationForOrientationLw(DisplayRotation displayRotation, int orientation,
- int lastRotation) {
- return rotationToReport;
- }
-
- @Override
public void setSafeMode(boolean safeMode) {
}
@@ -593,13 +578,4 @@
public boolean setAodShowing(boolean aodShowing) {
return false;
}
-
- @Override
- public void updateOrientationListener() {
- }
-
- @Override
- public RotationSource getRotationSource(int displayId) {
- return null;
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index a48a3b9..a1b1640 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -22,8 +22,10 @@
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
+import android.view.Display;
import android.view.IApplicationToken;
import android.view.IWindow;
+import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
@@ -60,6 +62,37 @@
return service;
}
+ /** An extension of {@link DisplayContent} to gain package scoped access. */
+ public static class TestDisplayContent extends DisplayContent {
+
+ private TestDisplayContent(Display display, WindowManagerService service,
+ WallpaperController wallpaperController, DisplayWindowController controller) {
+ super(display, service, wallpaperController, controller);
+ }
+
+ /** Create a mocked default {@link DisplayContent}. */
+ public static TestDisplayContent create(Context context) {
+ final TestDisplayContent displayContent = mock(TestDisplayContent.class);
+ displayContent.isDefaultDisplay = true;
+
+ final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
+ when(displayPolicy.navigationBarCanMove()).thenReturn(true);
+ when(displayPolicy.hasNavigationBar()).thenReturn(true);
+
+ final DisplayRotation displayRotation = new DisplayRotation(
+ mock(WindowManagerService.class), displayContent, displayPolicy,
+ context, new Object());
+ displayRotation.mPortraitRotation = Surface.ROTATION_0;
+ displayRotation.mLandscapeRotation = Surface.ROTATION_90;
+ displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
+ displayRotation.mSeascapeRotation = Surface.ROTATION_270;
+
+ when(displayContent.getDisplayRotation()).thenReturn(displayRotation);
+
+ return displayContent;
+ }
+ }
+
/**
* Creates a mock instance of {@link StackWindowController}.
*/