Merge "Always run Virtual Display when in a BootsToVR device." into oc-dr1-dev

This commit is contained in:
Santos Cordon
2017-06-30 17:09:09 +00:00
committed by Android (Google) Code Review
4 changed files with 174 additions and 57 deletions

View File

@@ -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:

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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 */);
}
}