diff options
| author | 2017-06-30 17:18:54 +0000 | |
|---|---|---|
| committer | 2017-06-30 17:18:54 +0000 | |
| commit | 2d85fca9daf25d408e5dbd9c4272c15f84d52d7c (patch) | |
| tree | 879da667a2dc7fd646f088ace3d3f8ed6c1594de | |
| parent | 5e8651c1958916f3e6763c0be93e5a87b74beaa3 (diff) | |
| parent | b8a17cde7e069e385d507ea2147b7e3320aa1e3a (diff) | |
Merge "Always run Virtual Display when in a BootsToVR device." into oc-dr1-dev
am: b8a17cde7e
Change-Id: Ic21bfaafead58f0c3ce7f0d206de235890636039
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 */); + } } |