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

Commit e8c0483b authored by Kwangkyu Park's avatar Kwangkyu Park Committed by Emilian Peev
Browse files

Camera: Use characteristic from user app for extension

For the advanced extender, camera characteristics are provided from the
extension proxy service. However, the vendor key-values are ripped off
from the characteristics because the service does not hold the camera
permission.

To maintain consistency across the basic and advanced extender and
CameraX extension and Camera2 extension, this change will populate the
camera characteristics from the user app side.

Bug: 279854053
Test: Manual test with vendor key, Camera Extension CTS
Change-Id: Ic08751b824ea1cfa0208cf7246ab8c3ff7cd367c
parent bb0278a3
Loading
Loading
Loading
Loading
+47 −38
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.hardware.camera2.extension.IInitializeSessionCallback;
import android.hardware.camera2.extension.IPreviewExtenderImpl;
import android.hardware.camera2.extension.LatencyRange;
import android.hardware.camera2.extension.SizeList;
import android.hardware.camera2.impl.CameraExtensionUtils;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.ExtensionSessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
@@ -47,8 +48,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Future;
@@ -161,16 +164,19 @@ public final class CameraExtensionCharacteristics {

    private final Context mContext;
    private final String mCameraId;
    private final CameraCharacteristics mChars;
    private final Map<String, CameraCharacteristics> mCharacteristicsMap;
    private final Map<String, CameraMetadataNative> mCharacteristicsMapNative;

    /**
     * @hide
     */
    public CameraExtensionCharacteristics(Context context, String cameraId,
            CameraCharacteristics chars) {
            Map<String, CameraCharacteristics> characteristicsMap) {
        mContext = context;
        mCameraId = cameraId;
        mChars = chars;
        mCharacteristicsMap = characteristicsMap;
        mCharacteristicsMapNative =
                CameraExtensionUtils.getCharacteristicsMapNative(characteristicsMap);
    }

    private static ArrayList<Size> getSupportedSizes(List<SizeList> sizesList,
@@ -468,11 +474,11 @@ public final class CameraExtensionCharacteristics {
     * @hide
     */
    public static boolean isExtensionSupported(String cameraId, int extensionType,
            CameraCharacteristics chars) {
            Map<String, CameraMetadataNative> characteristicsMap) {
        if (areAdvancedExtensionsSupported()) {
            try {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extensionType);
                return extender.isExtensionAvailable(cameraId);
                return extender.isExtensionAvailable(cameraId, characteristicsMap);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to query extension availability! Extension service does not"
                        + " respond!");
@@ -487,8 +493,10 @@ public final class CameraExtensionCharacteristics {
            }

            try {
                return extenders.first.isExtensionAvailable(cameraId, chars.getNativeMetadata()) &&
                        extenders.second.isExtensionAvailable(cameraId, chars.getNativeMetadata());
                return extenders.first.isExtensionAvailable(cameraId,
                        characteristicsMap.get(cameraId))
                        && extenders.second.isExtensionAvailable(cameraId,
                        characteristicsMap.get(cameraId));
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to query extension availability! Extension service does not"
                        + " respond!");
@@ -563,7 +571,7 @@ public final class CameraExtensionCharacteristics {

        try {
            for (int extensionType : EXTENSION_LIST) {
                if (isExtensionSupported(mCameraId, extensionType, mChars)) {
                if (isExtensionSupported(mCameraId, extensionType, mCharacteristicsMapNative)) {
                    ret.add(extensionType);
                }
            }
@@ -597,18 +605,18 @@ public final class CameraExtensionCharacteristics {
        }

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                return extender.isPostviewAvailable();
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                return extenders.second.isPostviewAvailable();
            }
        } catch (RemoteException e) {
@@ -655,7 +663,7 @@ public final class CameraExtensionCharacteristics {
        }

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

@@ -664,7 +672,7 @@ public final class CameraExtensionCharacteristics {
            sz.width = captureSize.getWidth();
            sz.height = captureSize.getHeight();

            StreamConfigurationMap streamMap = mChars.get(
            StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            if (areAdvancedExtensionsSupported()) {
@@ -676,13 +684,13 @@ public final class CameraExtensionCharacteristics {
                        throw new IllegalArgumentException("Unsupported format: " + format);
                }
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                return generateSupportedSizes(extender.getSupportedPostviewResolutions(
                    sz), format, streamMap);
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                if ((extenders.second.getCaptureProcessor() == null) ||
                        !isPostviewAvailable(extension)) {
                    // Extensions that don't implement any capture processor
@@ -754,22 +762,23 @@ public final class CameraExtensionCharacteristics {
        }

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            StreamConfigurationMap streamMap = mChars.get(
            StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                return generateSupportedSizes(
                        extender.getSupportedPreviewOutputResolutions(mCameraId),
                        ImageFormat.PRIVATE, streamMap);
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.first.init(mCameraId, mChars.getNativeMetadata());
                extenders.first.init(mCameraId,
                        mCharacteristicsMapNative.get(mCameraId));
                return generateSupportedSizes(extenders.first.getSupportedResolutions(),
                        ImageFormat.PRIVATE, streamMap);
            }
@@ -811,11 +820,11 @@ public final class CameraExtensionCharacteristics {
            }

            try {
                if (!isExtensionSupported(mCameraId, extension, mChars)) {
                if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                    throw new IllegalArgumentException("Unsupported extension");
                }

                StreamConfigurationMap streamMap = mChars.get(
                StreamConfigurationMap streamMap = mCharacteristicsMap.get(mCameraId).get(
                        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                if (areAdvancedExtensionsSupported()) {
                    switch(format) {
@@ -826,14 +835,14 @@ public final class CameraExtensionCharacteristics {
                            throw new IllegalArgumentException("Unsupported format: " + format);
                    }
                    IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                    extender.init(mCameraId);
                    extender.init(mCameraId, mCharacteristicsMapNative);
                    return generateSupportedSizes(extender.getSupportedCaptureOutputResolutions(
                            mCameraId), format, streamMap);
                } else {
                    if (format == ImageFormat.YUV_420_888) {
                        Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                                initializeExtension(extension);
                        extenders.second.init(mCameraId, mChars.getNativeMetadata());
                        extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                        if (extenders.second.getCaptureProcessor() == null) {
                            // Extensions that don't implement any capture processor are limited to
                            // JPEG only!
@@ -844,7 +853,7 @@ public final class CameraExtensionCharacteristics {
                    } else if (format == ImageFormat.JPEG) {
                        Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                                initializeExtension(extension);
                        extenders.second.init(mCameraId, mChars.getNativeMetadata());
                        extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                        if (extenders.second.getCaptureProcessor() != null) {
                            // The framework will perform the additional encoding pass on the
                            // processed YUV_420 buffers.
@@ -900,7 +909,7 @@ public final class CameraExtensionCharacteristics {
        }

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

@@ -910,7 +919,7 @@ public final class CameraExtensionCharacteristics {
            sz.height = captureOutputSize.getHeight();
            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                LatencyRange latencyRange = extender.getEstimatedCaptureLatencyRange(mCameraId,
                        sz, format);
                if (latencyRange != null) {
@@ -919,7 +928,7 @@ public final class CameraExtensionCharacteristics {
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                if ((format == ImageFormat.YUV_420_888) &&
                        (extenders.second.getCaptureProcessor() == null) ){
                    // Extensions that don't implement any capture processor are limited to
@@ -965,18 +974,18 @@ public final class CameraExtensionCharacteristics {
        }

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                return extender.isCaptureProcessProgressAvailable();
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                return extenders.second.isCaptureProcessProgressAvailable();
            }
        } catch (RemoteException e) {
@@ -1012,20 +1021,20 @@ public final class CameraExtensionCharacteristics {
        HashSet<CaptureRequest.Key> ret = new HashSet<>();

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            CameraMetadataNative captureRequestMeta = null;
            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                captureRequestMeta = extender.getAvailableCaptureRequestKeys(mCameraId);
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.onInit(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                captureRequestMeta = extenders.second.getAvailableCaptureRequestKeys();
                extenders.second.onDeInit();
            }
@@ -1090,20 +1099,20 @@ public final class CameraExtensionCharacteristics {

        HashSet<CaptureResult.Key> ret = new HashSet<>();
        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
            if (!isExtensionSupported(mCameraId, extension, mCharacteristicsMapNative)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            CameraMetadataNative captureResultMeta = null;
            if (areAdvancedExtensionsSupported()) {
                IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
                extender.init(mCameraId);
                extender.init(mCameraId, mCharacteristicsMapNative);
                captureResultMeta = extender.getAvailableCaptureResultKeys(mCameraId);
            } else {
                Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                        initializeExtension(extension);
                extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
                extenders.second.init(mCameraId, mChars.getNativeMetadata());
                extenders.second.onInit(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                extenders.second.init(mCameraId, mCharacteristicsMapNative.get(mCameraId));
                captureResultMeta = extenders.second.getAvailableCaptureResultKeys();
                extenders.second.onDeInit();
            }
+4 −1
Original line number Diff line number Diff line
@@ -694,7 +694,10 @@ public final class CameraManager {
    public CameraExtensionCharacteristics getCameraExtensionCharacteristics(
            @NonNull String cameraId) throws CameraAccessException {
        CameraCharacteristics chars = getCameraCharacteristics(cameraId);
        return new CameraExtensionCharacteristics(mContext, cameraId, chars);
        Map<String, CameraCharacteristics> characteristicsMap = getPhysicalIdToCharsMap(chars);
        characteristicsMap.put(cameraId, chars);

        return new CameraExtensionCharacteristics(mContext, cameraId, characteristicsMap);
    }

    private Map<String, CameraCharacteristics> getPhysicalIdToCharsMap(
+4 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package android.hardware.camera2.extension;

import android.hardware.camera2.impl.CameraMetadataNative;

import android.hardware.camera2.extension.ISessionProcessorImpl;
import android.hardware.camera2.extension.LatencyRange;
import android.hardware.camera2.extension.Size;
@@ -24,8 +26,8 @@ import android.hardware.camera2.impl.CameraMetadataNative;
/** @hide */
interface IAdvancedExtenderImpl
{
    boolean isExtensionAvailable(in String cameraId);
    void init(in String cameraId);
    boolean isExtensionAvailable(in String cameraId, in Map<String, CameraMetadataNative> charsMap);
    void init(in String cameraId, in Map<String, CameraMetadataNative> charsMap);
    LatencyRange getEstimatedCaptureLatencyRange(in String cameraId, in Size outputSize,
            int format);
    @nullable List<SizeList> getSupportedPreviewOutputResolutions(in String cameraId);
+4 −1
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package android.hardware.camera2.extension;

import android.hardware.camera2.impl.CameraMetadataNative;

import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.extension.CameraSessionConfig;
import android.hardware.camera2.extension.ICaptureCallback;
@@ -26,7 +28,8 @@ import android.hardware.camera2.extension.OutputSurface;
/** @hide */
interface ISessionProcessorImpl
{
    CameraSessionConfig initSession(in String cameraId, in OutputSurface previewSurface,
    CameraSessionConfig initSession(in String cameraId,
            in Map<String, CameraMetadataNative> charsMap, in OutputSurface previewSurface,
            in OutputSurface imageCaptureSurface, in OutputSurface postviewSurface);
    void deInitSession();
    void onCaptureSessionStart(IRequestProcessorImpl requestProcessor);
+15 −11
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraExtensionCharacteristics;
import android.hardware.camera2.CameraExtensionSession;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
@@ -78,6 +77,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes

    private final Executor mExecutor;
    private final CameraDevice mCameraDevice;
    private final Map<String, CameraMetadataNative> mCharacteristicsMap;
    private final long mExtensionClientId;
    private final Handler mHandler;
    private final HandlerThread mHandlerThread;
@@ -109,6 +109,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
    @RequiresPermission(android.Manifest.permission.CAMERA)
    public static CameraAdvancedExtensionSessionImpl createCameraAdvancedExtensionSession(
            @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
            @NonNull Map<String, CameraCharacteristics> characteristicsMap,
            @NonNull Context ctx, @NonNull ExtensionSessionConfiguration config, int sessionId)
            throws CameraAccessException, RemoteException {
        long clientId = CameraExtensionCharacteristics.registerClient(ctx);
@@ -117,13 +118,13 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
        }

        String cameraId = cameraDevice.getId();
        CameraManager manager = ctx.getSystemService(CameraManager.class);
        CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
        CameraExtensionCharacteristics extensionChars = new CameraExtensionCharacteristics(ctx,
                cameraId, chars);
                cameraId, characteristicsMap);

        Map<String, CameraMetadataNative> characteristicsMapNative =
                CameraExtensionUtils.getCharacteristicsMapNative(characteristicsMap);
        if (!CameraExtensionCharacteristics.isExtensionSupported(cameraDevice.getId(),
                config.getExtension(), chars)) {
                config.getExtension(), characteristicsMapNative)) {
            throw new UnsupportedOperationException("Unsupported extension type: " +
                    config.getExtension());
        }
@@ -198,11 +199,12 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes

        IAdvancedExtenderImpl extender = CameraExtensionCharacteristics.initializeAdvancedExtension(
                config.getExtension());
        extender.init(cameraId);
        extender.init(cameraId, characteristicsMapNative);

        CameraAdvancedExtensionSessionImpl ret = new CameraAdvancedExtensionSessionImpl(clientId,
                extender, cameraDevice, repeatingRequestSurface, burstCaptureSurface,
                postviewSurface, config.getStateCallback(), config.getExecutor(), sessionId);
                extender, cameraDevice, characteristicsMapNative, repeatingRequestSurface,
                burstCaptureSurface, postviewSurface, config.getStateCallback(),
                config.getExecutor(), sessionId);
        ret.initialize();

        return ret;
@@ -210,14 +212,16 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes

    private CameraAdvancedExtensionSessionImpl(long extensionClientId,
            @NonNull IAdvancedExtenderImpl extender,
            @NonNull android.hardware.camera2.impl.CameraDeviceImpl cameraDevice,
            @NonNull CameraDeviceImpl cameraDevice,
            Map<String, CameraMetadataNative> characteristicsMap,
            @Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface,
            @Nullable Surface postviewSurface,
            @NonNull CameraExtensionSession.StateCallback callback, @NonNull Executor executor,
            @NonNull StateCallback callback, @NonNull Executor executor,
            int sessionId) {
        mExtensionClientId = extensionClientId;
        mAdvancedExtender = extender;
        mCameraDevice = cameraDevice;
        mCharacteristicsMap = characteristicsMap;
        mCallbacks = callback;
        mExecutor = executor;
        mClientRepeatingRequestSurface = repeatingRequestSurface;
@@ -247,7 +251,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes

        mSessionProcessor = mAdvancedExtender.getSessionProcessor();
        CameraSessionConfig sessionConfig = mSessionProcessor.initSession(mCameraDevice.getId(),
                previewSurface, captureSurface, postviewSurface);
                mCharacteristicsMap, previewSurface, captureSurface, postviewSurface);
        List<CameraOutputConfig> outputConfigs = sessionConfig.outputConfigs;
        ArrayList<OutputConfiguration> outputList = new ArrayList<>();
        for (CameraOutputConfig output : outputConfigs) {
Loading