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

Commit 3587ff71 authored by [D's avatar [D[1;5D
Browse files

Move the core computer control logic to system server

The virtual device is created and managed within VDM but still owned
by the caller.

The app process is provided a minimal Binder interface to perform
limited safe operations on the virtual device, displays, and session.

Fix: 432679227
Test: atest
Flag: android.companion.virtualdevice.flags.computer_control_access

Change-Id: I339337f7d1f222fb66c42fcbc1d71240ec08a8d1
parent 43b3cf17
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.companion.virtual.IVirtualDeviceListener;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IComputerControlSession;
import android.content.AttributionSource;

/**
@@ -50,11 +52,13 @@ interface IVirtualDeviceManager {
            in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener,
            in IVirtualDeviceSoundEffectListener soundEffectListener);

    /**
     * Creates a new computer control session.
     */
    @EnforcePermission("ACCESS_COMPUTER_CONTROL")
    IVirtualDevice createLocalVirtualDevice(
    IComputerControlSession createComputerControlSession(
            in IBinder token, in AttributionSource attributionSource,
            in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener,
            in IVirtualDeviceSoundEffectListener soundEffectListener);
            in ComputerControlSessionParams params);

    /**
     * Returns the details of all available virtual devices.
+0 −14
Original line number Diff line number Diff line
@@ -218,20 +218,6 @@ public class VirtualDeviceInternal {
                mSoundEffectListener);
    }

    @RequiresPermission(Manifest.permission.ACCESS_COMPUTER_CONTROL)
    VirtualDeviceInternal(
            IVirtualDeviceManager service,
            Context context,
            VirtualDeviceParams params) throws RemoteException {
        mContext = context.getApplicationContext();
        mVirtualDevice = service.createLocalVirtualDevice(
                new Binder(),
                mContext.getAttributionSource(),
                params,
                mActivityListenerBinder,
                mSoundEffectListener);
    }

    VirtualDeviceInternal(Context context, IVirtualDevice virtualDevice) {
        mContext = context.getApplicationContext();
        mVirtualDevice = virtualDevice;
+6 −11
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import android.companion.virtual.audio.VirtualAudioDevice;
import android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback;
import android.companion.virtual.camera.VirtualCamera;
import android.companion.virtual.camera.VirtualCameraConfig;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IComputerControlSession;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtualdevice.flags.Flags;
import android.content.ComponentName;
@@ -209,10 +211,12 @@ public final class VirtualDeviceManager {
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_COMPUTER_CONTROL)
    @NonNull
    public VirtualDevice createVirtualDevice(@NonNull VirtualDeviceParams params) {
    public IComputerControlSession createComputerControlSession(
            @NonNull ComputerControlSessionParams params) {
        Objects.requireNonNull(params, "params must not be null");
        try {
            return new VirtualDevice(mService, mContext, params);
            return mService.createComputerControlSession(
                    new Binder(), mContext.getAttributionSource(), params);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -572,15 +576,6 @@ public final class VirtualDeviceManager {
                    new VirtualDeviceInternal(service, context, associationId, params);
        }

        @RequiresPermission(Manifest.permission.ACCESS_COMPUTER_CONTROL)
        private VirtualDevice(
                IVirtualDeviceManager service,
                Context context,
                VirtualDeviceParams params) throws RemoteException {
            mVirtualDeviceInternal =
                    new VirtualDeviceInternal(service, context, params);
        }

        /** @hide */
        public VirtualDevice(Context context, IVirtualDevice virtualDevice) {
            mVirtualDeviceInternal = new VirtualDeviceInternal(context, virtualDevice);
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.virtual.computercontrol;

import android.view.Surface;

/**
 * Parameters for creating a computer control session.
 *
 * @hide
 */
parcelable ComputerControlSessionParams {

    /** The name of the session. Only used internally and not shown to users. */
    String name;

    /** The width of the display used for the session. */
    int displayWidthPx;

    /** The height of the display used for the session. */
    int displayHeightPx;

    /** The DPI of the display used for the session. */
    int displayDpi;

    /** The surface of the display used for the session. */
    Surface displaySurface;

    /** Whether the display used for the session should remain always unlocked. */
    boolean isDisplayAlwaysUnlocked;
}
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.virtual.computercontrol;

import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.IVirtualInputDevice;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualTouchEvent;
import android.hardware.input.VirtualTouchscreenConfig;

/**
 * Interface for computer control session management.
 *
 * @hide
 */
interface IComputerControlSession {

    /** Returns the ID of the single trusted virtual display for this session. */
    int getVirtualDisplayId();

    /** Injects a key event into the trusted virtual display. */
    void sendKeyEvent(in VirtualKeyEvent event);

    /** Injects a touch event into the trusted virtual display. */
    void sendTouchEvent(in VirtualTouchEvent event);

    /** Creates a virtual display mirroring the trusted one and returns the display ID. */
    int createMirrorDisplay(in VirtualDisplayConfig config, in IVirtualDisplayCallback callback);

    /** Creates a touchscreen associated with a mirror display. */
    IVirtualInputDevice createMirrorDisplayTouchscreen(in VirtualTouchscreenConfig config);

    /** Closes this session. */
    void close();
}
Loading