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

Commit af769b1e authored by Antony Sargent's avatar Antony Sargent
Browse files

Prevent deadlock when releasing VirtualDisplays

When releasing a VirtualDisplay owned by a VirtualDevice, the
VirtualDeviceManagerService needs to release a WakeLock it holds on
behalf of the display. This needs to happen outside of the
synchronized block in DisplayManagerService, because releasing the
WakeLock ends up calling back into the DisplayManagerService.

Fixes: 224775363
Test: atest StreamedAppBehaviorTest
Change-Id: Ie831fcad7105d51c64717c3e00d332c543de3b47
parent e5f9c3da
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -1459,16 +1459,6 @@ public final class DisplayManagerService extends SystemService {
            DisplayDevice device =
                    mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
            if (device != null) {
                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
                if (display != null) {
                    final int displayId = display.getDisplayIdLocked();
                    if (mDisplayWindowPolicyControllers.contains(displayId)) {
                        Pair<IVirtualDevice, DisplayWindowPolicyController> pair =
                                mDisplayWindowPolicyControllers.removeReturnOld(displayId);
                        getLocalService(VirtualDeviceManagerInternal.class)
                                .onVirtualDisplayRemoved(pair.first, displayId);
                    }
                }
                // TODO: multi-display - handle virtual displays the same as other display adapters.
                mDisplayDeviceRepo.onDisplayDeviceEvent(device,
                        DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
@@ -1628,6 +1618,17 @@ public final class DisplayManagerService extends SystemService {
        DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
        scheduleTraversalLocked(false);

        if (mDisplayWindowPolicyControllers.contains(displayId)) {
            final IVirtualDevice virtualDevice = mDisplayWindowPolicyControllers.removeReturnOld(
                    displayId).first;
            if (virtualDevice != null) {
                mHandler.post(() -> {
                    getLocalService(VirtualDeviceManagerInternal.class)
                            .onVirtualDisplayRemoved(virtualDevice, displayId);
                });
            }
        }
    }

    private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) {