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

Commit 0960fb46 authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

camera2: Add physical camera id in CaptureResult

- Add physical camera id in capture result.
- Add ability for app to get metadata key/value for physical camera.
- Batch physical and logical camera result within one processCaptureResult call.

Test: testLogicalCamera CTS test
Bug: 64691172
Change-Id: Ic67275aa5b44cbcad7ef98409e4365ee08989736
parent 3bc6f794
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16146,6 +16146,7 @@ package android.hardware.camera2 {
  public final class TotalCaptureResult extends android.hardware.camera2.CaptureResult {
    method public java.util.List<android.hardware.camera2.CaptureResult> getPartialResults();
    method public <T> T getPhysicalCameraKey(android.hardware.camera2.CaptureResult.Key<T>, java.lang.String);
  }
}
+54 −1
Original line number Diff line number Diff line
@@ -17,11 +17,14 @@
package android.hardware.camera2;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.impl.PhysicalCaptureResultInfo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
@@ -44,6 +47,12 @@ import java.util.List;
 * as {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE}). Refer to each key documentation on
 * a case-by-case basis.</p>
 *
 * <p>For a logical multi-camera device, if the CaptureRequest contains a surface for an underlying
 * physical camera, the corresponding {@link TotalCaptureResult} object will include the metadata
 * for that physical camera. And its keys and values can be accessed by
 * {@link #getPhysicalCameraKey}. If all requested surfaces are for the logical camera, no
 * metadata for physical camera will be included.</p>
 *
 * <p>{@link TotalCaptureResult} objects are immutable.</p>
 *
 * @see CameraDevice.CaptureCallback#onCaptureCompleted
@@ -52,6 +61,8 @@ public final class TotalCaptureResult extends CaptureResult {

    private final List<CaptureResult> mPartialResults;
    private final int mSessionId;
    // The map between physical camera id and capture result
    private final HashMap<String, CameraMetadataNative> mPhysicalCaptureResults;

    /**
     * Takes ownership of the passed-in camera metadata and the partial results
@@ -60,7 +71,8 @@ public final class TotalCaptureResult extends CaptureResult {
     * @hide
     */
    public TotalCaptureResult(CameraMetadataNative results, CaptureRequest parent,
            CaptureResultExtras extras, List<CaptureResult> partials, int sessionId) {
            CaptureResultExtras extras, List<CaptureResult> partials, int sessionId,
            PhysicalCaptureResultInfo physicalResults[]) {
        super(results, parent, extras);

        if (partials == null) {
@@ -70,6 +82,12 @@ public final class TotalCaptureResult extends CaptureResult {
        }

        mSessionId = sessionId;

        mPhysicalCaptureResults = new HashMap<String, CameraMetadataNative>();
        for (PhysicalCaptureResultInfo onePhysicalResult : physicalResults) {
            mPhysicalCaptureResults.put(onePhysicalResult.getCameraId(),
                    onePhysicalResult.getCameraMetadata());
        }
    }

    /**
@@ -83,6 +101,7 @@ public final class TotalCaptureResult extends CaptureResult {

        mPartialResults = new ArrayList<>();
        mSessionId = CameraCaptureSession.SESSION_ID_NONE;
        mPhysicalCaptureResults = new HashMap<String, CameraMetadataNative>();
    }

    /**
@@ -111,4 +130,38 @@ public final class TotalCaptureResult extends CaptureResult {
    public int getSessionId() {
        return mSessionId;
    }

    /**
     * Get a capture result field value for a particular physical camera id.
     *
     * <p>The field definitions can be found in {@link CaptureResult}.</p>
     *
     * <p>This function can be called for logical camera devices, which are devices that have
     * REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA capability and calls to {@link
     * CameraCharacteristics#getPhysicalCameraIds} return a non-empty list of physical devices that
     * are backing the logical camera. The camera id included in physicalCameraId argument
     * selects an individual physical device, and returns its specific capture result field.</p>
     *
     * <p>This function should only be called if one or more streams from the underlying
     * 'physicalCameraId' was requested by the corresponding capture request.</p>
     *
     * @throws IllegalArgumentException if the key was not valid, or the physicalCameraId is not
     * applicable to the current camera, or a stream from 'physicalCameraId' is not requested by the
     * corresponding capture request.
     *
     * @param key The result field to read.
     * @param physicalCameraId The physical camera the result originates from.
     *
     * @return The value of that key, or {@code null} if the field is not set.
     */
    @Nullable
    public <T> T getPhysicalCameraKey(Key<T> key, @NonNull String physicalCameraId) {
        if (!mPhysicalCaptureResults.containsKey(physicalCameraId)) {
            throw new IllegalArgumentException(
                    "No TotalCaptureResult exists for physical camera " + physicalCameraId);
        }

        CameraMetadataNative physicalMetadata = mPhysicalCaptureResults.get(physicalCameraId);
        return physicalMetadata.get(key);
    }
}
+11 −9
Original line number Diff line number Diff line
@@ -1001,19 +1001,17 @@ public class CameraDeviceImpl extends CameraDevice
                    throw new IllegalArgumentException("Null Surface targets are not allowed");
                }

                if (!request.isReprocess()) {
                    continue;
                }
                for (int i = 0; i < mConfiguredOutputs.size(); i++) {
                    OutputConfiguration configuration = mConfiguredOutputs.valueAt(i);
                    if (configuration.isForPhysicalCamera()
                            && configuration.getSurfaces().contains(surface)) {
                        if (request.isReprocess()) {
                            throw new IllegalArgumentException(
                                    "Reprocess request on physical stream is not allowed");
                        }
                    }
                }

            }
        }

        synchronized(mInterfaceLock) {
@@ -1966,7 +1964,8 @@ public class CameraDeviceImpl extends CameraDevice

        @Override
        public void onResultReceived(CameraMetadataNative result,
                CaptureResultExtras resultExtras) throws RemoteException {
                CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[])
                throws RemoteException {

            int requestId = resultExtras.getRequestId();
            long frameNumber = resultExtras.getFrameNumber();
@@ -2073,7 +2072,8 @@ public class CameraDeviceImpl extends CameraDevice
                            request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
                    final int subsequenceId = resultExtras.getSubsequenceId();
                    final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
                            request, resultExtras, partialResults, holder.getSessionId());
                            request, resultExtras, partialResults, holder.getSessionId(),
                            physicalResults);
                    // Final capture result
                    resultDispatch = new Runnable() {
                        @Override
@@ -2088,9 +2088,11 @@ public class CameraDeviceImpl extends CameraDevice
                                                NANO_PER_SECOND/fpsRange.getUpper());
                                        CameraMetadataNative resultLocal =
                                                new CameraMetadataNative(resultCopy);
                                        // No logical multi-camera support for batched output mode.
                                        TotalCaptureResult resultInBatch = new TotalCaptureResult(
                                            resultLocal, holder.getRequest(i), resultExtras,
                                            partialResults, holder.getSessionId());
                                            partialResults, holder.getSessionId(),
                                            new PhysicalCaptureResultInfo[0]);

                                        holder.getCallback().onCaptureCompleted(
                                            CameraDeviceImpl.this,
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.hardware.camera2.impl;

import android.hardware.camera2.impl.CameraMetadataNative;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @hide
 */
public class PhysicalCaptureResultInfo implements Parcelable {
    private String cameraId;
    private CameraMetadataNative cameraMetadata;

    public static final Parcelable.Creator<PhysicalCaptureResultInfo> CREATOR =
            new Parcelable.Creator<PhysicalCaptureResultInfo>() {
        @Override
        public PhysicalCaptureResultInfo createFromParcel(Parcel in) {
            return new PhysicalCaptureResultInfo(in);
        }

        @Override
        public PhysicalCaptureResultInfo[] newArray(int size) {
            return new PhysicalCaptureResultInfo[size];
        }
    };

    private PhysicalCaptureResultInfo(Parcel in) {
        readFromParcel(in);
    }

    public PhysicalCaptureResultInfo(String cameraId, CameraMetadataNative cameraMetadata) {
        this.cameraId = cameraId;
        this.cameraMetadata = cameraMetadata;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(cameraId);
        cameraMetadata.writeToParcel(dest, flags);
    }

    public void readFromParcel(Parcel in) {
        cameraId = in.readString();
        cameraMetadata = new CameraMetadataNative();
        cameraMetadata.readFromParcel(in);
    }

    public String getCameraId() {
        return cameraId;
    }

    public CameraMetadataNative getCameraMetadata() {
        return cameraMetadata;
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.impl.PhysicalCaptureResultInfo;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.SubmitInfo;
import android.os.ConditionVariable;
@@ -249,7 +250,8 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {

        @Override
        public void onResultReceived(final CameraMetadataNative result,
                final CaptureResultExtras resultExtras) {
                final CaptureResultExtras resultExtras,
                PhysicalCaptureResultInfo physicalResults[]) {
            Object[] resultArray = new Object[] { result, resultExtras };
            Message msg = getHandler().obtainMessage(RESULT_RECEIVED,
                    /*obj*/ resultArray);
@@ -320,7 +322,8 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
                            Object[] resultArray = (Object[]) msg.obj;
                            CameraMetadataNative result = (CameraMetadataNative) resultArray[0];
                            CaptureResultExtras resultExtras = (CaptureResultExtras) resultArray[1];
                            mCallbacks.onResultReceived(result, resultExtras);
                            mCallbacks.onResultReceived(result, resultExtras,
                                    new PhysicalCaptureResultInfo[0]);
                            break;
                        }
                        case PREPARED: {
Loading