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

Commit 325b667c authored by Vadim Caen's avatar Vadim Caen Committed by Biswarup Pal
Browse files

Add virtual camera API and the aidl interfaces.

 - Single callback class for VirtualCamera
 - Update the virtual camera AIDL interface and parcelable to
   align with the planned API
 - Add interoperability between the client-server aidl and
   server-service aidl and update the related test

Test: atest VirtualCameraControllerTest
Bug: 270352264
Fixes: 302255544
API-Coverage-Bug: 310857520

Change-Id: I3ab768db277b5574d6fdb74b674d0500ffd6452e
parent 65959325
Loading
Loading
Loading
Loading
+47 −0
Original line number Original line Diff line number Diff line
@@ -3330,6 +3330,53 @@ package android.companion.virtual.audio {
}
}
package android.companion.virtual.camera {
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public final class VirtualCamera implements java.io.Closeable {
    method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
    method @NonNull public android.companion.virtual.camera.VirtualCameraConfig getConfig();
  }
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public interface VirtualCameraCallback {
    method public void onProcessCaptureRequest(int, long, @Nullable android.companion.virtual.camera.VirtualCameraMetadata);
    method public void onStreamClosed(int);
    method public void onStreamConfigured(int, @NonNull android.view.Surface, @NonNull android.companion.virtual.camera.VirtualCameraStreamConfig);
  }
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public final class VirtualCameraConfig implements android.os.Parcelable {
    method public int describeContents();
    method @StringRes public int getDisplayNameStringRes();
    method @NonNull public java.util.Set<android.companion.virtual.camera.VirtualCameraStreamConfig> getStreamConfigs();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.camera.VirtualCameraConfig> CREATOR;
  }
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public static final class VirtualCameraConfig.Builder {
    ctor public VirtualCameraConfig.Builder();
    method @NonNull public android.companion.virtual.camera.VirtualCameraConfig.Builder addStreamConfig(int, int, int);
    method @NonNull public android.companion.virtual.camera.VirtualCameraConfig build();
    method @NonNull public android.companion.virtual.camera.VirtualCameraConfig.Builder setDisplayNameStringRes(@StringRes int);
    method @NonNull public android.companion.virtual.camera.VirtualCameraConfig.Builder setVirtualCameraCallback(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.camera.VirtualCameraCallback);
  }
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public final class VirtualCameraMetadata implements android.os.Parcelable {
    method public int describeContents();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.camera.VirtualCameraMetadata> CREATOR;
  }
  @FlaggedApi("android.companion.virtual.flags.virtual_camera") public final class VirtualCameraStreamConfig implements android.os.Parcelable {
    ctor public VirtualCameraStreamConfig(@IntRange(from=1) int, @IntRange(from=1) int, int);
    method public int describeContents();
    method public int getFormat();
    method @IntRange(from=1) public int getHeight();
    method @IntRange(from=1) public int getWidth();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.camera.VirtualCameraStreamConfig> CREATOR;
  }
}
package android.companion.virtual.sensor {
package android.companion.virtual.sensor {
  public final class VirtualSensor implements android.os.Parcelable {
  public final class VirtualSensor implements android.os.Parcelable {
+10 −4
Original line number Original line Diff line number Diff line
@@ -23,8 +23,7 @@ import android.companion.virtual.audio.IAudioRoutingCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensorConfig;
import android.companion.virtual.sensor.VirtualSensorConfig;
import android.companion.virtual.sensor.VirtualSensorEvent;
import android.companion.virtual.sensor.VirtualSensorEvent;
import android.companion.virtual.camera.IVirtualCamera;
import android.companion.virtual.camera.VirtualCameraConfig;
import android.companion.virtual.camera.VirtualCameraHalConfig;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.graphics.Point;
import android.graphics.Point;
@@ -236,8 +235,15 @@ interface IVirtualDevice {
    void unregisterIntentInterceptor(in IVirtualDeviceIntentInterceptor intentInterceptor);
    void unregisterIntentInterceptor(in IVirtualDeviceIntentInterceptor intentInterceptor);


    /**
    /**
     * Creates a new VirtualCamera and registers it with the VirtualCameraProvider.
     * Creates a new virtual camera and registers it with the virtual camera service.
     */
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void registerVirtualCamera(in IVirtualCamera camera);
    void registerVirtualCamera(in VirtualCameraConfig camera);

    /**
     * Destroys the virtual camera with given config and unregisters it from the virtual camera
     * service.
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void unregisterVirtualCamera(in VirtualCameraConfig camera);
}
}
+0 −17
Original line number Original line Diff line number Diff line
package android.companion.virtual.camera;

import android.companion.virtual.camera.IVirtualCameraSession;
import android.companion.virtual.camera.VirtualCameraHalConfig;

/**
 * Counterpart of ICameraDevice for virtual camera.
 *
 * @hide
 */
interface IVirtualCamera {

    IVirtualCameraSession open();

    VirtualCameraHalConfig getHalConfig();

}
 No newline at end of file
+70 −0
Original line number Original line 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.virtual.camera;

import android.companion.virtual.camera.VirtualCameraStreamConfig;
import android.companion.virtual.camera.VirtualCameraMetadata;
import android.view.Surface;

/**
 * Interface for the virtual camera service and system server to talk back to the virtual camera owner.
 *
 * @hide
 */
interface IVirtualCameraCallback {

    /**
     * Called when one of the requested stream has been configured by the virtual camera service and
     * is ready to receive data onto its {@link Surface}
     *
     * @param streamId     The id of the configured stream
     * @param surface      The surface to write data into for this stream
     * @param streamConfig The image data configuration for this stream
     */
    oneway void onStreamConfigured(
            int streamId,
            in Surface surface,
            in VirtualCameraStreamConfig streamConfig);

    /**
     * The client application is requesting a camera frame for the given streamId with the provided
     * metadata.
     *
     * <p>The virtual camera needs to write the frame data in the {@link Surface} corresponding to
     * this stream that was provided during the {@link #onStreamConfigured(int, Surface,
     * VirtualCameraStreamConfig)} call.
     *
     * @param streamId The streamId for which the frame is requested. This corresponds to the
     *     streamId that was given in {@link #onStreamConfigured(int, Surface,
     *     VirtualCameraStreamConfig)}
     * @param frameId The frameId that is being requested. Each request will have a different
     *     frameId, that will be increasing for each call with a particular streamId.
     * @param metadata The metadata requested for the frame. The virtual camera should do its best
     *     to honor the requested metadata.
     */
    oneway void onProcessCaptureRequest(
            int streamId, long frameId, in VirtualCameraMetadata metadata);

    /**
     * The stream previously configured when {@link #onStreamConfigured(int, Surface,
     * VirtualCameraStreamConfig)} was called is now being closed and associated resources can be
     * freed. The Surface was disposed on the client side and should not be used anymore by the virtual camera owner
     *
     * @param streamId The id of the stream that was closed.
     */
    oneway void onStreamClosed(int streamId);

}
 No newline at end of file
+38 −19
Original line number Original line Diff line number Diff line
@@ -16,20 +16,44 @@


package android.companion.virtual.camera;
package android.companion.virtual.camera;


import android.annotation.FlaggedApi;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.flags.Flags;
import android.hardware.camera2.CameraDevice;
import android.os.RemoteException;
import android.os.RemoteException;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;


import java.io.Closeable;
import java.util.Objects;
import java.util.Objects;
import java.util.concurrent.Executor;


/**
/**
 * Virtual camera that is used to send image data into system.
 * A VirtualCamera is the representation of a remote or computer generated camera that will be
 * exposed to applications using the Android Camera APIs.
 *
 *
 * <p>A VirtualCamera is created using {@link
 * VirtualDeviceManager.VirtualDevice#createVirtualCamera(VirtualCameraConfig)}.
 *
 * <p>Once a virtual camera is created, it will receive callbacks from the system when an
 * application attempts to use it via the {@link VirtualCameraCallback} class set using {@link
 * VirtualCameraConfig.Builder#setVirtualCameraCallback(Executor, VirtualCameraCallback)}
 *
 * @see VirtualDeviceManager.VirtualDevice#createVirtualDevice(int, VirtualDeviceParams)
 * @see VirtualCameraConfig.Builder#setVirtualCameraCallback(Executor, VirtualCameraCallback)
 * @see android.hardware.camera2.CameraManager#openCamera(String, CameraDevice.StateCallback,
 *     android.os.Handler)
 * @hide
 * @hide
 */
 */
public final class VirtualCamera extends IVirtualCamera.Stub {
@SystemApi
@FlaggedApi(Flags.FLAG_VIRTUAL_CAMERA)
public final class VirtualCamera implements Closeable {


    private final IVirtualDevice mVirtualDevice;
    private final VirtualCameraConfig mConfig;
    private final VirtualCameraConfig mConfig;


    /**
    /**
@@ -37,40 +61,35 @@ public final class VirtualCamera extends IVirtualCamera.Stub {
     *
     *
     * @param virtualDevice The Binder object representing this camera in the server.
     * @param virtualDevice The Binder object representing this camera in the server.
     * @param config Configuration for the new virtual camera
     * @param config Configuration for the new virtual camera
     * @hide
     */
     */
    @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
    public VirtualCamera(
    public VirtualCamera(
            @NonNull IVirtualDevice virtualDevice, @NonNull VirtualCameraConfig config) {
            @NonNull IVirtualDevice virtualDevice, @NonNull VirtualCameraConfig config) {
        mVirtualDevice = virtualDevice;
        mConfig = Objects.requireNonNull(config);
        mConfig = Objects.requireNonNull(config);
        Objects.requireNonNull(virtualDevice);
        Objects.requireNonNull(virtualDevice);
        // TODO(b/310857519): Avoid registration inside constructor.
        try {
        try {
            virtualDevice.registerVirtualCamera(this);
            mVirtualDevice.registerVirtualCamera(config);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
        }
        }
    }
    }


    /** Get the camera session associated with this device */
    @Override
    public IVirtualCameraSession open() {
        // TODO: b/302255544 - Make this async.
        VirtualCameraSession session = mConfig.getCallback().onOpenSession();
        return new VirtualCameraSessionInternal(session);
    }

    /** Returns the configuration of this virtual camera instance. */
    /** Returns the configuration of this virtual camera instance. */
    @NonNull
    @NonNull
    public VirtualCameraConfig getConfig() {
    public VirtualCameraConfig getConfig() {
        return mConfig;
        return mConfig;
    }
    }


    /**
     * Returns the configuration to be used by the virtual camera HAL.
     *
     * @hide
     */
    @Override
    @Override
    @NonNull
    @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
    public VirtualCameraHalConfig getHalConfig() {
    public void close() {
        return mConfig.getHalConfig();
        try {
            mVirtualDevice.unregisterVirtualCamera(mConfig);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }
    }
}
}
Loading