summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shivangi Dubey <dshivangi@google.com> 2024-04-03 09:19:31 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-04-03 09:19:31 +0000
commit9acf675d137e6d5289d6903e844ef03dc8a8b72d (patch)
tree6c7a3aedccaf78fa77d310447deef85361686795
parenta68db76dcca5b30694cdbf94469b62268c2c43f2 (diff)
parentb204db1ed08ec5d697a471289d8017bb3d2bd950 (diff)
Merge "Selectively expect device to stay awake on fold" into 24D1-dev
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java3
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java40
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java225
3 files changed, 256 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ad89444edcfd..28664dd66c19 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -145,6 +145,7 @@ import android.window.ScreenCapture;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.foldables.FoldGracePeriodProvider;
import com.android.internal.foldables.FoldLockSettingAvailabilityProvider;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
@@ -573,7 +574,7 @@ public final class DisplayManagerService extends SystemService {
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
- foldSettingProvider,
+ foldSettingProvider, new FoldGracePeriodProvider(),
mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler, mFlags);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext,
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 2e8de31f2af1..86afa9b0630e 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -40,6 +40,7 @@ import android.view.DisplayAddress;
import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.foldables.FoldGracePeriodProvider;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
@@ -120,7 +121,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
/**
* Sleep the device when transitioning into these device state.
*/
- private final SparseBooleanArray mDeviceStatesOnWhichToSleep;
+ private final SparseBooleanArray mDeviceStatesOnWhichToSelectiveSleep;
/**
* Map of all logical displays indexed by logical display id.
@@ -153,6 +154,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final DisplayManagerService.SyncRoot mSyncRoot;
private final LogicalDisplayMapperHandler mHandler;
private final FoldSettingProvider mFoldSettingProvider;
+ private final FoldGracePeriodProvider mFoldGracePeriodProvider;
private final PowerManager mPowerManager;
/**
@@ -200,15 +202,18 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final DisplayManagerFlags mFlags;
LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ FoldGracePeriodProvider foldGracePeriodProvider,
@NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler, DisplayManagerFlags flags) {
- this(context, foldSettingProvider, repo, listener, syncRoot, handler,
+ this(context, foldSettingProvider, foldGracePeriodProvider, repo, listener, syncRoot,
+ handler,
new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
: sNextNonDefaultDisplayId++, flags), flags);
}
LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ FoldGracePeriodProvider foldGracePeriodProvider,
@NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap,
@@ -220,13 +225,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mDisplayDeviceRepo = repo;
mListener = listener;
mFoldSettingProvider = foldSettingProvider;
+ mFoldGracePeriodProvider = foldGracePeriodProvider;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
mDeviceStatesOnWhichToWakeUp = toSparseBooleanArray(context.getResources().getIntArray(
com.android.internal.R.array.config_deviceStatesOnWhichToWakeUp));
- mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
- com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
+ mDeviceStatesOnWhichToSelectiveSleep = toSparseBooleanArray(
+ context.getResources().getIntArray(
+ com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
mDisplayDeviceRepo.addListener(this);
mDeviceStateToLayoutMap = deviceStateToLayoutMap;
mFlags = flags;
@@ -403,7 +410,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
ipw.println("mCurrentLayout=" + mCurrentLayout);
ipw.println("mDeviceStatesOnWhichToWakeUp=" + mDeviceStatesOnWhichToWakeUp);
- ipw.println("mDeviceStatesOnWhichToSleep=" + mDeviceStatesOnWhichToSleep);
+ ipw.println("mDeviceStatesOnWhichSelectiveSleep=" + mDeviceStatesOnWhichToSelectiveSleep);
ipw.println("mInteractive=" + mInteractive);
ipw.println("mBootCompleted=" + mBootCompleted);
@@ -569,8 +576,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isOverrideActive,
boolean isInteractive, boolean isBootCompleted) {
return currentState != DeviceStateManager.INVALID_DEVICE_STATE
- && mDeviceStatesOnWhichToSleep.get(pendingState)
- && !mDeviceStatesOnWhichToSleep.get(currentState)
+ && mDeviceStatesOnWhichToSelectiveSleep.get(pendingState)
+ && !mDeviceStatesOnWhichToSelectiveSleep.get(currentState)
&& !isOverrideActive
&& isInteractive && isBootCompleted
&& !mFoldSettingProvider.shouldStayAwakeOnFold();
@@ -611,9 +618,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
final boolean waitingToWakeDevice = mDeviceStatesOnWhichToWakeUp.get(mPendingDeviceState)
&& !mDeviceStatesOnWhichToWakeUp.get(mDeviceState)
&& !mInteractive && mBootCompleted;
- final boolean waitingToSleepDevice = mDeviceStatesOnWhichToSleep.get(mPendingDeviceState)
- && !mDeviceStatesOnWhichToSleep.get(mDeviceState)
- && mInteractive && mBootCompleted;
+ // The device should only wait for sleep if #shouldStayAwakeOnFold method returns false.
+ // If not, device should be marked ready for transition immediately.
+ final boolean waitingToSleepDevice = mDeviceStatesOnWhichToSelectiveSleep.get(
+ mPendingDeviceState)
+ && !mDeviceStatesOnWhichToSelectiveSleep.get(mDeviceState)
+ && mInteractive && mBootCompleted && !shouldStayAwakeOnFold();
final boolean displaysOff = areAllTransitioningDisplaysOffLocked();
final boolean isReadyToTransition = displaysOff && !waitingToWakeDevice
@@ -1231,6 +1241,16 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
return retval;
}
+ /**
+ * Returns true if the device would definitely have outer display ON/Stay Awake on fold based on
+ * the value of `Continue using app on fold` setting
+ */
+ private boolean shouldStayAwakeOnFold() {
+ return mFoldSettingProvider.shouldStayAwakeOnFold() || (
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold()
+ && mFoldGracePeriodProvider.isEnabled());
+ }
+
private String displayEventToString(int msg) {
switch(msg) {
case LOGICAL_DISPLAY_EVENT_ADDED:
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index bed6f928a55c..357999ab65c9 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -20,6 +20,8 @@ import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STA
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY_GROUP;
import static android.view.Display.FLAG_REAR;
+import static android.view.Display.STATE_OFF;
+import static android.view.Display.STATE_ON;
import static android.view.Display.TYPE_EXTERNAL;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.Display.TYPE_VIRTUAL;
@@ -28,6 +30,7 @@ import static com.android.server.display.DeviceStateToLayoutMap.STATE_DEFAULT;
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.DisplayDeviceInfo.DIFF_EVERYTHING;
import static com.android.server.display.DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED;
import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CONNECTED;
@@ -35,6 +38,9 @@ import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EV
import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED;
import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
import static com.android.server.display.layout.Layout.Display.POSITION_UNKNOWN;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SELECTIVE_STAY_AWAKE;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SLEEP_ON_FOLD;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_STAY_AWAKE_ON_FOLD;
import static com.google.common.truth.Truth.assertThat;
@@ -72,6 +78,7 @@ import android.view.DisplayInfo;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.foldables.FoldGracePeriodProvider;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
@@ -96,9 +103,13 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class LogicalDisplayMapperTest {
private static int sUniqueTestDisplayId = 0;
+ private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500;
+ private static final int FOLD_SETTLE_DELAY = 1000;
private static final int DEVICE_STATE_CLOSED = 0;
+ private static final int DEVICE_STATE_HALF_OPEN = 1;
private static final int DEVICE_STATE_OPEN = 2;
private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
+ private static final int FLAG_GO_TO_SLEEP_FLAG_SOFT_SLEEP = 2;
private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
@@ -116,6 +127,7 @@ public class LogicalDisplayMapperTest {
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
@Mock FoldSettingProvider mFoldSettingProviderMock;
+ @Mock FoldGracePeriodProvider mFoldGracePeriodProvider;
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
@@ -160,6 +172,7 @@ public class LogicalDisplayMapperTest {
.thenReturn(Context.POWER_SERVICE);
when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSelectiveStayAwakeOnFold()).thenReturn(true);
when(mIPowerManagerMock.isInteractive()).thenReturn(true);
when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
@@ -177,6 +190,7 @@ public class LogicalDisplayMapperTest {
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
+ mFoldGracePeriodProvider,
mDisplayDeviceRepo,
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
mDeviceStateToLayoutMapSpy, mFlagsMock);
@@ -694,22 +708,147 @@ public class LogicalDisplayMapperTest {
when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
finishBootAndFoldDevice();
+ advanceTime(FOLD_SETTLE_DELAY);
verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
eq(FLAG_GO_TO_SLEEP_ON_FOLD));
}
@Test
+ public void testDeviceShouldPutToSleepWhenFoldSettingSelective() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSelectiveStayAwakeOnFold()).thenReturn(true);
+
+ finishBootAndFoldDevice();
+ advanceTime(FOLD_SETTLE_DELAY);
+
+ verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_FLAG_SOFT_SLEEP));
+ }
+
+ @Test
public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
finishBootAndFoldDevice();
+ advanceTime(FOLD_SETTLE_DELAY);
verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
eq(FLAG_GO_TO_SLEEP_ON_FOLD));
}
@Test
+ public void testWaitForSleepWhenFoldSettingSleep() {
+ // Test device should not be marked ready for transition immediately, when 'Continue
+ // using app on fold' set to 'Never'
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ foldableDisplayDevices.mInner.setState(STATE_OFF);
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+
+ assertDisplayDisabled(foldableDisplayDevices.mOuter);
+ assertDisplayEnabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testSwapDeviceStateWithDelayWhenFoldSettingSleep() {
+ // Test device should be marked ready for transition after a delay when 'Continue using
+ // app on fold' set to 'Never'
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ foldableDisplayDevices.mInner.setState(STATE_OFF);
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+ advanceTime(TIMEOUT_STATE_TRANSITION_MILLIS);
+
+ assertDisplayEnabled(foldableDisplayDevices.mOuter);
+ assertDisplayDisabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testDoNotWaitForSleepWhenFoldSettingStayAwake() {
+ // Test device should be marked ready for transition immediately when 'Continue using app
+ // on fold' set to 'Always'
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ foldableDisplayDevices.mInner.setState(STATE_OFF);
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+
+ assertDisplayEnabled(foldableDisplayDevices.mOuter);
+ assertDisplayDisabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testDoNotWaitForSleepWhenFoldSettingSelectiveStayAwake() {
+ // Test device should be marked ready for transition immediately when 'Continue using app
+ // on fold' set to 'Swipe up to continue'
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ setGracePeriodAvailability(true);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ foldableDisplayDevices.mInner.setState(STATE_OFF);
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+
+ assertDisplayEnabled(foldableDisplayDevices.mOuter);
+ assertDisplayDisabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testWaitForSleepWhenGracePeriodSettingDisabled() {
+ // Test device should not be marked ready for transition immediately when 'Continue using
+ // app on fold' set to 'Swipe up to continue' but Grace Period flag is disabled
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ foldableDisplayDevices.mInner.setState(STATE_OFF);
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+
+ assertDisplayDisabled(foldableDisplayDevices.mOuter);
+ assertDisplayEnabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testWaitForSleepWhenTransitionDisplayStaysOn() {
+ // Test device should not be marked ready for transition immediately, when 'Continue
+ // using app on fold' set to 'Always' but not all transitioning displays are OFF.
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+
+ assertDisplayDisabled(foldableDisplayDevices.mOuter);
+ assertDisplayEnabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
+ public void testSwapDeviceStateWithDelayWhenTransitionDisplayStaysOn() {
+ // Test device should be marked ready for transition after a delay, when 'Continue using
+ // app on fold' set to 'Never' but not all transitioning displays are OFF.
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ setGracePeriodAvailability(false);
+ FoldableDisplayDevices foldableDisplayDevices = createFoldableDeviceStateToLayoutMap();
+
+ finishBootAndFoldDevice();
+ notifyDisplayChanges(foldableDisplayDevices.mOuter);
+ advanceTime(TIMEOUT_STATE_TRANSITION_MILLIS);
+
+ assertDisplayEnabled(foldableDisplayDevices.mOuter);
+ assertDisplayDisabled(foldableDisplayDevices.mInner);
+ }
+
+ @Test
public void testDeviceStateLocked() {
DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -963,13 +1102,77 @@ public class LogicalDisplayMapperTest {
// Helper Methods
/////////////////
+ private void setGracePeriodAvailability(boolean isGracePeriodEnabled) {
+ when(mFoldGracePeriodProvider.isEnabled()).thenReturn(isGracePeriodEnabled);
+ }
+
+ private void setFoldLockBehaviorSettingValue(String foldLockBehaviorSettingValue) {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSelectiveStayAwakeOnFold()).thenReturn(false);
+
+ switch (foldLockBehaviorSettingValue) {
+ case SETTING_VALUE_STAY_AWAKE_ON_FOLD:
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
+ break;
+
+ case SETTING_VALUE_SLEEP_ON_FOLD:
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
+ break;
+
+ default:
+ when(mFoldSettingProviderMock.shouldSelectiveStayAwakeOnFold()).thenReturn(true);
+ break;
+ }
+ }
+
+ private FoldableDisplayDevices createFoldableDeviceStateToLayoutMap() {
+ TestDisplayDevice outer = createDisplayDevice(TYPE_INTERNAL, 600, 800,
+ FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ TestDisplayDevice inner = createDisplayDevice(TYPE_INTERNAL, 600, 800,
+ FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ outer.setState(STATE_OFF);
+ inner.setState(STATE_ON);
+
+ Layout layout = new Layout();
+ createDefaultDisplay(layout, outer);
+ createNonDefaultDisplay(layout, inner, /* enabled= */ false, /* group= */ null);
+ when(mDeviceStateToLayoutMapSpy.get(DEVICE_STATE_CLOSED)).thenReturn(layout);
+
+ layout = new Layout();
+ createNonDefaultDisplay(layout, outer, /* enabled= */ false, /* group= */ null);
+ createDefaultDisplay(layout, inner);
+ when(mDeviceStateToLayoutMapSpy.get(DEVICE_STATE_HALF_OPEN)).thenReturn(layout);
+ when(mDeviceStateToLayoutMapSpy.get(DEVICE_STATE_OPEN)).thenReturn(layout);
+ when(mDeviceStateToLayoutMapSpy.size()).thenReturn(4);
+
+ add(outer);
+ add(inner);
+
+ return new FoldableDisplayDevices(outer, inner);
+ }
+
private void finishBootAndFoldDevice() {
mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
+ mLogicalDisplayMapper.onEarlyInteractivityChange(true);
advanceTime(1000);
mLogicalDisplayMapper.onBootCompleted();
advanceTime(1000);
mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
- advanceTime(1000);
+ }
+
+ private void notifyDisplayChanges(TestDisplayDevice displayDevice) {
+ mLogicalDisplayMapper.onDisplayDeviceChangedLocked(displayDevice, DIFF_EVERYTHING);
+ }
+
+ private void assertDisplayEnabled(DisplayDevice displayDevice) {
+ assertThat(
+ mLogicalDisplayMapper.getDisplayLocked(displayDevice).isEnabledLocked()).isTrue();
+ }
+
+ private void assertDisplayDisabled(DisplayDevice displayDevice) {
+ assertThat(
+ mLogicalDisplayMapper.getDisplayLocked(displayDevice).isEnabledLocked()).isFalse();
}
private void createDefaultDisplay(Layout layout, DisplayDevice device) {
@@ -1071,6 +1274,16 @@ public class LogicalDisplayMapperTest {
assertNotEquals(DEFAULT_DISPLAY, id(displayRemoved));
}
+ private final static class FoldableDisplayDevices {
+ final TestDisplayDevice mOuter;
+ final TestDisplayDevice mInner;
+
+ FoldableDisplayDevices(TestDisplayDevice outer, TestDisplayDevice inner) {
+ this.mOuter = outer;
+ this.mInner = inner;
+ }
+ }
+
class TestDisplayDevice extends DisplayDevice {
private DisplayDeviceInfo mInfo;
private DisplayDeviceInfo mSentInfo;
@@ -1096,6 +1309,16 @@ public class LogicalDisplayMapperTest {
mSentInfo = null;
}
+ public void setState(int state) {
+ mState = state;
+ if (mSentInfo == null) {
+ mInfo.state = state;
+ } else {
+ mInfo.state = state;
+ mSentInfo.state = state;
+ }
+ }
+
@Override
public boolean hasStableUniqueId() {
return true;