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

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

Add methods to VirtualDeviceManagerInternal

These allow determining:

-Which VirtualDevice's, if any, have a given app running on them
-What app owns a VirtualDevice

This information is going to be used for implementing siloed clipboard
support for VirtualDevices in ClipboardService.

Bug: 262038440
Test: atest VirtualDeviceManagerServiceTest
Change-Id: I78ee1c3ea1f21804b5f2faca4108c33156b27bc8
parent 37f3eda7
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -62,6 +63,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@@ -494,6 +496,35 @@ public class VirtualDeviceManagerService extends SystemService {
            }
        }

        @Override
        public int getDeviceOwnerUid(int deviceId) {
            synchronized (mVirtualDeviceManagerLock) {
                int size = mVirtualDevices.size();
                for (int i = 0; i < size; i++) {
                    VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
                    if (device.getDeviceId() == deviceId) {
                        return device.getOwnerUid();
                    }
                }
            }
            return Process.INVALID_UID;
        }

        @Override
        public @NonNull Set<Integer> getDeviceIdsForUid(int uid) {
            ArraySet<Integer> result = new ArraySet<>();
            synchronized (mVirtualDeviceManagerLock) {
                int size = mVirtualDevices.size();
                for (int i = 0; i < size; i++) {
                    VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
                    if (device.isAppRunningOnVirtualDevice(uid)) {
                        result.add(device.getDeviceId());
                    }
                }
            }
            return result;
        }

        @Override
        public void onVirtualDisplayCreated(int displayId) {
            final VirtualDisplayListener[] listeners;
+19 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ public abstract class VirtualDeviceManagerInternal {
        void onVirtualDisplayRemoved(int displayId);
    }


    /** Interface to listen to the changes on the list of app UIDs running on any virtual device. */
    public interface AppsOnVirtualDeviceListener {
        /** Notifies that running apps on any virtual device has changed */
@@ -71,6 +70,25 @@ public abstract class VirtualDeviceManagerInternal {
     */
    public abstract boolean isValidVirtualDevice(IVirtualDevice virtualDevice);

    /**
     * Gets the owner uid for a deviceId.
     *
     * @param deviceId which device we're asking about
     * @return the uid of the app which created and owns the VirtualDevice with the given deviceId,
     * or {@link android.os.Process#INVALID_UID} if no such device exists.
     */
    public abstract int getDeviceOwnerUid(int deviceId);

    /**
     * Finds VirtualDevices where an app is running.
     *
     * @param uid - the app's uid
     * @return a set of id's of VirtualDevices where the app with the given uid is running.
     * *Note* this only checks VirtualDevices, and does not include information about whether
     * the app is running on the default device or not.
     */
    public abstract @NonNull Set<Integer> getDeviceIdsForUid(int uid);

    /**
     * Notifies that a virtual display is created.
     *
+129 −12
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ import com.android.server.LocalServices;
import com.android.server.input.InputManagerInternal;
import com.android.server.sensors.SensorManagerInternal;

import com.google.android.collect.Sets;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -108,6 +110,7 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

@Presubmit
@@ -124,6 +127,9 @@ public class VirtualDeviceManagerServiceTest {
    private static final String GOOGLE_MAPS_PACKAGE_NAME = "com.google.android.apps.maps";
    private static final String DEVICE_NAME = "device name";
    private static final int DISPLAY_ID = 2;
    private static final int DISPLAY_ID_2 = 3;
    private static final int DEVICE_OWNER_UID_1 = 50;
    private static final int DEVICE_OWNER_UID_2 = 51;
    private static final int UID_1 = 0;
    private static final int UID_2 = 10;
    private static final int UID_3 = 10000;
@@ -301,22 +307,13 @@ public class VirtualDeviceManagerServiceTest {
                mContext.getSystemService(WindowManager.class), threadVerifier);
        mSensorController = new SensorController(new Object(), VIRTUAL_DEVICE_ID);

        mAssociationInfo = new AssociationInfo(1, 0, null,
        mAssociationInfo = new AssociationInfo(ASSOCIATION_ID_1, 0, null,
                MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0);

        mVdms = new VirtualDeviceManagerService(mContext);
        mLocalService = mVdms.getLocalServiceInstance();
        mVdm = mVdms.new VirtualDeviceManagerImpl();

        VirtualDeviceParams params = new VirtualDeviceParams
                .Builder()
                .setBlockedActivities(getBlockedActivities())
                .build();
        mDeviceImpl = new VirtualDeviceImpl(mContext,
                mAssociationInfo, new Binder(), /* ownerUid= */ 0, VIRTUAL_DEVICE_ID,
                mInputController, mSensorController, (int associationId) -> {},
                mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params);
        mVdms.addVirtualDevice(mDeviceImpl);
        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID, DEVICE_OWNER_UID_1, mAssociationInfo);
    }

    @Test
