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

Commit a2a9fbc6 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski Committed by Android (Google) Code Review
Browse files

Merge "Native VDM: base service implementation" into main

parents 15767624 bf90ffd6
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -431,6 +431,16 @@ aidl_interface {
    },
}

aidl_interface {
    name: "android.companion.virtual.virtualdevice_aidl",
    unstable: true,
    host_supported: true,
    srcs: [
        "android/companion/virtualnative/IVirtualDeviceManagerNative.aidl",
    ],
    local_include_dir: ".",
}

filegroup {
    name: "frameworks-base-java-overview",
    srcs: ["overview.html"],
+8 −0
Original line number Diff line number Diff line
@@ -7,6 +7,14 @@ flag {
  bug: "291725823"
}

flag {
  name: "enable_native_vdm"
  namespace: "virtual_devices"
  description: "Enable native VDM service"
  bug: "303535376"
  is_fixed_read_only: true
}

flag {
  name: "dynamic_policy"
  namespace: "virtual_devices"
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.companion.virtualnative;

/**
 * Parallel implementation of certain VirtualDeviceManager APIs that need to be exposed to native
 * code.
 *
 * <p>These APIs are a parallel definition to the APIs in VirtualDeviceManager and/or
 * VirtualDeviceManagerInternal, so they can technically diverge. However, it's good practice to
 * keep these APIs in sync with each other.</p>
 *
 * <p>Even though the name implies otherwise, the implementation is actually in Java. The 'native'
 * suffix comes from the intended usage - native framework backends that need to communicate with
 * VDM for some reason.</p>
 *
 * <p>Because these APIs are exposed to native code that runs in the app process, they may be
 * accessed by apps directly, even though they're hidden. Care should be taken to avoid exposing
 * sensitive data or potential security holes.</p>
 *
 * @hide
 */
interface IVirtualDeviceManagerNative {
    /**
     * Counterpart to VirtualDeviceParams#DevicePolicy.
     */
    const int DEVICE_POLICY_DEFAULT = 0;
    const int DEVICE_POLICY_CUSTOM = 1;

    /**
     * Counterpart to VirtualDeviceParams#PolicyType.
     */
    const int POLICY_TYPE_SENSORS = 0;
    const int POLICY_TYPE_AUDIO = 1;
    const int POLICY_TYPE_RECENTS = 2;
    const int POLICY_TYPE_ACTIVITY = 3;

    /**
     * Returns the IDs for all VirtualDevices where an app with the given is running.
     *
     * Note that this returns only VirtualDevice IDs: if the app is not running on any virtual
     * device, then an an empty array is returned. This does not include information about whether
     * the app is running on the default device or not.
     */
    int[] getDeviceIdsForUid(int uid);

    /**
     * Returns the device policy for the given virtual device and policy type.
     */
    int getDevicePolicy(int deviceId, int policyType);
}
 No newline at end of file
+21 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.flags.Flags;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtualnative.IVirtualDeviceManagerNative;
import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
@@ -88,8 +89,11 @@ public class VirtualDeviceManagerService extends SystemService {

    private static final String TAG = "VirtualDeviceManagerService";

    private static final String VIRTUAL_DEVICE_NATIVE_SERVICE = "virtualdevice_native";

    private final Object mVirtualDeviceManagerLock = new Object();
    private final VirtualDeviceManagerImpl mImpl;
    private final VirtualDeviceManagerNativeImpl mNativeImpl;
    private final VirtualDeviceManagerInternal mLocalService;
    private VirtualDeviceLog mVirtualDeviceLog = new VirtualDeviceLog(getContext());
    private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -125,6 +129,7 @@ public class VirtualDeviceManagerService extends SystemService {
    public VirtualDeviceManagerService(Context context) {
        super(context);
        mImpl = new VirtualDeviceManagerImpl();
        mNativeImpl = Flags.enableNativeVdm() ? new VirtualDeviceManagerNativeImpl() : null;
        mLocalService = new LocalService();
    }

@@ -155,6 +160,9 @@ public class VirtualDeviceManagerService extends SystemService {
    @Override
    public void onStart() {
        publishBinderService(Context.VIRTUAL_DEVICE_SERVICE, mImpl);
        if (Flags.enableNativeVdm()) {
            publishBinderService(VIRTUAL_DEVICE_NATIVE_SERVICE, mNativeImpl);
        }
        publishLocalService(VirtualDeviceManagerInternal.class, mLocalService);
        ActivityTaskManagerInternal activityTaskManagerInternal = getLocalService(
                ActivityTaskManagerInternal.class);
@@ -590,6 +598,19 @@ public class VirtualDeviceManagerService extends SystemService {
        }
    }

    final class VirtualDeviceManagerNativeImpl extends IVirtualDeviceManagerNative.Stub {
        @Override // Binder call
        public int[] getDeviceIdsForUid(int uid) {
            return mLocalService
                    .getDeviceIdsForUid(uid).stream().mapToInt(Integer::intValue).toArray();
        }

        @Override // Binder call
        public int getDevicePolicy(int deviceId, int policyType) {
            return mImpl.getDevicePolicy(deviceId, policyType);
        }
    }

    private final class LocalService extends VirtualDeviceManagerInternal {
        @GuardedBy("mVirtualDeviceManagerLock")
        private final ArrayList<VirtualDisplayListener>
+29 −12
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ public class VirtualDeviceManagerServiceTest {
    private VirtualDeviceManagerService mVdms;
    private VirtualDeviceManagerInternal mLocalService;
    private VirtualDeviceManagerService.VirtualDeviceManagerImpl mVdm;
    private VirtualDeviceManagerService.VirtualDeviceManagerNativeImpl mVdmNative;
    private VirtualDeviceLog mVirtualDeviceLog;
    @Mock
    private InputController.NativeWrapper mNativeWrapperMock;
@@ -340,6 +341,7 @@ public class VirtualDeviceManagerServiceTest {
        mSetFlagsRule.disableFlags(Flags.FLAG_DYNAMIC_POLICY);
        mSetFlagsRule.disableFlags(Flags.FLAG_STREAM_PERMISSIONS);
        mSetFlagsRule.disableFlags(Flags.FLAG_VDM_CUSTOM_HOME);
        mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_NATIVE_VDM);

        doReturn(true).when(mInputManagerInternalMock).setVirtualMousePointerDisplayId(anyInt());
        doNothing().when(mInputManagerInternalMock).setPointerAcceleration(anyFloat(), anyInt());
@@ -384,6 +386,7 @@ public class VirtualDeviceManagerServiceTest {
        mVdms = new VirtualDeviceManagerService(mContext);
        mLocalService = mVdms.getLocalServiceInstance();
        mVdm = mVdms.new VirtualDeviceManagerImpl();
        mVdmNative = mVdms.new VirtualDeviceManagerNativeImpl();
        mVirtualDeviceLog = new VirtualDeviceLog(mContext);
        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1);
        mSensorController = mDeviceImpl.getSensorControllerForTest();
@@ -440,24 +443,32 @@ public class VirtualDeviceManagerServiceTest {
    public void getDevicePolicy_invalidDeviceId_returnsDefault() {
        assertThat(mVdm.getDevicePolicy(DEVICE_ID_INVALID, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
        assertThat(mVdmNative.getDevicePolicy(DEVICE_ID_INVALID, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
    }

    @Test
    public void getDevicePolicy_defaultDeviceId_returnsDefault() {
        assertThat(mVdm.getDevicePolicy(DEVICE_ID_DEFAULT, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
        assertThat(mVdmNative.getDevicePolicy(DEVICE_ID_DEFAULT, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
    }

    @Test
    public void getDevicePolicy_nonExistentDeviceId_returnsDefault() {
        assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId() + 1, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
        assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId() + 1, POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
    }

    @Test
    public void getDevicePolicy_unspecifiedPolicy_returnsDefault() {
        assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
        assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_DEFAULT);
    }

    @Test
@@ -472,6 +483,8 @@ public class VirtualDeviceManagerServiceTest {

        assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_CUSTOM);
        assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
                .isEqualTo(DEVICE_POLICY_CUSTOM);
    }

    @Test
@@ -567,8 +580,8 @@ public class VirtualDeviceManagerServiceTest {

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

    @Test
@@ -577,8 +590,8 @@ public class VirtualDeviceManagerServiceTest {
        mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
                Sets.newArraySet(UID_2));

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

    @Test
@@ -587,8 +600,9 @@ public class VirtualDeviceManagerServiceTest {
        mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
                Sets.newArraySet(UID_1));

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

    @Test
@@ -598,8 +612,9 @@ public class VirtualDeviceManagerServiceTest {
        mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
                Sets.newArraySet(UID_1, UID_2));

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

    @Test
@@ -611,8 +626,9 @@ public class VirtualDeviceManagerServiceTest {
        secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged(
                Sets.newArraySet(UID_1));

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

    @Test
@@ -628,8 +644,9 @@ public class VirtualDeviceManagerServiceTest {
        secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged(
                Sets.newArraySet(UID_1, UID_2));

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