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

Commit 63ba140c authored by Jan Sebechlebsky's avatar Jan Sebechlebsky
Browse files

Refactor virtual display creation and cleanup

* Consolidate all resources tied to display in newly added
  VirtualDisplayWrapper data class.
* Simplify virtual display creation logic but moving all
  business logic inside VirtualDeviceImpl.createVirtualDisplay
* Release all not-yet released displays when the virtual device
  is closed.
* Fix locking issues (unnecessary holding of lock, vs missing locking).
* Fix deadlock caused by lock inversion when holding mVirtualDeviceLock during calls into mInputController / InputManagerInternal.

Bug: 267747549
Bug: 266567359
Test: atest VirtualDeviceManagerServiceTest
Test: atest CtsVirtualDevicesTestCases
Test: atest VirtualDisplayTest --iterations 30
Change-Id: Ie447bd1cee9356a6343ed38c35e13c8228d2464f
parent 04b79853
Loading
Loading
Loading
Loading
+223 −119

File changed.

Preview size limit exceeded, changes collapsed.

+64 −82
Original line number Original line Diff line number Diff line
@@ -37,7 +37,6 @@ import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensor;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.display.VirtualDisplayConfig;
import android.os.Binder;
import android.os.Binder;
@@ -193,12 +192,21 @@ public class VirtualDeviceManagerService extends SystemService {
        }
        }
    }
    }


    @VisibleForTesting
    void removeVirtualDevice(int deviceId) {
    void removeVirtualDevice(int deviceId) {
        synchronized (mVirtualDeviceManagerLock) {
        synchronized (mVirtualDeviceManagerLock) {
            mAppsOnVirtualDevices.remove(deviceId);
            mAppsOnVirtualDevices.remove(deviceId);
            mVirtualDevices.remove(deviceId);
            mVirtualDevices.remove(deviceId);
        }
        }

        Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
        i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
        i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        final long identity = Binder.clearCallingIdentity();
        try {
            getContext().sendBroadcastAsUser(i, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }
    }


    class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub {
    class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub {
@@ -206,7 +214,8 @@ public class VirtualDeviceManagerService extends SystemService {
        private final VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback =
        private final VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback =
                new VirtualDeviceImpl.PendingTrampolineCallback() {
                new VirtualDeviceImpl.PendingTrampolineCallback() {
                    @Override
                    @Override
            public void startWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline) {
                    public void startWaitingForPendingTrampoline(
                            PendingTrampoline pendingTrampoline) {
                        PendingTrampoline existing = mPendingTrampolines.put(
                        PendingTrampoline existing = mPendingTrampolines.put(
                                pendingTrampoline.mPendingIntent.getCreatorPackage(),
                                pendingTrampoline.mPendingIntent.getCreatorPackage(),
                                pendingTrampoline);
                                pendingTrampoline);
@@ -217,8 +226,10 @@ public class VirtualDeviceManagerService extends SystemService {
                    }
                    }


                    @Override
                    @Override
            public void stopWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline) {
                    public void stopWaitingForPendingTrampoline(
                mPendingTrampolines.remove(pendingTrampoline.mPendingIntent.getCreatorPackage());
                            PendingTrampoline pendingTrampoline) {
                        mPendingTrampolines.remove(
                                pendingTrampoline.mPendingIntent.getCreatorPackage());
                    }
                    }
                };
                };


@@ -251,8 +262,9 @@ public class VirtualDeviceManagerService extends SystemService {
                final Consumer<ArraySet<Integer>> runningAppsChangedCallback =
                final Consumer<ArraySet<Integer>> runningAppsChangedCallback =
                        runningUids -> notifyRunningAppsChanged(deviceId, runningUids);
                        runningUids -> notifyRunningAppsChanged(deviceId, runningUids);
                VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
                VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
                        associationInfo, token, callingUid, deviceId, cameraAccessController,
                        associationInfo, VirtualDeviceManagerService.this, token, callingUid,
                        this::onDeviceClosed, mPendingTrampolineCallback, activityListener,
                        deviceId, cameraAccessController,
                        mPendingTrampolineCallback, activityListener,
                        soundEffectListener, runningAppsChangedCallback, params);
                        soundEffectListener, runningAppsChangedCallback, params);
                mVirtualDevices.put(deviceId, virtualDevice);
                mVirtualDevices.put(deviceId, virtualDevice);
                return virtualDevice;
                return virtualDevice;
@@ -281,26 +293,9 @@ public class VirtualDeviceManagerService extends SystemService {
                        "uid " + callingUid
                        "uid " + callingUid
                                + " is not the owner of the supplied VirtualDevice");
                                + " is not the owner of the supplied VirtualDevice");
            }
            }
            GenericWindowPolicyController gwpc;
            final long token = Binder.clearCallingIdentity();
            try {
                gwpc = virtualDeviceImpl.createWindowPolicyController(
                    virtualDisplayConfig.getDisplayCategories());
            } finally {
                Binder.restoreCallingIdentity(token);
            }

            DisplayManagerInternal displayManager = getLocalService(
                    DisplayManagerInternal.class);
            int displayId = displayManager.createVirtualDisplay(virtualDisplayConfig, callback,
                    virtualDevice, gwpc, packageName);


            final long tokenTwo = Binder.clearCallingIdentity();
            int displayId = virtualDeviceImpl.createVirtualDisplay(virtualDisplayConfig, callback,
            try {
                    packageName);
                virtualDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, displayId);
            } finally {
                Binder.restoreCallingIdentity(tokenTwo);
            }
            mLocalService.onVirtualDisplayCreated(displayId);
            mLocalService.onVirtualDisplayCreated(displayId);
            return displayId;
            return displayId;
        }
        }
