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

Commit 3c6b7f35 authored by Jyoti Bhayana's avatar Jyoti Bhayana
Browse files

Camera2 multi-client support

Enable multiple clients to establish a shared session. Once the
session is created, allow each client to independently initiate and
terminate streaming using the `startStreaming` and `stopStreaming`
APIs. Additionally, primary clients can call create captureRequest
API. Ensure that all clients can simultaneously stream the camera
images.

Flag: com.android.internal.camera.flags.camera_multi_client
Bug:265196098
API-Coverage-Bug: 377371012
Test: A session is established with a shared configuration that
supports two streams: SurfaceView and ImageReader. The Java client
can create a session utilizing the SurfaceView stream. The native
client can create a session utilizing the ImageReader stream.
The Java client initiates streaming by creating a capture request and
using the `setRepeatingRequest` method. The native client initiates
streaming using the `startStreaming` API and the ImageReader surface
to receive camera images. Also, ran camera CTS tests on these CLs to
ensure we don't introduce any regressions.

Change-Id: I6ab4e5eef094e75c9b1230ad24afe1c50133df86
parent 4052738f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -36,6 +36,20 @@ interface ICameraDeviceUser

    SubmitInfo submitRequest(in CaptureRequest request, boolean streaming);
    SubmitInfo submitRequestList(in CaptureRequest[] requestList, boolean streaming);
    /**
     * When a camera device is opened in shared mode, only the primary client can change capture
     * parameters and submit capture requests. Secondary clients can use the startStreaming API to
     * provide the stream and surface IDs they want to stream on. If the primary client has an
     * ongoing repeating request, camera service will attach these surfaces to it. Otherwise,
     * camera service will create a default capture request with a preview template.
     *
     * @param streamIdxArray stream ids of the target surfaces
     * @param surfaceIdxArray surface ids of the target surfaces
     * @return SubmitInfo data structure containing the request id of the capture request and the
     *         frame number of the last request, of the previous batch of repeating requests, if
     *         any. If there is no previous  batch, the frame number returned will be -1.
     */
    SubmitInfo startStreaming(in int[] streamIdxArray, in int[] surfaceIdxArray);

    /**
     * Cancel the repeating request specified by requestId
+23 −14
Original line number Diff line number Diff line
@@ -178,30 +178,39 @@ camera_status_t ACameraCaptureSession_abortCaptures(ACameraCaptureSession* sessi

EXPORT
camera_status_t ACameraCaptureSessionShared_startStreaming(
    ACameraCaptureSession* /*session*/, ACameraCaptureSession_captureCallbacksV2* /*callbacks*/,
    int /*numOutputWindows*/, ANativeWindow** /*window*/,
    int* /*captureSequenceId*/) {
    ACameraCaptureSession* session,
    /*optional*/ACameraCaptureSession_captureCallbacksV2* callbacks,
    int numOutputWindows, ANativeWindow** windows,
    /*optional*/int* captureSequenceId) {
    ATRACE_CALL();
    // Todo: need to add implementation
    return  ACAMERA_OK;
    return startStreamingTemplate(session, callbacks, numOutputWindows, windows,
            captureSequenceId);
}

EXPORT
camera_status_t ACameraCaptureSessionShared_logicalCamera_startStreaming(
    ACameraCaptureSession* /*session*/,
    ACameraCaptureSession_logicalCamera_captureCallbacksV2* /*callbacks*/,
    int /*numOutputWindows*/, ANativeWindow** /*windows*/,
    int* /*captureSequenceId*/) {
    ACameraCaptureSession* session,
    /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* callbacks,
    int numOutputWindows, ANativeWindow** windows,
    /*optional*/int* captureSequenceId) {
    ATRACE_CALL();
    // Todo: need to add implementation
    return  ACAMERA_OK;
    return  startStreamingTemplate(session, callbacks, numOutputWindows, windows,
            captureSequenceId);
}

EXPORT
camera_status_t ACameraCaptureSessionShared_stopStreaming(ACameraCaptureSession* /*session*/) {
camera_status_t ACameraCaptureSessionShared_stopStreaming(ACameraCaptureSession* session) {
    ATRACE_CALL();
    // Todo: need to add implementation
    return  ACAMERA_OK;
    if (session == nullptr) {
        ALOGE("%s: Error: session is null", __FUNCTION__);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }

    if (session->isClosed()) {
        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
        return ACAMERA_ERROR_SESSION_CLOSED;
    }
    return session->stopStreaming();
}

EXPORT
+21 −0
Original line number Diff line number Diff line
@@ -68,3 +68,24 @@ camera_status_t setRepeatingRequestTemplate(

    return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
}

template <class CallbackType>
camera_status_t startStreamingTemplate(ACameraCaptureSession* session,
    /*optional*/CallbackType* callbacks,
    int numOutputWindows, ANativeWindow** windows,
    /*optional*/int* captureSequenceId) {
    ATRACE_CALL();
    if (session == nullptr || windows == nullptr || numOutputWindows < 1) {
        ALOGE("%s: Error: invalid input: session %p, numOutputWindows %d, windows %p",
                __FUNCTION__, session, numOutputWindows, windows);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }
    if (session->isClosed()) {
        ALOGE("%s: session %p is already closed", __FUNCTION__, session);
        if (captureSequenceId) {
            *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
        }
        return ACAMERA_ERROR_SESSION_CLOSED;
    }
    return session->startStreaming(callbacks, numOutputWindows, windows, captureSequenceId);
}
+6 −0
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ camera_status_t ACameraDevice_createCaptureRequest(
                __FUNCTION__, device, request);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }
    if (device->isSharedMode() && !device->isPrimaryClient()) {
        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
    }
    switch (templateId) {
        case TEMPLATE_PREVIEW:
        case TEMPLATE_STILL_CAPTURE:
@@ -86,6 +89,9 @@ camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds(
                __FUNCTION__, device, request, physicalCameraIdList);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }
    if (device->isSharedMode() && !device->isPrimaryClient()) {
        return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
    }
    switch (templateId) {
        case TEMPLATE_PREVIEW:
        case TEMPLATE_STILL_CAPTURE:
+5 −0
Original line number Diff line number Diff line
@@ -227,6 +227,11 @@ camera_status_t ACameraManager_openSharedCamera(
                __FUNCTION__, mgr, cameraId, callback, device, primaryClient);
        return ACAMERA_ERROR_INVALID_PARAMETER;
    }
    bool sharedMode;
    camera_status_t status = mgr->isCameraDeviceSharingSupported(cameraId, &sharedMode);
    if ((status != ACAMERA_OK) || !sharedMode) {
         return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
    }
    return mgr->openCamera(cameraId, /*sharedMode*/true, callback, device, primaryClient);
}

Loading