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

Commit 0b285173 authored by Oleg Blinnikov's avatar Oleg Blinnikov
Browse files

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 66b273e1)
parent 1745193e
Loading
Loading
Loading
Loading
+29 −1
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -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();
+22 −2
Original line number Diff line number Diff line
@@ -228,12 +228,26 @@ 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 {
@@ -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) {