summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Santos Cordon <santoscordon@google.com> 2017-06-30 17:18:54 +0000
committer android-build-merger <android-build-merger@google.com> 2017-06-30 17:18:54 +0000
commit2d85fca9daf25d408e5dbd9c4272c15f84d52d7c (patch)
tree879da667a2dc7fd646f088ace3d3f8ed6c1594de
parent5e8651c1958916f3e6763c0be93e5a87b74beaa3 (diff)
parentb8a17cde7e069e385d507ea2147b7e3320aa1e3a (diff)
Merge "Always run Virtual Display when in a BootsToVR device." into oc-dr1-dev
am: b8a17cde7e Change-Id: Ic21bfaafead58f0c3ce7f0d206de235890636039
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java48
-rw-r--r--services/core/java/com/android/server/vr/Vr2dDisplay.java46
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java135
4 files changed, 174 insertions, 57 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ab3aff99937d..8269042da24a 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 @@ public final class DisplayManagerService extends SystemService {
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 @@ public final class DisplayManagerService extends SystemService {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
-
}
public void setupSchedulerPolicies() {
@@ -284,9 +283,9 @@ public final class DisplayManagerService extends SystemService {
// 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 final class DisplayManagerService extends SystemService {
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 @@ public final class DisplayManagerService extends SystemService {
}
}
- 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 @@ public final class DisplayManagerService extends SystemService {
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
registerOverlayDisplayAdapterLocked();
registerWifiDisplayAdapterLocked();
- registerVirtualDisplayAdapterLocked();
}
}
}
@@ -719,12 +733,6 @@ public final class DisplayManagerService extends SystemService {
}
}
- 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 @@ public final class DisplayManagerService extends SystemService {
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 @@ public final class DisplayManagerService extends SystemService {
@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 fa98f1744393..b1c1df14feeb 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 @@ class Vr2dDisplay {
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 @@ class Vr2dDisplay {
/**
* 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 @@ class Vr2dDisplay {
new IPersistentVrStateCallbacks.Stub() {
@Override
public void onPersistentVrStateChanged(boolean enabled) {
- if (enabled != mIsVrModeEnabled) {
- mIsVrModeEnabled = enabled;
+ if (enabled != mIsPersistentVrModeEnabled) {
+ mIsPersistentVrModeEnabled = enabled;
updateVirtualDisplay();
}
}
@@ -98,26 +97,33 @@ class Vr2dDisplay {
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 @@ class Vr2dDisplay {
*/
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 @@ class Vr2dDisplay {
}
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 55d471919099..f13cc76577c8 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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
(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/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index e3ce17bcd2d8..61df22ecda9c 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.SurfaceControl;
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 @@ import static org.mockito.Mockito.when;
@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 class DisplayManagerServiceTest extends AndroidTestCase {
}
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 @@ public class DisplayManagerServiceTest extends AndroidTestCase {
"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 class DisplayManagerServiceTest extends AndroidTestCase {
}
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 @@ public class DisplayManagerServiceTest extends AndroidTestCase {
"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 */);
+ }
}