@@ -412,19 +407,6 @@ public class VirtualDeviceManagerService extends SystemService {
            return null;
            return null;
        }
        }


        private void onDeviceClosed(int deviceId) {
            removeVirtualDevice(deviceId);
            Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
            i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
            i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            final long identity = Binder.clearCallingIdentity();
            try {
                getContext().sendBroadcastAsUser(i, UserHandle.ALL);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        @Override
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
                throws RemoteException {
@@ -512,9 +494,14 @@ public class VirtualDeviceManagerService extends SystemService {
        @Override
        @Override
        public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
        public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
            final VirtualDisplayListener[] listeners;
            final VirtualDisplayListener[] listeners;
            VirtualDeviceImpl virtualDeviceImpl;
            synchronized (mVirtualDeviceManagerLock) {
            synchronized (mVirtualDeviceManagerLock) {
                ((VirtualDeviceImpl) virtualDevice).onVirtualDisplayRemovedLocked(displayId);
                listeners = mVirtualDisplayListeners.toArray(new VirtualDisplayListener[0]);
                listeners = mVirtualDisplayListeners.toArray(new VirtualDisplayListener[0]);
                virtualDeviceImpl = mVirtualDevices.get(
                        ((VirtualDeviceImpl) virtualDevice).getDeviceId());
            }
            if (virtualDeviceImpl != null) {
                virtualDeviceImpl.onVirtualDisplayRemoved(displayId);
            }
            }
            mHandler.post(() -> {
            mHandler.post(() -> {
                for (VirtualDisplayListener listener : listeners) {
                for (VirtualDisplayListener listener : listeners) {
@@ -599,16 +586,11 @@ public class VirtualDeviceManagerService extends SystemService {


        @Override
        @Override
        public @NonNull ArraySet<Integer> getDisplayIdsForDevice(int deviceId) {
        public @NonNull ArraySet<Integer> getDisplayIdsForDevice(int deviceId) {
            VirtualDeviceImpl virtualDevice;
            synchronized (mVirtualDeviceManagerLock) {
            synchronized (mVirtualDeviceManagerLock) {
                int size = mVirtualDevices.size();
                virtualDevice = mVirtualDevices.get(deviceId);
                for (int i = 0; i < size; i++) {
                    VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
                    if (device.getDeviceId() == deviceId) {
                        return new ArraySet<>(device.mVirtualDisplayIds);
                    }
                }
            }
            }
            return new ArraySet<>();
            return virtualDevice == null ? new ArraySet<>() : virtualDevice.getDisplayIds();
        }
        }


        @Override
        @Override
+119 −121

File changed.

Preview size limit exceeded, changes collapsed.