diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 70c9e23c6af81..f64006c3b7c4b 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -167,6 +167,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo, @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, @NonNull Handler handler) { + this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap()); + } + + LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo, + @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, + @NonNull Handler handler, DeviceStateToLayoutMap deviceStateToLayoutMap) { mSyncRoot = syncRoot; mPowerManager = context.getSystemService(PowerManager.class); mInteractive = mPowerManager.isInteractive(); @@ -181,7 +187,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray( com.android.internal.R.array.config_deviceStatesOnWhichToSleep)); mDisplayDeviceRepo.addListener(this); - mDeviceStateToLayoutMap = new DeviceStateToLayoutMap(); + mDeviceStateToLayoutMap = deviceStateToLayoutMap; } @Override @@ -369,9 +375,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // the transition is smooth. Plus, on some devices, only one internal displays can be // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be // temporarily turned off. - if (mDeviceState != DeviceStateManager.INVALID_DEVICE_STATE) { - resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION); - } + resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION); mPendingDeviceState = state; final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState, mInteractive, mBootCompleted); @@ -891,8 +895,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { newDisplay.swapDisplaysLocked(oldDisplay); } - if (!displayLayout.isEnabled()) { - setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_DISABLED); + if (displayLayout.isEnabled()) { + setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_ENABLED); } } @@ -912,7 +916,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); display.updateLocked(mDisplayDeviceRepo); mLogicalDisplays.put(displayId, display); - setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED); + setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_DISABLED); return display; } diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java index cc68ba88f76ef..2094c9345fa25 100644 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java @@ -22,6 +22,8 @@ import static android.view.Display.DEFAULT_DISPLAY_GROUP; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED; +import static com.android.server.display.LogicalDisplay.DISPLAY_PHASE_DISABLED; +import static com.android.server.display.LogicalDisplay.DISPLAY_PHASE_ENABLED; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED; @@ -53,6 +55,8 @@ import android.view.DisplayInfo; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.server.display.layout.Layout; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -85,6 +89,7 @@ public class LogicalDisplayMapperTest { @Mock Resources mResourcesMock; @Mock IPowerManager mIPowerManagerMock; @Mock IThermalService mIThermalServiceMock; + @Mock DeviceStateToLayoutMap mDeviceStateToLayoutMapMock; @Captor ArgumentCaptor mDisplayCaptor; @@ -130,11 +135,13 @@ public class LogicalDisplayMapperTest { when(mResourcesMock.getIntArray( com.android.internal.R.array.config_deviceStatesOnWhichToSleep)) .thenReturn(new int[]{0}); + when(mDeviceStateToLayoutMapMock.get(-1)).thenReturn(new Layout()); mLooper = new TestLooper(); mHandler = new Handler(mLooper.getLooper()); mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo, - mListenerMock, new DisplayManagerService.SyncRoot(), mHandler); + mListenerMock, new DisplayManagerService.SyncRoot(), mHandler, + mDeviceStateToLayoutMapMock); } @@ -413,6 +420,58 @@ public class LogicalDisplayMapperTest { /* isBootCompleted= */true)); } + @Test + public void testDeviceStateLocked() { + DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, + DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, + DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY); + + Layout layout = new Layout(); + layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, true, true); + layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, false, false); + when(mDeviceStateToLayoutMapMock.get(0)).thenReturn(layout); + + layout = new Layout(); + layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, false, false); + layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, true, true); + when(mDeviceStateToLayoutMapMock.get(1)).thenReturn(layout); + when(mDeviceStateToLayoutMapMock.get(2)).thenReturn(layout); + + LogicalDisplay display1 = add(device1); + assertEquals(info(display1).address, info(device1).address); + assertEquals(DEFAULT_DISPLAY, id(display1)); + + LogicalDisplay display2 = add(device2); + assertEquals(info(display2).address, info(device2).address); + // We can only have one default display + assertEquals(DEFAULT_DISPLAY, id(display1)); + + mLogicalDisplayMapper.setDeviceStateLocked(0, false); + mLooper.moveTimeForward(1000); + mLooper.dispatchAll(); + assertEquals(DISPLAY_PHASE_ENABLED, + mLogicalDisplayMapper.getDisplayLocked(device1).getPhase()); + assertEquals(DISPLAY_PHASE_DISABLED, + mLogicalDisplayMapper.getDisplayLocked(device2).getPhase()); + + mLogicalDisplayMapper.setDeviceStateLocked(1, false); + mLooper.moveTimeForward(1000); + mLooper.dispatchAll(); + assertEquals(DISPLAY_PHASE_DISABLED, + mLogicalDisplayMapper.getDisplayLocked(device1).getPhase()); + assertEquals(DISPLAY_PHASE_ENABLED, + mLogicalDisplayMapper.getDisplayLocked(device2).getPhase()); + + mLogicalDisplayMapper.setDeviceStateLocked(2, false); + mLooper.moveTimeForward(1000); + mLooper.dispatchAll(); + assertEquals(DISPLAY_PHASE_DISABLED, + mLogicalDisplayMapper.getDisplayLocked(device1).getPhase()); + assertEquals(DISPLAY_PHASE_ENABLED, + mLogicalDisplayMapper.getDisplayLocked(device2).getPhase()); + } + ///////////////// // Helper Methods /////////////////