@@ -388,6 +385,112 @@ public class VirtualDeviceManagerServiceTest {
                .isEqualTo(DEVICE_POLICY_CUSTOM);
    }

    @Test
    public void getDeviceOwnerUid_oneDevice_returnsCorrectId() {
        int ownerUid = mLocalService.getDeviceOwnerUid(mDeviceImpl.getDeviceId());
        assertThat(ownerUid).isEqualTo(mDeviceImpl.getOwnerUid());
    }

    @Test
    public void getDeviceOwnerUid_twoDevices_returnsCorrectId() {
        int firstDeviceId = mDeviceImpl.getDeviceId();
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));

        int secondDeviceOwner = mLocalService.getDeviceOwnerUid(secondDeviceId);
        assertThat(secondDeviceOwner).isEqualTo(DEVICE_OWNER_UID_2);

        int firstDeviceOwner = mLocalService.getDeviceOwnerUid(firstDeviceId);
        assertThat(firstDeviceOwner).isEqualTo(DEVICE_OWNER_UID_1);
    }

    @Test
    public void getDeviceOwnerUid_nonExistentDevice_returnsInvalidUid() {
        int nonExistentDeviceId = DEVICE_ID_DEFAULT;
        int ownerUid = mLocalService.getDeviceOwnerUid(nonExistentDeviceId);
        assertThat(ownerUid).isEqualTo(Process.INVALID_UID);
    }

    @Test
    public void getDeviceIdsForUid_noRunningApps_returnsNull() {
        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).isEmpty();
    }

    @Test
    public void getDeviceIdsForUid_differentUidOnDevice_returnsNull() {
        GenericWindowPolicyController gwpc =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID);
        gwpc.onRunningAppsChanged(Sets.newArraySet(UID_2));

        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).isEmpty();
    }

    @Test
    public void getDeviceIdsForUid_oneUidOnDevice_returnsCorrectId() {
        GenericWindowPolicyController gwpc =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID);
        gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1));

        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).containsExactly(mDeviceImpl.getDeviceId());
    }

    @Test
    public void getDeviceIdsForUid_twoUidsOnDevice_returnsCorrectId() {
        GenericWindowPolicyController gwpc =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID);
        gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1, UID_2));

        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).containsExactly(mDeviceImpl.getDeviceId());
    }

    @Test
    public void getDeviceIdsForUid_twoDevicesUidOnOne_returnsCorrectId() {
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));

        GenericWindowPolicyController gwpc =
                secondDevice.createWindowPolicyController(new ArrayList<>());
        secondDevice.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_2);
        gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1));

        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).containsExactly(secondDevice.getDeviceId());
    }

    @Test
    public void getDeviceIdsForUid_twoDevicesUidOnBoth_returnsCorrectId() {
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));
        GenericWindowPolicyController gwpc1 =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        GenericWindowPolicyController gwpc2 =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc1, DISPLAY_ID);
        secondDevice.onVirtualDisplayCreatedLocked(gwpc2, DISPLAY_ID_2);
        gwpc1.onRunningAppsChanged(Sets.newArraySet(UID_1));
        gwpc2.onRunningAppsChanged(Sets.newArraySet(UID_1, UID_2));

        Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
        assertThat(deviceIds).containsExactly(
                mDeviceImpl.getDeviceId(), secondDevice.getDeviceId());
    }

    @Test
    public void onVirtualDisplayRemovedLocked_doesNotThrowException() {
        mDeviceImpl.onVirtualDisplayCreatedLocked(
@@ -1160,7 +1263,6 @@ public class VirtualDeviceManagerServiceTest {
                /* targetDisplayCategory= */ null);
        verify(mContext).startActivityAsUser(argThat(intent ->
                intent.filterEquals(blockedAppIntent)), any(), any());

    }

    @Test
@@ -1185,4 +1287,19 @@ public class VirtualDeviceManagerServiceTest {
        verify(mContext).startActivityAsUser(argThat(intent ->
                intent.filterEquals(blockedAppIntent)), any(), any());
    }

    private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid,
            AssociationInfo associationInfo) {
        VirtualDeviceParams params = new VirtualDeviceParams
                .Builder()
                .setBlockedActivities(getBlockedActivities())
                .build();
        VirtualDeviceImpl virtualDeviceImpl = new VirtualDeviceImpl(mContext,
                associationInfo, new Binder(), ownerUid, virtualDeviceId,
                mInputController, mSensorController, (int associationId) -> {},
                mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params);
        mVdms.addVirtualDevice(virtualDeviceImpl);
        return virtualDeviceImpl;
    }

}