Merge "Update Landscape <-> Autorotate QS animations" into oc-dr1-dev
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6834ba8..be31d1b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -42,6 +42,9 @@
import java.util.ArrayList;
import java.util.Locale;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_UNDEFINED;
+
/**
* This class describes all device configuration information that can
* impact the resources the application retrieves. This includes both
@@ -597,6 +600,13 @@
*/
public int orientation;
+ /**
+ * The mRotation used at the time orientation was determined.
+ * TODO(b/36812336): Move mRotation out of {@link Configuration}.
+ * {@hide}
+ */
+ private int mRotation;
+
/** Constant for {@link #uiMode}: bits that encode the mode type. */
public static final int UI_MODE_TYPE_MASK = 0x0f;
/** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
@@ -884,6 +894,7 @@
navigation = o.navigation;
navigationHidden = o.navigationHidden;
orientation = o.orientation;
+ mRotation = o.mRotation;
screenLayout = o.screenLayout;
colorMode = o.colorMode;
uiMode = o.uiMode;
@@ -1074,6 +1085,7 @@
navigation = NAVIGATION_UNDEFINED;
navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
+ mRotation = ROTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_UNDEFINED;
colorMode = COLOR_MODE_UNDEFINED;
uiMode = UI_MODE_TYPE_UNDEFINED;
@@ -1182,6 +1194,11 @@
changed |= ActivityInfo.CONFIG_ORIENTATION;
orientation = delta.orientation;
}
+ if (delta.mRotation != ROTATION_UNDEFINED
+ && mRotation != delta.mRotation) {
+ changed |= ActivityInfo.CONFIG_ORIENTATION;
+ mRotation = delta.mRotation;
+ }
if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
&& (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
@@ -1376,6 +1393,10 @@
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
}
+ if ((compareUndefined || delta.mRotation != ROTATION_UNDEFINED)
+ && mRotation != delta.mRotation) {
+ changed |= ActivityInfo.CONFIG_ORIENTATION;
+ }
if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
(SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
&& getScreenLayoutNoDirection(screenLayout) !=
@@ -1512,6 +1533,7 @@
dest.writeInt(navigation);
dest.writeInt(navigationHidden);
dest.writeInt(orientation);
+ dest.writeInt(mRotation);
dest.writeInt(screenLayout);
dest.writeInt(colorMode);
dest.writeInt(uiMode);
@@ -1548,6 +1570,7 @@
navigation = source.readInt();
navigationHidden = source.readInt();
orientation = source.readInt();
+ mRotation = source.readInt();
screenLayout = source.readInt();
colorMode = source.readInt();
uiMode = source.readInt();
@@ -1632,6 +1655,8 @@
if (n != 0) return n;
n = this.orientation - that.orientation;
if (n != 0) return n;
+ n = this.mRotation - that.mRotation;
+ if (n != 0) return n;
n = this.colorMode - that.colorMode;
if (n != 0) return n;
n = this.screenLayout - that.screenLayout;
@@ -1763,6 +1788,24 @@
/**
* @hide
*
+ * Setter for orientation converts from {@link Surface} values to internal representation.
+ */
+ public void setRotation(int rotation) {
+ this.mRotation = rotation;
+ }
+
+ /**
+ * @hide
+ *
+ * Getter for orientation. Converts from internal representation to {@link Surface} values.
+ */
+ public int getRotation() {
+ return mRotation != ROTATION_UNDEFINED ? mRotation : ROTATION_0;
+ }
+
+ /**
+ * @hide
+ *
* Clears the locale without changing layout direction.
*/
public void clearLocales() {
@@ -2193,6 +2236,10 @@
delta.orientation = change.orientation;
}
+ if (base.mRotation != change.mRotation) {
+ base.mRotation = change.mRotation;
+ }
+
if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
(change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
@@ -2264,6 +2311,7 @@
private static final String XML_ATTR_NAVIGATION = "nav";
private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
private static final String XML_ATTR_ORIENTATION = "ori";
+ private static final String XML_ATTR_ROTATION = "rot";
private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
private static final String XML_ATTR_COLOR_MODE = "clrMod";
private static final String XML_ATTR_UI_MODE = "ui";
@@ -2323,6 +2371,8 @@
DENSITY_DPI_UNDEFINED);
configOut.appBounds =
Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
+ configOut.mRotation = XmlUtils.readIntAttribute(parser, XML_ATTR_ROTATION,
+ ROTATION_UNDEFINED);
// For persistence, we don't care about assetsSeq, so do not read it out.
}
@@ -2399,6 +2449,10 @@
config.appBounds.flattenToString());
}
+ if (config.mRotation != ROTATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_ROTATION, config.mRotation);
+ }
+
// For persistence, we do not care about assetsSeq, so do not write it out.
}
}
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
index 68d0309..ae66050 100644
--- a/core/java/android/util/MergedConfiguration.java
+++ b/core/java/android/util/MergedConfiguration.java
@@ -161,6 +161,21 @@
return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}";
}
+ @Override
+ public int hashCode() {
+ return mMergedConfig.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (!(that instanceof MergedConfiguration)) {
+ return false;
+ }
+
+ if (that == this) return true;
+ return mMergedConfig.equals(((MergedConfiguration) that).mMergedConfig);
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "mGlobalConfig=" + mGlobalConfig);
pw.println(prefix + "mOverrideConfig=" + mOverrideConfig);
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index cdb9b82..7346a21 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -726,6 +726,17 @@
}
/**
+ * Returns the rotation associated with this display as used during layout. This is currently
+ * derived from the {@link Configuration}.
+ *
+ * @hide
+ */
+ @Surface.Rotation
+ public int getLayoutRotation() {
+ return mResources.getConfiguration().getRotation();
+ }
+
+ /**
* @deprecated use {@link #getRotation}
* @return orientation of this display.
*/
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 4f9dbd5..1b70232 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -131,11 +131,17 @@
public static final int SCALING_MODE_NO_SCALE_CROP = 3;
/** @hide */
- @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
+ @IntDef({ROTATION_UNDEFINED, ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
@Retention(RetentionPolicy.SOURCE)
public @interface Rotation {}
/**
+ * Rotation constant: undefined
+ * @hide
+ */
+ public static final int ROTATION_UNDEFINED = -1;
+
+ /**
* Rotation constant: 0 degree rotation (natural orientation)
*/
public static final int ROTATION_0 = 0;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e27eab9..e38a55f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1904,14 +1904,16 @@
+ " outsets=" + mPendingOutsets.toShortString()
+ " surface=" + mSurface);
- final Configuration pendingMergedConfig =
- mPendingMergedConfiguration.getMergedConfiguration();
- if (pendingMergedConfig.seq != 0) {
+ // If the pending {@link MergedConfiguration} handed back from
+ // {@link #relayoutWindow} does not match the one last reported,
+ // WindowManagerService has reported back a frame from a configuration not yet
+ // handled by the client. In this case, we need to accept the configuration so we
+ // do not lay out and draw with the wrong configuration.
+ if (!mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) {
if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
- + pendingMergedConfig);
+ + mPendingMergedConfiguration.getMergedConfiguration());
performConfigurationChange(mPendingMergedConfiguration, !mFirst,
INVALID_DISPLAY /* same display */);
- pendingMergedConfig.seq = 0;
updatedConfiguration = true;
}
@@ -3596,6 +3598,13 @@
mView.setLayoutDirection(currentLayoutDirection);
}
mView.dispatchConfigurationChanged(config);
+
+ // We could have gotten this {@link Configuration} update after we called
+ // {@link #performTraversals} with an older {@link Configuration}. As a result, our
+ // window frame may be stale. We must ensure the next pass of {@link #performTraversals}
+ // catches this.
+ mForceNextWindowRelayout = true;
+ requestLayout();
}
}
@@ -3757,10 +3766,10 @@
SomeArgs args = (SomeArgs) msg.obj;
final int displayId = args.argi3;
- final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
+ MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
final boolean displayChanged = mDisplay.getDisplayId() != displayId;
- if (mergedConfiguration != null) {
+ if (!mLastReportedMergedConfiguration.equals(mergedConfiguration)) {
// If configuration changed - notify about that and, maybe, about move to
// display.
performConfigurationChange(mergedConfiguration, false /* force */,
@@ -6094,7 +6103,7 @@
if (params != null) {
if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
}
- mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
+
//Log.d(mTag, ">>>>>> CALLING relayout");
if (params != null && mOrigWindowType != params.type) {
// For compatibility with old apps, don't crash here.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 14d0b7e..33d92fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -309,7 +309,7 @@
public static final boolean DEBUG_GESTURES = false;
public static final boolean DEBUG_MEDIA = false;
public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
- public static final boolean DEBUG_CAMERA_LIFT = true; // false once b/62623620 is fixed
+ public static final boolean DEBUG_CAMERA_LIFT = false;
public static final boolean DEBUG_WINDOW_STATE = false;
@@ -425,6 +425,7 @@
private boolean mWakeUpComingFromTouch;
private PointF mWakeUpTouchLocation;
private boolean mScreenTurningOn;
+ private boolean mScreenFullyOff;
int mPixelFormat;
Object mQueueLock = new Object();
@@ -2811,7 +2812,9 @@
}
public void onScreenTurnedOff() {
+ mScreenFullyOff = true;
mFalsingManager.onScreenOff();
+ updateIsKeyguard();
}
public NotificationStackScrollLayout getNotificationScrollLayout() {
@@ -4188,8 +4191,11 @@
private boolean updateIsKeyguard() {
// For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
- // there's no surface we can show to the user.
- boolean keyguardForDozing = mDozingRequested && !mDeviceInteractive;
+ // there's no surface we can show to the user. Note that the device goes fully interactive
+ // late in the transition, so we also allow the device to start dozing once the screen has
+ // turned off fully.
+ boolean keyguardForDozing = mDozingRequested &&
+ (!mDeviceInteractive || mStartedGoingToSleep && (mScreenFullyOff || mIsKeyguard));
boolean shouldBeKeyguard = mKeyguardRequested || keyguardForDozing;
if (keyguardForDozing) {
updatePanelExpansionForKeyguard();
@@ -5130,6 +5136,7 @@
}
public void onScreenTurningOn() {
+ mScreenFullyOff = false;
mScreenTurningOn = true;
mFalsingManager.onScreenTurningOn();
mNotificationPanel.onScreenTurningOn();
@@ -5297,7 +5304,7 @@
mDozingRequested = true;
DozeLog.traceDozing(mContext, mDozing);
updateDozing();
-
+ updateIsKeyguard();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 9b0307d..2833ff1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -152,7 +152,7 @@
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
*/
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
- if (mBouncer.needsFullscreenBouncer()) {
+ if (mBouncer.needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
mStatusBar.hideKeyguard();
@@ -258,8 +258,11 @@
}
public void setDozing(boolean dozing) {
- mDozing = dozing;
- updateStates();
+ if (mDozing != dozing) {
+ mDozing = dozing;
+ reset(dozing /* hideBouncerWhenShowing */);
+ updateStates();
+ }
}
public void onScreenTurnedOff() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 93dc6de..6104bef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -138,7 +138,7 @@
}
private void adjustScreenOrientation(State state) {
- if (state.isKeyguardShowingAndNotOccluded()) {
+ if (state.isKeyguardShowingAndNotOccluded() || state.dozing) {
if (mKeyguardScreenRotation) {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
} else {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java b/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java
index 13ed2a2..2a44771 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/RoundedCornersTest.java
@@ -46,7 +46,6 @@
import com.android.systemui.tuner.TunerService;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -105,7 +104,6 @@
}
@Test
- @Ignore
public void testRounding() {
mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20);
mContext.getOrCreateTestableResources()
@@ -115,8 +113,8 @@
// Add 2 windows for rounded corners (top and bottom).
verify(mWindowManager, times(2)).addView(any(), any());
- // Add 3 tag listeners for each of the fragments that are needed.
- verify(mFragmentHostManager, times(3)).addTagListener(any(), any());
+ // Add 2 tag listeners for each of the fragments that are needed.
+ verify(mFragmentHostManager, times(2)).addTagListener(any(), any());
// One tunable.
verify(mTunerService, times(1)).addTunable(any(), any());
// One TunablePadding.
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 4c9495a..a903f3d 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -57,7 +57,7 @@
*/
public class GestureLauncherService extends SystemService {
private static final boolean DBG = false;
- private static final boolean DBG_CAMERA_LIFT = true; // false once b/62623620 is fixed
+ private static final boolean DBG_CAMERA_LIFT = false;
private static final String TAG = "GestureLauncherService";
/**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ab3aff9..8269042 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -132,7 +132,7 @@
private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
- private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
+ private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
private static final int MSG_REQUEST_TRAVERSAL = 4;
@@ -266,7 +266,6 @@
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
-
}
public void setupSchedulerPolicies() {
@@ -284,9 +283,9 @@
// We need to pre-load the persistent data store so it's ready before the default display
// adapter is up so that we have it's configuration. We could load it lazily, but since
// we're going to have to read it in eventually we may as well do it here rather than after
- // we've waited for the diplay to register itself with us.
+ // we've waited for the display to register itself with us.
mPersistentDataStore.loadIfNeeded();
- mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
+ mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true /*allowIsolated*/);
@@ -298,12 +297,16 @@
public void onBootPhase(int phase) {
if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
synchronized (mSyncRoot) {
- long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
- while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
+ long timeout = SystemClock.uptimeMillis()
+ + mInjector.getDefaultDisplayDelayTimeout();
+ while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
+ mVirtualDisplayAdapter == null) {
long delay = timeout - SystemClock.uptimeMillis();
if (delay <= 0) {
throw new RuntimeException("Timeout waiting for default display "
- + "to be initialized.");
+ + "to be initialized. DefaultDisplay="
+ + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
+ + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
}
if (DEBUG) {
Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
@@ -685,11 +688,23 @@
}
}
- private void registerDefaultDisplayAdapter() {
- // Register default display adapter.
+ private void registerDefaultDisplayAdapters() {
+ // Register default display adapters.
synchronized (mSyncRoot) {
+ // main display adapter
registerDisplayAdapterLocked(new LocalDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
+
+ // Standalone VR devices rely on a virtual display as their primary display for
+ // 2D UI. We register virtual display adapter along side the main display adapter
+ // here so that it is ready by the time the system sends the home Intent for
+ // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
+ // the virtual display inside VR before any VR-specific apps even run.
+ mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
+ mHandler, mDisplayAdapterListener);
+ if (mVirtualDisplayAdapter != null) {
+ registerDisplayAdapterLocked(mVirtualDisplayAdapter);
+ }
}
}
@@ -698,7 +713,6 @@
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
registerOverlayDisplayAdapterLocked();
registerWifiDisplayAdapterLocked();
- registerVirtualDisplayAdapterLocked();
}
}
}
@@ -719,12 +733,6 @@
}
}
- private void registerVirtualDisplayAdapterLocked() {
- mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, mHandler,
- mDisplayAdapterListener);
- registerDisplayAdapterLocked(mVirtualDisplayAdapter);
- }
-
private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
// In safe mode, we disable non-essential display adapters to give the user
// an opportunity to fix broken settings or other problems that might affect
@@ -1219,6 +1227,10 @@
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
}
+
+ long getDefaultDisplayDelayTimeout() {
+ return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
+ }
}
@VisibleForTesting
@@ -1241,8 +1253,8 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
- registerDefaultDisplayAdapter();
+ case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
+ registerDefaultDisplayAdapters();
break;
case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index fa98f17..b1c1df1 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -35,7 +35,6 @@
private final static String TAG = "Vr2dDisplay";
private final static boolean DEBUG = false;
- // TODO: Go over these values and figure out what is best
private int mVirtualDisplayHeight;
private int mVirtualDisplayWidth;
private int mVirtualDisplayDpi;
@@ -55,17 +54,17 @@
/**
* The default width of the VR virtual display
*/
- public static final int DEFAULT_VR_DISPLAY_WIDTH = 1400;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_WIDTH = 1400;
/**
* The default height of the VR virtual display
*/
- public static final int DEFAULT_VR_DISPLAY_HEIGHT = 1800;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_HEIGHT = 1400;
/**
* The default height of the VR virtual dpi.
*/
- public static final int DEFAULT_VR_DISPLAY_DPI = 320;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_DPI = 320;
/**
* The minimum height, width and dpi of VR virtual display.
@@ -87,8 +86,8 @@
new IPersistentVrStateCallbacks.Stub() {
@Override
public void onPersistentVrStateChanged(boolean enabled) {
- if (enabled != mIsVrModeEnabled) {
- mIsVrModeEnabled = enabled;
+ if (enabled != mIsPersistentVrModeEnabled) {
+ mIsPersistentVrModeEnabled = enabled;
updateVirtualDisplay();
}
}
@@ -98,26 +97,33 @@
private Surface mSurface;
private ImageReader mImageReader;
private Runnable mStopVDRunnable;
- private boolean mIsVrModeOverrideEnabled;
- private boolean mIsVrModeEnabled;
- private boolean mIsVirtualDisplayAllowed = true;
+ private boolean mIsVrModeOverrideEnabled; // debug override to set vr mode.
+ private boolean mIsVirtualDisplayAllowed = true; // Virtual-display feature toggle
+ private boolean mIsPersistentVrModeEnabled; // indicates we are in vr persistent mode.
+ private boolean mBootsToVr = false; // The device boots into VR (standalone VR device)
public Vr2dDisplay(DisplayManager displayManager,
ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
mDisplayManager = displayManager;
mActivityManagerInternal = activityManagerInternal;
mVrManager = vrManager;
- mVirtualDisplayWidth = DEFAULT_VR_DISPLAY_WIDTH;
- mVirtualDisplayHeight = DEFAULT_VR_DISPLAY_HEIGHT;
- mVirtualDisplayDpi = DEFAULT_VR_DISPLAY_DPI;
+ mVirtualDisplayWidth = DEFAULT_VIRTUAL_DISPLAY_WIDTH;
+ mVirtualDisplayHeight = DEFAULT_VIRTUAL_DISPLAY_HEIGHT;
+ mVirtualDisplayDpi = DEFAULT_VIRTUAL_DISPLAY_DPI;
}
/**
* Initializes the compabilitiy display by listening to VR mode changes.
*/
- public void init(Context context) {
+ public void init(Context context, boolean bootsToVr) {
startVrModeListener();
startDebugOnlyBroadcastReceiver(context);
+ mBootsToVr = bootsToVr;
+ if (mBootsToVr) {
+ // If we are booting into VR, we need to start the virtual display immediately. This
+ // ensures that the virtual display is up by the time Setup Wizard is started.
+ updateVirtualDisplay();
+ }
}
/**
@@ -125,11 +131,13 @@
*/
private void updateVirtualDisplay() {
if (DEBUG) {
- Log.i(TAG, "isVrMode: " + mIsVrModeEnabled + ", override: " + mIsVrModeOverrideEnabled
- + ", isAllowed: " + mIsVirtualDisplayAllowed);
+ Log.i(TAG, "isVrMode: " + mIsPersistentVrModeEnabled + ", override: "
+ + mIsVrModeOverrideEnabled + ", isAllowed: " + mIsVirtualDisplayAllowed
+ + ", bootsToVr: " + mBootsToVr);
}
if (shouldRunVirtualDisplay()) {
+ Log.i(TAG, "Attempting to start virtual display");
// TODO: Consider not creating the display until ActivityManager needs one on
// which to display a 2D application.
startVirtualDisplay();
@@ -383,6 +391,12 @@
}
private boolean shouldRunVirtualDisplay() {
- return mIsVirtualDisplayAllowed && (mIsVrModeEnabled || mIsVrModeOverrideEnabled);
+ // Virtual Display should run whenever:
+ // * Virtual Display is allowed/enabled AND
+ // (1) BootsToVr is set indicating the device never leaves VR
+ // (2) VR (persistent) mode is enabled
+ // (3) VR mode is overridden to be enabled.
+ return mIsVirtualDisplayAllowed &&
+ (mBootsToVr || mIsPersistentVrModeEnabled || mIsVrModeOverrideEnabled);
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 55d4719..f13cc76 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -619,7 +619,7 @@
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
- mVr2dDisplay.init(getContext());
+ mVr2dDisplay.init(getContext(), mBootsToVr);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c98d60d..9fe7381 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1183,6 +1183,8 @@
final int dh = displayInfo.logicalHeight;
config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
Configuration.ORIENTATION_LANDSCAPE;
+ config.setRotation(displayInfo.rotation);
+
config.screenWidthDp =
(int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
config.uiMode, mDisplayId) / mDisplayMetrics.density);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ceddc4e..613c830 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -30,7 +30,6 @@
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
-import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
@@ -50,7 +49,6 @@
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -233,7 +231,6 @@
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.ThreadPriorityBooster;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -2020,8 +2017,7 @@
win.setDisplayLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement(true);
}
- result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
- oldVisibility);
+ result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
try {
result = createSurfaceControl(outSurface, result, win, winAnimator);
@@ -2159,6 +2155,15 @@
if (!win.isGoneForLayoutLw()) {
win.mResizedWhileGone = false;
}
+
+ // We must always send the latest {@link MergedConfiguration}, regardless of whether we
+ // have already reported it. The client might not have processed the previous value yet
+ // and needs process it before handling the corresponding window frame. the variable
+ // {@code mergedConfiguration} is an out parameter that will be passed back to the
+ // client over IPC and checked there.
+ win.getMergedConfiguration(mergedConfiguration);
+ win.setReportedConfiguration(mergedConfiguration);
+
outFrame.set(win.mCompatFrame);
outOverscanInsets.set(win.mOverscanInsets);
outContentInsets.set(win.mContentInsets);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f74948f..d1fbf90 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2207,8 +2207,7 @@
}
}
- void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration,
- boolean wasVisible) {
+ void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
// We need to turn on screen regardless of visibility.
if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
@@ -2230,16 +2229,16 @@
if (isDrawnLw() && mService.okToDisplay()) {
mWinAnimator.applyEnterAnimationLocked();
}
+ }
- if (isConfigChanged()) {
- final Configuration globalConfig = mService.mRoot.getConfiguration();
- final Configuration overrideConfig = getMergedOverrideConfiguration();
- mergedConfiguration.setConfiguration(globalConfig, overrideConfig);
- if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this
- + " visible with new global config: " + globalConfig
- + " merged override config: " + overrideConfig);
- mLastReportedConfiguration.setTo(getConfiguration());
- }
+ void getMergedConfiguration(MergedConfiguration outConfiguration) {
+ final Configuration globalConfig = mService.mRoot.getConfiguration();
+ final Configuration overrideConfig = getMergedOverrideConfiguration();
+ outConfiguration.setConfiguration(globalConfig, overrideConfig);
+ }
+
+ void setReportedConfiguration(MergedConfiguration config) {
+ mLastReportedConfiguration.setTo(config.getMergedConfiguration());
}
void adjustStartingWindowFlags() {
@@ -3005,14 +3004,12 @@
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
- final MergedConfiguration mergedConfiguration;
- if (isConfigChanged()) {
- mergedConfiguration = new MergedConfiguration(mService.mRoot.getConfiguration(),
- getMergedOverrideConfiguration());
- mLastReportedConfiguration.setTo(mergedConfiguration.getMergedConfiguration());
- } else {
- mergedConfiguration = null;
- }
+ final MergedConfiguration mergedConfiguration =
+ new MergedConfiguration(mService.mRoot.getConfiguration(),
+ getMergedOverrideConfiguration());
+
+ setReportedConfiguration(mergedConfiguration);
+
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
@@ -4342,8 +4339,7 @@
return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
}
- int relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges,
- int oldVisibility) {
+ int relayoutVisibleWindow(int result, int attrChanges, int oldVisibility) {
final boolean wasVisible = isVisibleLw();
result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0;
@@ -4366,7 +4362,7 @@
mWinAnimator.mEnteringAnimation = true;
- prepareWindowToDisplayDuringRelayout(mergedConfiguration, wasVisible);
+ prepareWindowToDisplayDuringRelayout(wasVisible);
if ((attrChanges & FORMAT_CHANGED) != 0) {
// If the format can't be changed in place, preserve the old surface until the app draws
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index e3ce17b..61df22e 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -29,9 +29,11 @@
import android.view.WindowManagerInternal;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
import com.android.server.display.DisplayDeviceInfo;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
+import com.android.server.lights.LightsManager;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -45,35 +47,51 @@
@SmallTest
public class DisplayManagerServiceTest extends AndroidTestCase {
- private Handler mHandler;
- private DisplayManagerService mDisplayManager;
+ private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
+ private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
+
+ private final DisplayManagerService.Injector mShortMockedInjector =
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler, DisplayAdapter.Listener listener) {
+ return mMockVirtualDisplayAdapter;
+ }
+
+ @Override
+ long getDefaultDisplayDelayTimeout() {
+ return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
+ }
+ };
+ private final DisplayManagerService.Injector mBasicInjector =
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler,
+ DisplayAdapter.Listener displayAdapterListener) {
+ return new VirtualDisplayAdapter(syncRoot, context, handler,
+ displayAdapterListener,
+ (String name, boolean secure) -> mMockDisplayToken);
+ }
+ };
+
@Mock InputManagerInternal mMockInputManagerInternal;
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
@Mock WindowManagerInternal mMockWindowManagerInternal;
+ @Mock LightsManager mMockLightsManager;
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@Mock IBinder mMockDisplayToken;
@Override
protected void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mDisplayManager = new DisplayManagerService(mContext,
- new DisplayManagerService.Injector() {
- @Override
- VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
- Handler handler, DisplayAdapter.Listener displayAdapterListener) {
- return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
- (String name, boolean secure) -> mMockDisplayToken);
- }
- });
- mHandler = mDisplayManager.getDisplayHandler();
LocalServices.removeServiceForTest(InputManagerInternal.class);
LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
-
- mDisplayManager.systemReady(false /* safeMode */, false /* onlyCore */);
- mDisplayManager.windowManagerAndInputReady();
+ LocalServices.removeServiceForTest(LightsManager.class);
+ LocalServices.addService(LightsManager.class, mMockLightsManager);
super.setUp();
}
@@ -83,8 +101,14 @@
}
public void testCreateVirtualDisplay_sentToInputManager() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.systemReady(false /* safeMode */, true /* onlyCore */);
+ displayManager.windowManagerAndInputReady();
+
// This is effectively the DisplayManager service published to ServiceManager.
- DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
String uniqueId = "uniqueId --- Test";
String uniqueIdPrefix = "virtual:" + mContext.getPackageName() + ":";
@@ -99,10 +123,10 @@
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
uniqueId);
- mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
+ displayManager.performTraversalInTransactionFromWindowManagerInternal();
// flush the handler
- mHandler.runWithScissors(() -> {}, 0 /* now */);
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
ArgumentCaptor<List<DisplayViewport>> virtualViewportCaptor =
ArgumentCaptor.forClass(List.class);
@@ -118,8 +142,12 @@
}
public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+
// This is effectively the DisplayManager service published to ServiceManager.
- DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
String uniqueId = "uniqueId --- Rotates With Content Test";
int width = 600;
@@ -133,13 +161,76 @@
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
uniqueId);
- mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
+ displayManager.performTraversalInTransactionFromWindowManagerInternal();
// flush the handler
- mHandler.runWithScissors(() -> {}, 0 /* now */);
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
- DisplayDeviceInfo ddi = mDisplayManager.getDisplayDeviceInfoInternal(displayId);
+ DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
assertNotNull(ddi);
assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
}
+
+ /**
+ * Tests that the virtual display is created along-side the default display.
+ */
+ public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ }
+
+ /**
+ * Tests that we get a Runtime exception when we cannot initialize the default display.
+ */
+ public void testStartVirtualDisplayWithDefDisplay_NoDefaultDisplay() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ Handler handler = displayManager.getDisplayHandler();
+ handler.runWithScissors(() -> {}, 0 /* now */);
+
+ try {
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ } catch (RuntimeException e) {
+ return;
+ }
+ fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
+ + " default display");
+ }
+
+ /**
+ * Tests that we get a Runtime exception when we cannot initialize the virtual display.
+ */
+ public void testStartVirtualDisplayWithDefDisplay_NoVirtualDisplayAdapter() throws Exception {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext,
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler, DisplayAdapter.Listener listener) {
+ return null; // return null for the adapter. This should cause a failure.
+ }
+
+ @Override
+ long getDefaultDisplayDelayTimeout() {
+ return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
+ }
+ });
+ try {
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ } catch (RuntimeException e) {
+ return;
+ }
+ fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
+ + " virtual display adapter");
+ }
+
+ private void registerDefaultDisplays(DisplayManagerService displayManager) {
+ Handler handler = displayManager.getDisplayHandler();
+ // Would prefer to call displayManager.onStart() directly here but it performs binderService
+ // registration which triggers security exceptions when running from a test.
+ handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
+ // flush the handler
+ handler.runWithScissors(() -> {}, 0 /* now */);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index c809c32..67db5f4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -218,8 +218,7 @@
root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
root.mTurnOnScreen = false;
- root.prepareWindowToDisplayDuringRelayout(new MergedConfiguration(),
- wasVisible /*wasVisible*/);
+ root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
assertTrue(root.mTurnOnScreen);
}
}