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

Commit b3d7acd0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Manage wallpaper connections on display changes" into main

parents 4c7c3b87 f5c8e3e1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:colorBackground">@*android:color/background_material_dark</item>
        <item name="android:colorBackground">@android:color/transparent</item>
    </style>

    <style name="TextAppearance.Keyguard">
+4 −0
Original line number Diff line number Diff line
@@ -91,6 +91,10 @@ constructor(
        super.onCreate(savedInstanceState)

        onCreateV2()
        val window = window ?: return
        val layoutParams = window.attributes
        layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
        window.attributes = layoutParams
    }

    fun onCreateV2() {
+103 −24
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.Flags.enableConnectedDisplaysWallpaper;
import static android.app.Flags.fixWallpaperChanged;
import static android.app.Flags.liveWallpaperContentHandling;
import static android.app.Flags.removeNextWallpaperComponent;
@@ -89,6 +90,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.multiuser.Flags;
import android.os.Binder;
import android.os.Bundle;
@@ -655,8 +657,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
    private final MyPackageMonitor mMonitor;
    private final AppOpsManager mAppOpsManager;

    private final DisplayManager.DisplayListener mDisplayListener =
            new DisplayManager.DisplayListener() {
    private final DisplayListener mDisplayListener = new DisplayListener() {

        @Override
        public void onDisplayAdded(int displayId) {
@@ -665,24 +666,64 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        @Override
        public void onDisplayRemoved(int displayId) {
            synchronized (mLock) {
                if (enableConnectedDisplaysWallpaper()) {
                    // There could be at most 2 wallpaper connections per display:
                    // 1. system & lock are the same: mLastWallpaper
                    // 2. system, lock are different: mLastWallpaper, mLastLockWallpaper
                    // 3. fallback used as both system & lock wallpaper: mFallbackWallpaper
                    // 4. fallback used as lock only wallpaper: mFallbackWallpaper,
                    //    mLastWallpaper
                    // 5. fallback used as system only wallpaper: mFallbackWallpaper,
                    //    mLastLockWallpaper
                    List<WallpaperData> pendingDisconnectWallpapers = new ArrayList<>();
                    if (mLastWallpaper != null && mLastWallpaper.connection != null
                            && mLastWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mLastWallpaper);
                    }
                    if (mLastLockWallpaper != null && mLastLockWallpaper.connection != null
                            && mLastLockWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mLastLockWallpaper);
                    }
                    if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
                            && mFallbackWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mFallbackWallpaper);
                    }
                    for (int i = 0; i < pendingDisconnectWallpapers.size(); i++) {
                        WallpaperData wallpaper = pendingDisconnectWallpapers.get(i);
                        DisplayConnector displayConnector =
                                wallpaper.connection.getDisplayConnectorOrCreate(displayId);
                        if (displayConnector == null) {
                            Slog.w(TAG,
                                    "Fail to disconnect wallpaper upon display removal");
                            return;
                        }
                        displayConnector.disconnectLocked(wallpaper.connection);
                        wallpaper.connection.removeDisplayConnector(displayId);
                    }
                } else {
                    if (mLastWallpaper != null) {
                        WallpaperData targetWallpaper = null;
                    if (mLastWallpaper.connection != null &&
                            mLastWallpaper.connection.containsDisplay(displayId)) {
                        if (mLastWallpaper.connection != null
                                && mLastWallpaper.connection.containsDisplay(displayId)) {
                            targetWallpaper = mLastWallpaper;
                    } else if (mFallbackWallpaper != null &&
                            mFallbackWallpaper.connection != null &&
                            mFallbackWallpaper.connection.containsDisplay(displayId)) {
                        } else if (mFallbackWallpaper != null
                                && mFallbackWallpaper.connection != null
                                && mFallbackWallpaper.connection.containsDisplay(
                                displayId)) {
                            targetWallpaper = mFallbackWallpaper;
                        }
                        if (targetWallpaper == null) return;
                        DisplayConnector connector =
                            targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
                                targetWallpaper.connection.getDisplayConnectorOrCreate(
                                        displayId);
                        if (connector == null) return;
                        connector.disconnectLocked(targetWallpaper.connection);
                        targetWallpaper.connection.removeDisplayConnector(displayId);
                    mWallpaperDisplayHelper.removeDisplayData(displayId);
                    }
                }

                mWallpaperDisplayHelper.removeDisplayData(displayId);

                for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
                    final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
                            mColorsChangedListeners.valueAt(i);
@@ -1627,6 +1668,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        public void onScreenTurnedOn(int displayId) {
            notifyScreenTurnedOn(displayId);
        }

        @Override
        public void onScreenTurningOn(int displayId) {
            notifyScreenTurningOn(displayId);
@@ -3707,6 +3749,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        }
        if (newWallpaper.mWhich == (FLAG_SYSTEM | FLAG_LOCK)) {
            mLastWallpaper = newWallpaper;
            mLastLockWallpaper = null;
        } else if (newWallpaper.mWhich == FLAG_SYSTEM) {
            mLastWallpaper = newWallpaper;
        } else if (newWallpaper.mWhich == FLAG_LOCK) {
@@ -3916,6 +3959,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            if (mLastWallpaper == null) {
                return;
            }
            if (enableConnectedDisplaysWallpaper()) {
                int useFallbackWallpaperWhich = 0;
                List<WallpaperData> wallpapers = new ArrayList<>();
                wallpapers.add(mLastWallpaper);
                // If the system and the lock wallpapers are not the same, we should also
                // establish a display connector to the lock wallpaper for this display.
                if (mLastLockWallpaper != null && mLastWallpaper != mLastLockWallpaper) {
                    wallpapers.add(mLastLockWallpaper);
                }

                for (int i = 0; i < wallpapers.size(); i++) {
                    WallpaperData wallpaper = wallpapers.get(i);
                    if (supportsMultiDisplay(wallpaper.connection)) {
                        final DisplayConnector connector =
                                wallpaper.connection.getDisplayConnectorOrCreate(displayId);
                        if (connector != null) {
                            connector.connectLocked(wallpaper.connection, wallpaper);
                        } else {
                            Slog.w(TAG, "Fail to connect to wallpaper for display id " + displayId
                                    + " due to null connector. Use fallback wallpaper.");
                            useFallbackWallpaperWhich |= wallpaper.mWhich;
                        }
                    } else {
                        useFallbackWallpaperWhich |= wallpaper.mWhich;
                    }
                }

                if (useFallbackWallpaperWhich == 0
                        || mFallbackWallpaper == null
                        || mFallbackWallpaper.connection == null) {
                    return;
                }
                mFallbackWallpaper.mWhich = useFallbackWallpaperWhich;
            } else {
                if (supportsMultiDisplay(mLastWallpaper.connection)) {
                    final DisplayConnector connector =
                            mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
@@ -3923,6 +4000,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                    connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
                    return;
                }
            }

            // System wallpaper does not support multiple displays, attach this display to
            // the fallback wallpaper.
            if (mFallbackWallpaper != null && mFallbackWallpaper
+256 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
@@ -65,6 +66,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
import android.graphics.Color;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -75,6 +77,7 @@ import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
import android.service.wallpaper.WallpaperService;
import android.testing.TestableContext;
import android.util.Log;
@@ -105,6 +108,7 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.quality.Strictness;
@@ -154,6 +158,8 @@ public class WallpaperManagerServiceTests {
    private WallpaperManagerService mService;
    private static IWallpaperConnection.Stub sWallpaperService;

    private static WindowManagerInternal sWindowManagerInternal;

    @BeforeClass
    public static void setUpClass() {
        sMockitoSession = mockitoSession()
@@ -163,8 +169,8 @@ public class WallpaperManagerServiceTests {
                .spyStatic(WallpaperManager.class)
                .startMocking();

        final WindowManagerInternal dmi = mock(WindowManagerInternal.class);
        LocalServices.addService(WindowManagerInternal.class, dmi);
        sWindowManagerInternal = mock(WindowManagerInternal.class);
        LocalServices.addService(WindowManagerInternal.class, sWindowManagerInternal);

        sContext.addMockSystemService(Context.APP_OPS_SERVICE, mock(AppOpsManager.class));

@@ -335,6 +341,43 @@ public class WallpaperManagerServiceTests {
        verifyCurrentSystemData(testUserId);
    }

    /**
     * Test setWallpaperComponent with FLAG_LOCK should update the mLastLockWallpaper.
     */
    @Test
    public void testSetLockWallpaper() {
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
        verifyCurrentSystemData(testUserId);

        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK, testUserId);
        verifyLastLockWallpaperData(testUserId, sImageWallpaperComponentName);
        verifyCurrentSystemData(testUserId);
    }

    /**
     * Test setWallpaperComponent with FLAG_LOCK and then setWallpaperComponent with
     * FLAG_LOCK | FLAG_SYSTEM should set mLastLockWallpaper to null.
     */
    @Test
    public void testSetLockWallpaperThenSetLockAndSystemWallpaper_setLastLockWallpaperToNull() {
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
        verifyCurrentSystemData(testUserId);

        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK, testUserId);
        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK | FLAG_SYSTEM, testUserId);

        verifyLastWallpaperData(testUserId, sImageWallpaperComponentName);
        assertThat(mService.mLastLockWallpaper).isNull();
        verifyCurrentSystemData(testUserId);
    }

    /**
     * Tests that when setWallpaperComponent is called with the currently set component, a command
     * is issued to the wallpaper.
@@ -661,6 +704,171 @@ public class WallpaperManagerServiceTests {
        assertPfdAndFileContentsEqual(pfd, originalSystemWallpaperFile);
    }

    // Verify a secondary display added started
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayAdded_sameSystemAndLockWallpaper_shouldAttachWallpaperServiceOnce()
            throws Exception {
        // GIVEN the same wallpaper used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        wallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));

        // WHEN displayId, 2, is ready.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);

        // Then there is a connection established for the system & lock wallpaper for display ID, 2.
        verify(mockIWallpaperService).attach(
                /* connection= */ eq(wallpaper.connection),
                /* windowToken= */ any(),
                /* windowType= */ anyInt(),
                /* isPreview= */ anyBoolean(),
                /* reqWidth= */ anyInt(),
                /* reqHeight= */ anyInt(),
                /* padding= */ any(),
                /* displayId= */ eq(testDisplayId),
                /* which= */ eq(FLAG_SYSTEM | FLAG_LOCK),
                /* info= */ any(),
                /* description= */ any());
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayAdded_differentSystemAndLockWallpapers_shouldAttachWallpaperServiceTwice()
            throws Exception {
        // GIVEN different wallpapers used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK, testUserId);
        final WallpaperData systemWallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM,
                testUserId);
        final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK,
                testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        systemWallpaper.connection.mService = mockIWallpaperService;
        lockWallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));

        // WHEN displayId, 2, is ready.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);

        // Then there is a connection established for the system wallpaper for display ID, 2.
        verify(mockIWallpaperService).attach(
                /* connection= */ eq(systemWallpaper.connection),
                /* windowToken= */ any(),
                /* windowType= */ anyInt(),
                /* isPreview= */ anyBoolean(),
                /* reqWidth= */ anyInt(),
                /* reqHeight= */ anyInt(),
                /* padding= */ any(),
                /* displayId= */ eq(testDisplayId),
                /* which= */ eq(FLAG_SYSTEM),
                /* info= */ any(),
                /* description= */ any());
        // Then there is a connection established for the lock wallpaper for display ID, 2.
        verify(mockIWallpaperService).attach(
                /* connection= */ eq(lockWallpaper.connection),
                /* windowToken= */ any(),
                /* windowType= */ anyInt(),
                /* isPreview= */ anyBoolean(),
                /* reqWidth= */ anyInt(),
                /* reqHeight= */ anyInt(),
                /* padding= */ any(),
                /* displayId= */ eq(testDisplayId),
                /* which= */ eq(FLAG_LOCK),
                /* info= */ any(),
                /* description= */ any());
    }
    // Verify a secondary display added end

    // Verify a secondary display removed started
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayRemoved_sameSystemAndLockWallpaper_shouldDetachWallpaperServiceOnce()
            throws Exception {
        ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass(
                DisplayListener.class);
        verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null));
        // GIVEN the same wallpaper used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        wallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
        // GIVEN wallpaper connections have been established for displayID, 2.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);
        // Save displayConnector for displayId 2 before display removal.
        WallpaperManagerService.DisplayConnector displayConnector =
                wallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);

        // WHEN displayId, 2, is removed.
        DisplayListener displayListener = displayListenerCaptor.getValue();
        displayListener.onDisplayRemoved(testDisplayId);

        // Then the wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(displayConnector.mToken));
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayRemoved_differentSystemAndLockWallpapers_shouldDetachWallpaperServiceTwice()
            throws Exception {
        ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass(
                DisplayListener.class);
        verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null));
        // GIVEN different wallpapers used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK, testUserId);
        final WallpaperData systemWallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM,
                testUserId);
        final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK,
                testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        systemWallpaper.connection.mService = mockIWallpaperService;
        lockWallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
        // GIVEN wallpaper connections have been established for displayID, 2.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);
        // Save displayConnectors for displayId 2 before display removal.
        WallpaperManagerService.DisplayConnector systemWallpaperDisplayConnector =
                systemWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
        WallpaperManagerService.DisplayConnector lockWallpaperDisplayConnector =
                lockWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);

        // WHEN displayId, 2, is removed.
        DisplayListener displayListener = displayListenerCaptor.getValue();
        displayListener.onDisplayRemoved(testDisplayId);

        // Then the system wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(systemWallpaperDisplayConnector.mToken));
        // Then the lock wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(lockWallpaperDisplayConnector.mToken));
    }
    // Verify a secondary display removed ended

    // Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
    // non-current user must not bind to wallpaper service.
    private void verifyNoConnectionBeforeLastUser(int lastUserId) {
@@ -681,11 +889,31 @@ public class WallpaperManagerServiceTests {
                lastData.connection);
    }

    private void verifyLastLockWallpaperData(int lastUserId, ComponentName expectedComponent) {
        final WallpaperData lastLockData = mService.mLastLockWallpaper;
        assertWithMessage("Last wallpaper must not be null").that(lastLockData).isNotNull();
        assertWithMessage("Last wallpaper component must be equals.")
                .that(expectedComponent)
                .isEqualTo(lastLockData.getComponent());
        assertWithMessage("The user id in last wallpaper should be the last switched user")
                .that(lastUserId)
                .isEqualTo(lastLockData.userId);
        assertWithMessage("Must exist user data connection on last wallpaper data")
                .that(lastLockData.connection)
                .isNotNull();
    }

    private void verifyCurrentSystemData(int userId) {
        final WallpaperData lastData = mService.mLastWallpaper;
        final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, userId);
        assertEquals("Last wallpaper should be equals to current system wallpaper",
                lastData, wallpaper);

        final WallpaperData lastLockData = mService.mLastLockWallpaper;
        final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK, userId);
        assertWithMessage("Last lock wallpaper should be equals to current lock wallpaper")
                .that(lastLockData)
                .isEqualTo(lockWallpaper);
    }

    private void verifyDisplayData() {
@@ -697,6 +925,32 @@ public class WallpaperManagerServiceTests {
        });
    }

    /**
     * Sets up mock displays for testing.
     *
     * <p>This method creates mock {@link Display} objects and configures the {@link DisplayManager}
     * to return them. It also sets up the {@link WindowManagerInternal} to indicate that all
     * displays support home.
     *
     * @param displayIds A list of display IDs to create mock displays for.
     */
    private void setUpDisplays(List<Integer> displayIds) {
        doReturn(true).when(sWindowManagerInternal).isHomeSupportedOnDisplay(anyInt());

        Display[] mockDisplays = new Display[displayIds.size()];
        for (int i = 0; i < displayIds.size(); i++) {
            final int displayId = displayIds.get(i);
            final Display mockDisplay = mock(Display.class);
            mockDisplays[i] = mockDisplay;
            doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension();
            doReturn(mockDisplay).when(mDisplayManager).getDisplay(eq(displayId));
            doReturn(displayId).when(mockDisplay).getDisplayId();
            doReturn(true).when(mockDisplay).hasAccess(anyInt());
        }

        doReturn(mockDisplays).when(mDisplayManager).getDisplays();
    }

    /**
     * Asserts that the contents of the given {@link ParcelFileDescriptor} and {@link File} contain
     * exactly the same bytes.