Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc5d9eb5 authored by Santos Cordon's avatar Santos Cordon Committed by android-build-merger
Browse files

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

am: b8a17cde

Change-Id: Ic0fe241ee3bea23816baea9523f89e4845626c68
parents 5e8651c1 b8a17cde
Loading
Loading
Loading
Loading
+30 −18
Original line number Diff line number Diff line
@@ -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:
+30 −16
Original line number Diff line number Diff line
@@ -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);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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);
+113 −22
Original line number Diff line number Diff line
@@ -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 */);
    }
}