10a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin/*
20a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Copyright (C) 2014 The Android Open Source Project
30a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin *
40a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
50a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * you may not use this file except in compliance with the License.
60a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * You may obtain a copy of the License at
70a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin *
80a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
90a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin *
100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Unless required by applicable law or agreed to in writing, software
110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * See the License for the specific language governing permissions and
140a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * limitations under the License.
150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */
160a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinpackage android.hardware.camera2.legacy;
180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
190a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.graphics.Rect;
200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.Camera;
210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.Camera.FaceDetectionListener;
220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.impl.CameraMetadataNative;
230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.legacy.ParameterUtils.ZoomData;
240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CameraCharacteristics;
250a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CaptureRequest;
260a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.CaptureResult;
270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.params.Face;
280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.utils.ListUtils;
290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.hardware.camera2.utils.ParamsUtils;
300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.util.Log;
310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport android.util.Size;
320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport com.android.internal.util.ArrayUtils;
340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.ArrayList;
360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.Arrays;
370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport java.util.List;
380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport static android.hardware.camera2.CaptureRequest.*;
400a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinimport static com.android.internal.util.Preconditions.*;
410a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
420a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin/**
430a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Map legacy face detect callbacks into face detection results.
440a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */
450a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin@SuppressWarnings("deprecation")
460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkinpublic class LegacyFaceDetectMapper {
470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private static String TAG = "LegacyFaceDetectMapper";
480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private final Camera mCamera;
518c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    /** Is the camera capable of face detection? */
520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private final boolean mFaceDetectSupported;
538c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    /** Is the camera is running face detection? */
540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private boolean mFaceDetectEnabled = false;
558c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    /** Did the last request say to use SCENE_MODE = FACE_PRIORITY? */
568c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    private boolean mFaceDetectScenePriority = false;
578c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    /** Did the last request enable the face detect mode to ON? */
588c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    private boolean mFaceDetectReporting = false;
590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
608c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin    /** Synchronize access to all fields */
610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private final Object mLock = new Object();
620a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private Camera.Face[] mFaces;
630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    private Camera.Face[] mFacesPrev;
640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    /**
650a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * Instantiate a new face detect mapper.
660a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
670a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param camera a non-{@code null} camera1 device
680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param characteristics a  non-{@code null} camera characteristics for that camera1
690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @throws NullPointerException if any of the args were {@code null}
710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     */
720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    public LegacyFaceDetectMapper(Camera camera, CameraCharacteristics characteristics) {
730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        mCamera = checkNotNull(camera, "camera must not be null");
740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        checkNotNull(characteristics, "characteristics must not be null");
750a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
760a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        mFaceDetectSupported = ArrayUtils.contains(
770a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                characteristics.get(
780a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES),
790a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                STATISTICS_FACE_DETECT_MODE_SIMPLE);
800a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (!mFaceDetectSupported) {
820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            return;
830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
840a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin       mCamera.setFaceDetectionListener(new FaceDetectionListener() {
860a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
870a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        @Override
880a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        public void onFaceDetection(Camera.Face[] faces, Camera camera) {
890a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            int lengthFaces = faces == null ? 0 : faces.length;
900a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            synchronized (mLock) {
910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                if (mFaceDetectEnabled) {
920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    mFaces = faces;
930a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                } else if (lengthFaces > 0) {
940a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    // stopFaceDetectMode could race against the requests, print a debug log
950a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    Log.d(TAG,
960a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            "onFaceDetection - Ignored some incoming faces since" +
970a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            "face detection was disabled");
980a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                }
990a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
1000a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1010a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (VERBOSE) {
1020a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                Log.v(TAG, "onFaceDetection - read " + lengthFaces + " faces");
1030a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
1040a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
1050a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin       });
1060a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    }
1070a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1080a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    /**
1090a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * Process the face detect mode from the capture request into an api1 face detect toggle.
1100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
1110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * <p>This method should be called after the parameters are {@link LegacyRequestMapper mapped}
1120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * with the request.</p>
1130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
1140a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * <p>Callbacks are processed in the background, and the next call to {@link #mapResultTriggers}
1150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * will have the latest faces detected as reflected by the camera1 callbacks.</p>
1160a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
1170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * <p>None of the arguments will be mutated.</p>
1180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
1190a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param captureRequest a non-{@code null} request
1200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param parameters a non-{@code null} parameters corresponding to this request (read-only)
1210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     */
1220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    public void processFaceDetectMode(CaptureRequest captureRequest,
1230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            Camera.Parameters parameters) {
1240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        checkNotNull(captureRequest, "captureRequest must not be null");
1250a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1260a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        /*
1270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin         * statistics.faceDetectMode
1280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin         */
1290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int fdMode = ParamsUtils.getOrDefault(captureRequest, STATISTICS_FACE_DETECT_MODE,
1300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                STATISTICS_FACE_DETECT_MODE_OFF);
1310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (fdMode != STATISTICS_FACE_DETECT_MODE_OFF && !mFaceDetectSupported) {
1330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            Log.w(TAG,
1340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    "processFaceDetectMode - Ignoring statistics.faceDetectMode; " +
1350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    "face detection is not available");
1360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            return;
1370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
1380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1398c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        /*
1408c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin         * control.sceneMode
1418c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin         */
1428c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        int sceneMode = ParamsUtils.getOrDefault(captureRequest, CONTROL_SCENE_MODE,
1438c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin                CONTROL_SCENE_MODE_DISABLED);
1448c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        if (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY && !mFaceDetectSupported) {
1458c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            Log.w(TAG, "processFaceDetectMode - ignoring control.sceneMode == FACE_PRIORITY; " +
1468c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin                    "face detection is not available");
1478c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            return;
1488c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        }
1498c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin
1500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        // Print some warnings out in case the values were wrong
1510a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        switch (fdMode) {
1520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            case STATISTICS_FACE_DETECT_MODE_OFF:
1530a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            case STATISTICS_FACE_DETECT_MODE_SIMPLE:
1540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                break;
1550a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            case STATISTICS_FACE_DETECT_MODE_FULL:
1560a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                Log.w(TAG,
1570a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        "processFaceDetectMode - statistics.faceDetectMode == FULL unsupported, " +
1580a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        "downgrading to SIMPLE");
1590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                break;
1600a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            default:
1610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                Log.w(TAG, "processFaceDetectMode - ignoring unknown statistics.faceDetectMode = "
1620a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        + fdMode);
1630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                return;
1640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
1650a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1668c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        boolean enableFaceDetect = (fdMode != STATISTICS_FACE_DETECT_MODE_OFF)
1678c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin                || (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY);
1680a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        synchronized (mLock) {
1690a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            // Enable/disable face detection if it's changed since last time
1700a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            if (enableFaceDetect != mFaceDetectEnabled) {
1710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                if (enableFaceDetect) {
1720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    mCamera.startFaceDetection();
1730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    if (VERBOSE) {
1750a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        Log.v(TAG, "processFaceDetectMode - start face detection");
1760a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    }
1770a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                } else {
1780a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    mCamera.stopFaceDetection();
1790a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1800a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    if (VERBOSE) {
1810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                        Log.v(TAG, "processFaceDetectMode - stop face detection");
1820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    }
1830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1840a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    mFaces = null;
1850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                }
1860a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1870a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                mFaceDetectEnabled = enableFaceDetect;
1888c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin                mFaceDetectScenePriority = sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY;
1898c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin                mFaceDetectReporting = fdMode != STATISTICS_FACE_DETECT_MODE_OFF;
1900a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
1910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
1920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    }
1930a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
1940a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    /**
1950a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * Update the {@code result} camera metadata map with the new value for the
1960a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * {@code statistics.faces} and {@code statistics.faceDetectMode}.
1970a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
1980a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * <p>Face detect callbacks are processed in the background, and each call to
1990a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * {@link #mapResultFaces} will have the latest faces as reflected by the camera1 callbacks.</p>
2000a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     *
2018c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin     * <p>If the scene mode was set to {@code FACE_PRIORITY} but face detection is disabled,
2028c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin     * the camera will still run face detection in the background, but no faces will be reported
2038c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin     * in the capture result.</p>
2048c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin     *
2050a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param result a non-{@code null} result
2060a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     * @param legacyRequest a non-{@code null} request (read-only)
2070a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin     */
2080a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    public void mapResultFaces(CameraMetadataNative result, LegacyRequest legacyRequest) {
2090a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        checkNotNull(result, "result must not be null");
2100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        checkNotNull(legacyRequest, "legacyRequest must not be null");
2110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        Camera.Face[] faces, previousFaces;
2130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        int fdMode;
2148c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        boolean fdScenePriority;
2150a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        synchronized (mLock) {
2168c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            fdMode = mFaceDetectReporting ?
2170a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            STATISTICS_FACE_DETECT_MODE_SIMPLE : STATISTICS_FACE_DETECT_MODE_OFF;
2180a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2198c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            if (mFaceDetectReporting) {
2200a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faces = mFaces;
2210a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            } else {
2220a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                faces = null;
2230a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
2240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2258c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            fdScenePriority = mFaceDetectScenePriority;
2268c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin
2270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            previousFaces = mFacesPrev;
2280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            mFacesPrev = faces;
2290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
2300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        CameraCharacteristics characteristics = legacyRequest.characteristics;
2320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        CaptureRequest request = legacyRequest.captureRequest;
2330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        Size previewSize = legacyRequest.previewSize;
2340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        Camera.Parameters params = legacyRequest.parameters;
2350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
2370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        ZoomData zoomData = ParameterUtils.convertScalerCropRegion(activeArray,
2380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                request.get(CaptureRequest.SCALER_CROP_REGION), previewSize, params);
2390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2400a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        List<Face> convertedFaces = new ArrayList<>();
2410a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (faces != null) {
2420a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            for (Camera.Face face : faces) {
2430a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                if (face != null) {
2440a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    convertedFaces.add(
2450a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                            ParameterUtils.convertFaceFromLegacy(face, activeArray, zoomData));
2460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                } else {
2470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                    Log.w(TAG, "mapResultFaces - read NULL face from camera1 device");
2480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin                }
2490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            }
2500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
2510a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2520a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        if (VERBOSE && previousFaces != faces) { // Log only in verbose and IF the faces changed
2530a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin            Log.v(TAG, "mapResultFaces - changed to " + ListUtils.listToString(convertedFaces));
2540a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        }
2550a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin
2560a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        result.set(CaptureResult.STATISTICS_FACES, convertedFaces.toArray(new Face[0]));
2570a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin        result.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, fdMode);
2588c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin
2598c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        // Override scene mode with FACE_PRIORITY if the request was using FACE_PRIORITY
2608c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        if (fdScenePriority) {
2618c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin            result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_FACE_PRIORITY);
2628c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin        }
2630a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin    }
2640a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin}
265