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

Commit 8a9fc481 authored by Biswarup Pal's avatar Biswarup Pal Committed by Android (Google) Code Review
Browse files

Merge "Async ComputerControl session creation and callback" into main

parents 812fde87 20fe1406
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ 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.companion.virtual.computercontrol.IComputerControlSessionCallback;
import android.content.AttributionSource;

/**
@@ -53,12 +53,12 @@ interface IVirtualDeviceManager {
            in IVirtualDeviceSoundEffectListener soundEffectListener);

    /**
     * Creates a new computer control session.
     * Requests a new computer control session.
     */
    @EnforcePermission("ACCESS_COMPUTER_CONTROL")
    IComputerControlSession createComputerControlSession(
            in IBinder token, in AttributionSource attributionSource,
            in ComputerControlSessionParams params);
    void requestComputerControlSession(
            in AttributionSource attributionSource, in ComputerControlSessionParams params,
            in IComputerControlSessionCallback callback);

    /**
     * Returns the details of all available virtual devices.
+21 −7
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ import android.companion.virtual.camera.VirtualCamera;
import android.companion.virtual.camera.VirtualCameraConfig;
import android.companion.virtual.computercontrol.ComputerControlSession;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IComputerControlSession;
import android.companion.virtual.computercontrol.IComputerControlSessionCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtualdevice.flags.Flags;
import android.content.ComponentName;
@@ -209,17 +209,31 @@ public final class VirtualDeviceManager {
    }

    /**
     * Requests the creation of a new {@link ComputerControlSession}.
     *
     * @param params The configuration of the session.
     * @param executor An executor to run the callback on.
     * @param callback A callback to get notified about the result of this operation.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_COMPUTER_CONTROL)
    @NonNull
    public ComputerControlSession createComputerControlSession(
            @NonNull ComputerControlSessionParams params) {
    public void requestComputerControlSession(
            @NonNull ComputerControlSessionParams params,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull ComputerControlSession.Callback callback) {
        if (mService == null) {
            Log.w(TAG, "Failed to request a new session; no virtual device manager service.");
            return;
        }
        Objects.requireNonNull(params, "params must not be null");
        Objects.requireNonNull(executor, "executor must not be null");
        Objects.requireNonNull(callback, "callback must not be null");
        try {
            IComputerControlSession session = mService.createComputerControlSession(
                    new Binder(), mContext.getAttributionSource(), params);
            return new ComputerControlSession(session);
            IComputerControlSessionCallback callbackProxy =
                    new ComputerControlSession.CallbackProxy(executor, callback);
            mService.requestComputerControlSession(
                    mContext.getAttributionSource(), params, callbackProxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+59 −0
Original line number Diff line number Diff line
@@ -16,15 +16,22 @@

package android.companion.virtual.computercontrol;

import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualTouchEvent;
import android.os.Binder;
import android.os.RemoteException;
import android.view.Surface;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * A session for automated control of applications.
@@ -36,6 +43,23 @@ import java.util.Objects;
 */
public final class ComputerControlSession implements AutoCloseable {

    /**
     * Error code indicating that a new session cannot be created because the maximum number of
     * allowed concurrent sessions has been reached.
     *
     * <p>This is a transient error and the session creation request can be retried later.</p>
     */
    public static final int ERROR_SESSION_LIMIT_REACHED = -1;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(
            prefix = "ERROR_",
            value = {ERROR_SESSION_LIMIT_REACHED})
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface SessionCreationError {
    }

    private final IComputerControlSession mSession;

    /** @hide */
@@ -99,4 +123,39 @@ public final class ComputerControlSession implements AutoCloseable {
            throw e.rethrowFromSystemServer();
        }
    }

    /** Callback for computer control session events. */
    public interface Callback {

        /** Called when the session request was successfully fulfilled. */
        void onSessionCreated(@NonNull ComputerControlSession session);

        /** Called when the session failed to be created. */
        void onSessionCreationFailed(@SessionCreationError int errorCode);
    }

    /** @hide */
    public static class CallbackProxy extends IComputerControlSessionCallback.Stub {

        private final Callback mCallback;
        private final Executor mExecutor;

        public CallbackProxy(@NonNull Executor executor, @NonNull Callback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onSessionCreated(IComputerControlSession session) {
            Binder.withCleanCallingIdentity(() ->
                    mExecutor.execute(() ->
                            mCallback.onSessionCreated(new ComputerControlSession(session))));
        }

        @Override
        public void onSessionCreationFailed(@SessionCreationError int errorCode) {
            Binder.withCleanCallingIdentity(() ->
                    mExecutor.execute(() -> mCallback.onSessionCreationFailed(errorCode)));
        }
    }
}
+33 −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.companion.virtual.computercontrol.IComputerControlSession;

/**
 * Callback for computer control session events.
 *
 * @hide
 */
oneway interface IComputerControlSessionCallback {

    /** Called when the session has been successfully created. */
    void onSessionCreated(in IComputerControlSession session);

    /** Called when the session failed to be created. */
    void onSessionCreationFailed(int errorCode);
}
+8 −8
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.computercontrol.ComputerControlSessionParams;
import android.companion.virtual.computercontrol.IComputerControlSession;
import android.companion.virtual.computercontrol.IComputerControlSessionCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtualdevice.flags.Flags;
import android.companion.virtualnative.IVirtualDeviceManagerNative;
@@ -416,22 +416,22 @@ public class VirtualDeviceManagerService extends SystemService {

        @EnforcePermission(android.Manifest.permission.ACCESS_COMPUTER_CONTROL)
        @Override // Binder call
        public IComputerControlSession createComputerControlSession(
                @NonNull IBinder token,
        public void requestComputerControlSession(
                @NonNull AttributionSource attributionSource,
                @NonNull ComputerControlSessionParams params) {
                @NonNull ComputerControlSessionParams params,
                @NonNull IComputerControlSessionCallback callback) {
            // TODO(b/432678187): Replace the permission check with an alternative
            createComputerControlSession_enforcePermission();
            requestComputerControlSession_enforcePermission();
            if (!android.companion.virtualdevice.flags.Flags.computerControlAccess()) {
                throw new IllegalStateException(
                        "Cannot create ComputerControlSession - flag disabled");
            }
            Objects.requireNonNull(token);
            Objects.requireNonNull(attributionSource);
            Objects.requireNonNull(params);
            Objects.requireNonNull(callback);

            return mComputerControlSessionProcessor.processNewSession(
                    token, attributionSource, params);
            mComputerControlSessionProcessor.processNewSessionRequest(
                    attributionSource, params, callback);
        }

        @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
Loading