diff options
author | 2024-03-08 14:01:53 +0000 | |
---|---|---|
committer | 2024-03-13 11:29:42 +0000 | |
commit | 0b2851736f16ccb8db4467da39f485a63d377df0 (patch) | |
tree | 92f0c0a487feb1758070440ce779851e4a6c8a04 | |
parent | 1745193e5af373170102df7176f17b8ecaf3f119 (diff) |
Connected displays wait for boot complete
Sending display "connected" for external display
too early during boot may result into
ExternalDisplayStatsService won't be able to
register listeners due to other services
for example ActivityManager may not be available
so early in the boot. Also, there is a problem
with disabling display early in the boot which
results into display not possible to re-enable
upon user click on Mirror dialog.
This CL postpones the disabling the connected
display together with initializing ExternalDisplay
StatsService until boot completes.
Change-Id: I472a82cfe8db01b644b14c05bab90f1de91818e8
Bug: 328463830
Bug: 318595765
Test: restart device while external display is connected
Test: atest ExternalDisplayPolicyTest
(cherry picked from commit 66b273e12d79b59478d17205982b428aecc29edd)
3 files changed, 56 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java index ab7c503bcb83..a12d2481330b 100644 --- a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java +++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java @@ -42,6 +42,9 @@ import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.display.notifications.DisplayNotificationManager; import com.android.server.display.utils.DebugUtils; +import java.util.HashSet; +import java.util.Set; + /** * Listens for Skin thermal sensor events, disables external displays if thermal status becomes * equal or above {@link android.os.Temperature#THROTTLING_CRITICAL}, enables external displays if @@ -106,6 +109,10 @@ class ExternalDisplayPolicy { private final ExternalDisplayStatsService mExternalDisplayStatsService; @ThrottlingStatus private volatile int mStatus = THROTTLING_NONE; + //@GuardedBy("mSyncRoot") + private boolean mIsBootCompleted; + //@GuardedBy("mSyncRoot") + private final Set<Integer> mDisplayIdsWaitingForBootCompletion = new HashSet<>(); ExternalDisplayPolicy(@NonNull final Injector injector) { mInjector = injector; @@ -121,6 +128,17 @@ class ExternalDisplayPolicy { * Starts listening for temperature changes. */ void onBootCompleted() { + synchronized (mSyncRoot) { + mIsBootCompleted = true; + for (var displayId : mDisplayIdsWaitingForBootCompletion) { + var logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); + if (logicalDisplay != null) { + handleExternalDisplayConnectedLocked(logicalDisplay); + } + } + mDisplayIdsWaitingForBootCompletion.clear(); + } + if (!mFlags.isConnectedDisplayManagementEnabled()) { if (DEBUG) { Slog.d(TAG, "External display management is not enabled on your device:" @@ -189,6 +207,11 @@ class ExternalDisplayPolicy { return; } + if (!mIsBootCompleted) { + mDisplayIdsWaitingForBootCompletion.add(logicalDisplay.getDisplayIdLocked()); + return; + } + mExternalDisplayStatsService.onDisplayConnected(logicalDisplay); if ((Build.IS_ENG || Build.IS_USERDEBUG) @@ -227,7 +250,12 @@ class ExternalDisplayPolicy { return; } - mExternalDisplayStatsService.onDisplayDisconnected(logicalDisplay.getDisplayIdLocked()); + var displayId = logicalDisplay.getDisplayIdLocked(); + if (mDisplayIdsWaitingForBootCompletion.remove(displayId)) { + return; + } + + mExternalDisplayStatsService.onDisplayDisconnected(displayId); } /** diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index b142334db9e9..18f03113c01c 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -2408,6 +2408,7 @@ public class DisplayManagerServiceTest { when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true); manageDisplaysPermission(/* granted= */ true); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); DisplayManagerInternal localService = displayManager.new LocalService(); DisplayManagerService.BinderService bs = displayManager.new BinderService(); LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); @@ -2440,6 +2441,7 @@ public class DisplayManagerServiceTest { .when(() -> SystemProperties.getBoolean(ENABLE_ON_CONNECT, false)); manageDisplaysPermission(/* granted= */ true); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); DisplayManagerInternal localService = displayManager.new LocalService(); DisplayManagerService.BinderService bs = displayManager.new BinderService(); LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); @@ -2487,6 +2489,7 @@ public class DisplayManagerServiceTest { when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true); manageDisplaysPermission(/* granted= */ true); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); DisplayManagerService.BinderService bs = displayManager.new BinderService(); LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(); @@ -2652,6 +2655,7 @@ public class DisplayManagerServiceTest { when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true); manageDisplaysPermission(/* granted= */ true); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); DisplayManagerService.BinderService bs = displayManager.new BinderService(); DisplayManagerInternal localService = displayManager.new LocalService(); LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); @@ -2699,6 +2703,7 @@ public class DisplayManagerServiceTest { when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true); manageDisplaysPermission(/* granted= */ true); DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); + displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); DisplayManagerService.BinderService bs = displayManager.new BinderService(); LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper(); FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(); diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java index 1529a087c284..1a71e77a3b1b 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java @@ -228,13 +228,27 @@ public class ExternalDisplayPolicyTest { @Test public void testOnExternalDisplayAvailable() { - when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(false); + mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay); + assertNotAskedToEnableDisplay(); + verify(mMockedExternalDisplayStatsService, never()).onDisplayConnected(any()); + + mExternalDisplayPolicy.onBootCompleted(); assertAskedToEnableDisplay(); verify(mMockedExternalDisplayStatsService).onDisplayConnected(eq(mMockedLogicalDisplay)); } @Test + public void testOnExternalDisplayUnpluggedBeforeBootCompletes() { + mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay); + mExternalDisplayPolicy.handleLogicalDisplayDisconnectedLocked(mMockedLogicalDisplay); + mExternalDisplayPolicy.onBootCompleted(); + assertNotAskedToEnableDisplay(); + verify(mMockedExternalDisplayStatsService, never()).onDisplayConnected(any()); + verify(mMockedExternalDisplayStatsService, never()).onDisplayDisconnected(anyInt()); + } + + @Test public void testOnExternalDisplayAvailable_criticalThermalCondition() throws RemoteException { // Disallow external displays due to thermals. @@ -303,8 +317,14 @@ public class ExternalDisplayPolicyTest { mDisplayEventCaptor.capture()); assertThat(mLogicalDisplayCaptor.getValue()).isEqualTo(mMockedLogicalDisplay); assertThat(mDisplayEventCaptor.getValue()).isEqualTo(EVENT_DISPLAY_CONNECTED); + verify(mMockedLogicalDisplay).setEnabledLocked(false); clearInvocations(mMockedLogicalDisplayMapper); - when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(true); + clearInvocations(mMockedLogicalDisplay); + } + + private void assertNotAskedToEnableDisplay() { + verify(mMockedInjector, never()).sendExternalDisplayEventLocked(any(), anyInt()); + verify(mMockedLogicalDisplay, never()).setEnabledLocked(anyBoolean()); } private void assertIsExternalDisplayAllowed(final boolean enabled) { |