11903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh/*
21903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * Copyright (C) 2018 The Android Open Source Project
31903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh *
41903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * Licensed under the Apache License, Version 2.0 (the "License");
51903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * you may not use this file except in compliance with the License.
61903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * You may obtain a copy of the License at
71903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh *
81903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh *      http://www.apache.org/licenses/LICENSE-2.0
91903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh *
101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * Unless required by applicable law or agreed to in writing, software
111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * distributed under the License is distributed on an "AS IS" BASIS,
121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * See the License for the specific language governing permissions and
141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh * limitations under the License.
151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh */
161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#define LOG_TAG "ExtCamDev@3.4"
1853f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh//#define LOG_NDEBUG 0
191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include <log/log.h>
201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2153f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh#include <algorithm>
221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include <array>
231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include <linux/videodev2.h>
241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include "android-base/macros.h"
251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include "CameraMetadata.h"
261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include "../../3.2/default/include/convert.h"
271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#include "ExternalCameraDevice_3_4.h"
281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace android {
301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace hardware {
311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace camera {
321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace device {
331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace V3_4 {
341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace implementation {
351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehnamespace {
371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh// Only support MJPEG for now as it seems to be the one supports higher fps
381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh// Other formats to consider in the future:
391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh// * V4L2_PIX_FMT_YVU420 (== YV12)
401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehconst std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
421903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    V4L2_PIX_FMT_MJPEG
431903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}}; // double braces required in C++11
441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
452d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yehconstexpr int MAX_RETRY = 5; // Allow retry v4l2 open failures a few times.
462d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yehconstexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds
472d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh
481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh} // anonymous namespace
491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
501798249b8f8a47bab9e7b96ef4ec1b13ae76aa6fYin-Chia YehExternalCameraDevice::ExternalCameraDevice(
511798249b8f8a47bab9e7b96ef4ec1b13ae76aa6fYin-Chia Yeh            const std::string& cameraId, const ExternalCameraConfig& cfg) :
5253f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh        mCameraId(cameraId),
531798249b8f8a47bab9e7b96ef4ec1b13ae76aa6fYin-Chia Yeh        mCfg(cfg) {
5453f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    status_t ret = initCameraCharacteristics();
561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (ret != OK) {
571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        mInitFailed = true;
591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehExternalCameraDevice::~ExternalCameraDevice() {}
631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehbool ExternalCameraDevice::isInitFailed() {
651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return mInitFailed;
661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehReturn<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    CameraResourceCost resCost;
701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    resCost.resourceCost = 100;
711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    _hidl_cb(Status::OK, resCost);
721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return Void();
731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehReturn<void> ExternalCameraDevice::getCameraCharacteristics(
761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        getCameraCharacteristics_cb _hidl_cb) {
771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    Mutex::Autolock _l(mLock);
781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    V3_2::CameraMetadata hidlChars;
791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (isInitFailed()) {
811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::INTERNAL_ERROR, hidlChars);
821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    _hidl_cb(Status::OK, hidlChars);
881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    mCameraCharacteristics.unlock(rawMetadata);
891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return Void();
901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehReturn<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return Status::METHOD_NOT_SUPPORTED;
941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehReturn<void> ExternalCameraDevice::open(
971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    Status status = Status::OK;
991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    sp<ExternalCameraDeviceSession> session = nullptr;
1001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (callback == nullptr) {
1021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: cannot open camera %s. callback is null!",
1031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                __FUNCTION__, mCameraId.c_str());
1041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
1051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (isInitFailed()) {
1091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: cannot open camera %s. camera init failed!",
1101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                __FUNCTION__, mCameraId.c_str());
1111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
1121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    mLock.lock();
1161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
1181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    session = mSession.promote();
1191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (session != nullptr && !session->isClosed()) {
1201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
1211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        mLock.unlock();
1221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::CAMERA_IN_USE, nullptr);
1231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
1271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (fd.get() < 0) {
1282d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh        int numAttempt = 0;
1292d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh        do {
1302d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            ALOGW("%s: v4l2 device %s open failed, wait 33ms and try again",
1312d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh                    __FUNCTION__, mCameraId.c_str());
1322d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            usleep(OPEN_RETRY_SLEEP_US); // sleep and try again
1332d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            fd.reset(::open(mCameraId.c_str(), O_RDWR));
1342d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            numAttempt++;
1352d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh        } while (fd.get() < 0 && numAttempt <= MAX_RETRY);
1362d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh
1372d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh        if (fd.get() < 0) {
1382d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            ALOGE("%s: v4l2 device open %s failed: %s",
1392d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh                    __FUNCTION__, mCameraId.c_str(), strerror(errno));
1402d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            mLock.unlock();
1412d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
1422d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh            return Void();
1432d61bfd2b0faee0a8daddfdec1fe0541d0e16f71Yin-Chia Yeh        }
1441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1451903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1461903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    session = new ExternalCameraDeviceSession(
14753f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh            callback, mCfg, mSupportedFormats, mCroppingType,
1484a3393cd8aaf5eeb6ff037368ebd03f540da208fYin-Chia Yeh            mCameraCharacteristics, mCameraId, std::move(fd));
1491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (session == nullptr) {
1501903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: camera device session allocation failed", __FUNCTION__);
1511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        mLock.unlock();
1521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
1531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (session->isInitFailed()) {
1561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: camera device session init failed", __FUNCTION__);
1571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        session = nullptr;
1581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        mLock.unlock();
1591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
1601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    mSession = session;
1631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    mLock.unlock();
1651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    _hidl_cb(status, session->getInterface());
1671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return Void();
1681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
1691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia YehReturn<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
1711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    Mutex::Autolock _l(mLock);
1721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (handle.getNativeHandle() == nullptr) {
1731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: handle must not be null", __FUNCTION__);
1741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (handle->numFds != 1 || handle->numInts != 0) {
1771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
1781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                __FUNCTION__, handle->numFds, handle->numInts);
1791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int fd = handle->data[0];
1821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (mSession == nullptr) {
1831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        dprintf(fd, "No active camera device session instance\n");
1841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    auto session = mSession.promote();
1871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (session == nullptr) {
1881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        dprintf(fd, "No active camera device session instance\n");
1891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return Void();
1901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
1911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // Call into active session to dump states
1921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    session->dumpState(handle);
1931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return Void();
1941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
1951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
1971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehstatus_t ExternalCameraDevice::initCameraCharacteristics() {
1981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (mCameraCharacteristics.isEmpty()) {
1991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        // init camera characteristics
2001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
2011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (fd.get() < 0) {
2021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
2031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            return DEAD_OBJECT;
2041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
2051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        status_t ret;
2071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ret = initDefaultCharsKeys(&mCameraCharacteristics);
2081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (ret != OK) {
2091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
2101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            mCameraCharacteristics.clear();
2111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            return ret;
2121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
2131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
2151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (ret != OK) {
2161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
2171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            mCameraCharacteristics.clear();
2181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            return ret;
2191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
2201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
2221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (ret != OK) {
2231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
2241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            mCameraCharacteristics.clear();
2251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            return ret;
2261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
2271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
2281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return OK;
2291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
2301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
2321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#define UPDATE(tag, data, size)                    \
2331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehdo {                                               \
2341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh  if (metadata->update((tag), (data), (size))) {   \
2351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    ALOGE("Update " #tag " failed!");              \
2361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return -EINVAL;                                \
2371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh  }                                                \
2381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh} while (0)
2391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehstatus_t ExternalCameraDevice::initDefaultCharsKeys(
2411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
2424acd76e647a0e229fda04c244eedb80e3218795dYin-Chia Yeh    const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL;
2431903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
2441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2451903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.colorCorrection
2461903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availableAberrationModes[] = {
2471903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
2481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
2491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
2501903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.control
2521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t antibandingMode =
2531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
2541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
2551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &antibandingMode, 1);
2561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
2581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
2591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(controlMaxRegions));
2601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t videoStabilizationMode =
2621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
2631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
2641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &videoStabilizationMode, 1);
2651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
2671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
2681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
2701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
2711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
2731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
2741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
2761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                                             ANDROID_CONTROL_MODE_AUTO};
2771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
2781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(controlAvailableModes));
2791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.edge
2811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
2821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
2831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.flash
2851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
2861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
2871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.hotPixel
2891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
2901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
2911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
2921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.jpeg
2931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
2941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
2951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
2961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(jpegAvailableThumbnailSizes));
2971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
29853f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh    const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
2991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
3001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.lens
3021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t focusDistanceCalibration =
3031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
3041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
3051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t opticalStabilizationMode =
3071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
3081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
3091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &opticalStabilizationMode, 1);
3101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
3121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_LENS_FACING, &facing, 1);
3131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.noiseReduction
3151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
3161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
3171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &noiseReductionMode, 1);
3181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
3191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.request
3211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availableCapabilities[] = {
3221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
3231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
3241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(availableCapabilities));
3251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t partialResultCount = 1;
3271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
3281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // This means pipeline latency of X frame intervals. The maximum number is 4.
3301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t requestPipelineMaxDepth = 4;
3311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
3321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // Three numbers represent the maximum numbers of different types of output
3341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // streams simultaneously. The types are raw sensor, processed (but not
3351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // stalling), and processed (but stalling). For usb limited mode, raw sensor
3361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // is not supported. Stalling stream is JPEG. Non-stalling streams are
3371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // YUV_420_888 or YV12.
3381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t requestMaxNumOutputStreams[] = {
3391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            /*RAW*/0,
3401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            /*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
3411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            /*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
3421903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
3431903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(requestMaxNumOutputStreams));
3441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3451903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // Limited mode doesn't support reprocessing.
3461903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t requestMaxNumInputStreams = 0;
3471903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
3481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           1);
3491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3501903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.scaler
3511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: b/72263447 V4L2_CID_ZOOM_*
3521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const float scalerAvailableMaxDigitalZoom[] = {1};
3531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
3541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           scalerAvailableMaxDigitalZoom,
3551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
3561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
3581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
3591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t testPatternModes[] = {
3611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
3621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
3631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(testPatternModes));
3641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
3661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
3671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // Orientation probably isn't useful for external facing camera?
3691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t orientation = 0;
3701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
3711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.shading
3731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
3741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
3751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.statistics
3771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
3781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
3791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           1);
3801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t maxFaceCount = 0;
3821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
3831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availableHotpixelMode =
3851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
3861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
3871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &availableHotpixelMode, 1);
3881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t lensShadingMapMode =
3901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
3911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
3921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           &lensShadingMapMode, 1);
3931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.sync
3951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
3961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
3971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
3981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    /* Other sensor/RAW realted keys:
3991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
4001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.physicalSize           -> not available
4011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.whiteLevel             -> not available/not needed
4021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.lensShadingApplied     -> not needed
4031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
4041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.blackLevelPattern           -> not available/not needed
4051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     */
4061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
4071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t availableRequestKeys[] = {
4081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
4091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_ANTIBANDING_MODE,
4101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
4111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_LOCK,
4121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_MODE,
4131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
4141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_MODE,
4161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_TRIGGER,
4171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_LOCK,
4181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_MODE,
4191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_CAPTURE_INTENT,
4201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_EFFECT_MODE,
4211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_MODE,
4221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_SCENE_MODE,
4231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
4241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_FLASH_MODE,
4251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_ORIENTATION,
4261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_QUALITY,
4271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_THUMBNAIL_QUALITY,
4281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_THUMBNAIL_SIZE,
4291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
4301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_NOISE_REDUCTION_MODE,
4311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SCALER_CROP_REGION,
4321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_TEST_PATTERN_MODE,
4331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_FACE_DETECT_MODE,
4341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
4351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
4361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(availableRequestKeys));
4371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
4381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t availableResultKeys[] = {
4391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
4401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_ANTIBANDING_MODE,
4411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
4421903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_LOCK,
4431903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_MODE,
4441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
4451903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_STATE,
4461903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
4471903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_MODE,
4481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_STATE,
4491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_TRIGGER,
4501903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_LOCK,
4511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_MODE,
4521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_STATE,
4531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_CAPTURE_INTENT,
4541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_EFFECT_MODE,
4551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_MODE,
4561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_SCENE_MODE,
4571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
4581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_FLASH_MODE,
4591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_FLASH_STATE,
4601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_ORIENTATION,
4611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_QUALITY,
4621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_THUMBNAIL_QUALITY,
4631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_THUMBNAIL_SIZE,
4641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
4651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_NOISE_REDUCTION_MODE,
4661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_PIPELINE_DEPTH,
4671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SCALER_CROP_REGION,
4681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_TIMESTAMP,
4691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_FACE_DETECT_MODE,
4701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
4711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
4721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_SCENE_FLICKER};
4731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys,
4741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(availableResultKeys));
4751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
4761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t availableCharacteristicsKeys[] = {
4771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
4781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
4791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_AVAILABLE_MODES,
4801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
4811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_COMPENSATION_RANGE,
4821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_COMPENSATION_STEP,
4831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AE_LOCK_AVAILABLE,
4841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AF_AVAILABLE_MODES,
4851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AVAILABLE_EFFECTS,
4861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AVAILABLE_MODES,
4871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
4881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
4891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_AVAILABLE_MODES,
4901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
4911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_CONTROL_MAX_REGIONS,
4921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_FLASH_INFO_AVAILABLE,
4931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
4941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
4951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_FACING,
4961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
4971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
4981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
4991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
5001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
5011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
5021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
5031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
5041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
5051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
5061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SCALER_CROPPING_TYPE,
5071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
5081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
5091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
5101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
5111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
5121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SENSOR_ORIENTATION,
5131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SHADING_AVAILABLE_MODES,
5141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
5151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
5161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
5171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
5181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ANDROID_SYNC_MAX_LATENCY};
5191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
5201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           availableCharacteristicsKeys,
5211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(availableCharacteristicsKeys));
5221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return OK;
5241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
5251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehstatus_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
5271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
5281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    /**
5291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.sensitivityRange   -> V4L2_CID_ISO_SENSITIVITY
5301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.exposureTimeRange  -> V4L2_CID_EXPOSURE_ABSOLUTE
5311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.sensor.info.maxFrameDuration   -> TBD
5321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
5331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.lens.info.hyperfocalDistance
5341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     * android.lens.info.availableFocalLengths -> not available?
5351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh     */
5361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // android.control
5381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // No AE compensation support for now.
5391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: V4L2_CID_EXPOSURE_BIAS
5401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const int32_t controlAeCompensationRange[] = {0, 0};
5411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
5421903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(controlAeCompensationRange));
5431903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
5441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
5451903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(controlAeCompensationStep));
5461903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5471903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: Check V4L2_CID_AUTO_FOCUS_*.
5491903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
5501903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                                        ANDROID_CONTROL_AF_MODE_OFF};
5511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
5521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(afAvailableModes));
5531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: V4L2_CID_SCENE_MODE
5551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
5561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
5571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: V4L2_CID_3A_LOCK
5591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
5601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
5611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
5621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
5631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    // TODO: V4L2_CID_ZOOM_*
5651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    const float scalerAvailableMaxDigitalZoom[] = {1};
5661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
5671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           scalerAvailableMaxDigitalZoom,
5681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
5691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return OK;
5711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
5721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehstatus_t ExternalCameraDevice::initOutputCharsKeys(int fd,
5741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
5751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    initSupportedFormatsLocked(fd);
5761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (mSupportedFormats.empty()) {
5771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: Init supported format list failed", __FUNCTION__);
5781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        return UNKNOWN_ERROR;
5791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
5801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::vector<int32_t> streamConfigurations;
5821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::vector<int64_t> minFrameDurations;
5831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::vector<int64_t> stallDurations;
5841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int32_t maxFps = std::numeric_limits<int32_t>::min();
5851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int32_t minFps = std::numeric_limits<int32_t>::max();
5861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::set<int32_t> framerates;
5871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::array<int, /*size*/3> halFormats{{
5891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        HAL_PIXEL_FORMAT_BLOB,
5901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        HAL_PIXEL_FORMAT_YCbCr_420_888,
5911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
5921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
5931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    for (const auto& supportedFormat : mSupportedFormats) {
5941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        for (const auto& format : halFormats) {
5951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            streamConfigurations.push_back(format);
5961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            streamConfigurations.push_back(supportedFormat.width);
5971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            streamConfigurations.push_back(supportedFormat.height);
5981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            streamConfigurations.push_back(
5991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
6001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
6011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
602134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh        int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
603134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh        for (const auto& fr : supportedFormat.frameRates) {
604134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            // 1000000000LL < (2^32 - 1) and
605134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            // fr.durationNumerator is uint32_t, so no overflow here
606134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            int64_t frameDuration = 1000000000LL * fr.durationNumerator /
607134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                    fr.durationDenominator;
608134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            if (frameDuration < minFrameDuration) {
609134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                minFrameDuration = frameDuration;
6101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            }
611134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
6121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            if (minFps > frameRateInt) {
6131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                minFps = frameRateInt;
6141903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            }
6151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            if (maxFps < frameRateInt) {
6161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                maxFps = frameRateInt;
6171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            }
6181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            framerates.insert(frameRateInt);
6191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
6201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        for (const auto& format : halFormats) {
6221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            minFrameDurations.push_back(format);
6231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            minFrameDurations.push_back(supportedFormat.width);
6241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            minFrameDurations.push_back(supportedFormat.height);
625134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh            minFrameDurations.push_back(minFrameDuration);
6261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
6271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
6291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        // duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
6301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        // TODO: b/72261675. Maybe set this dynamically
6311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        for (const auto& format : halFormats) {
6321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            const int64_t NS_TO_SECOND = 1000000000;
6331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            int64_t stall_duration =
6341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    (format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
6351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            stallDurations.push_back(format);
6361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            stallDurations.push_back(supportedFormat.width);
6371903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            stallDurations.push_back(supportedFormat.height);
6381903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            stallDurations.push_back(stall_duration);
6391903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
6401903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
6411903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6421903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    std::vector<int32_t> fpsRanges;
6438b699aaf374f3b17219d1bfd3d97346c0635541aYin-Chia Yeh    // FPS ranges
6441903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    for (const auto& framerate : framerates) {
6458b699aaf374f3b17219d1bfd3d97346c0635541aYin-Chia Yeh        // Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
6468b699aaf374f3b17219d1bfd3d97346c0635541aYin-Chia Yeh        fpsRanges.push_back(framerate / 2);
6471903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        fpsRanges.push_back(framerate);
6481903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
649c15a1cab6f7ac4ba7cd30cf7441aa08423c228aeYin-Chia Yeh    minFps /= 2;
650c15a1cab6f7ac4ba7cd30cf7441aa08423c228aeYin-Chia Yeh    int64_t maxFrameDuration = 1000000000LL / minFps;
6518b699aaf374f3b17219d1bfd3d97346c0635541aYin-Chia Yeh
6521903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
6531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           fpsRanges.size());
6541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
6561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           streamConfigurations.data(), streamConfigurations.size());
6571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
6591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           minFrameDurations.data(), minFrameDurations.size());
6601903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6611903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
6621903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           stallDurations.size());
6631903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6641903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
6651903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6661903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
6671903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    for (const auto& supportedFormat : mSupportedFormats) {
6681903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (supportedFormat.width >= maximumFormat.width &&
6691903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            supportedFormat.height >= maximumFormat.height) {
6701903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            maximumFormat = supportedFormat;
6711903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
6721903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
6731903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int32_t activeArraySize[] = {0, 0,
6741903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                                 static_cast<int32_t>(maximumFormat.width),
6751903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                                 static_cast<int32_t>(maximumFormat.height)};
6761903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
6771903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           activeArraySize, ARRAY_SIZE(activeArraySize));
6781903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
6791903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(activeArraySize));
6801903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6811903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
6821903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                                static_cast<int32_t>(maximumFormat.height)};
6831903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
6841903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh           ARRAY_SIZE(pixelArraySize));
6851903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    return OK;
6861903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
6871903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6881903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#undef ARRAY_SIZE
6891903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh#undef UPDATE
6901903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6911903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yehvoid ExternalCameraDevice::getFrameRateList(
6923aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        int fd, double fpsUpperBound, SupportedV4L2Format* format) {
6931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    format->frameRates.clear();
6941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
6951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    v4l2_frmivalenum frameInterval {
6961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .pixel_format = format->fourcc,
6971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .width = format->width,
6981903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .height = format->height,
6991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .index = 0
7001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    };
7011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
7021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    for (frameInterval.index = 0;
7031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
7041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            ++frameInterval.index) {
7051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
7061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            if (frameInterval.discrete.numerator != 0) {
707134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                SupportedV4L2Format::FrameRate fr = {
708134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                        frameInterval.discrete.numerator,
709134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                        frameInterval.discrete.denominator};
710134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                double framerate = fr.getDouble();
71153f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                if (framerate > fpsUpperBound) {
71253f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                    continue;
71353f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                }
7143aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
7151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    frameInterval.index,
7161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    frameInterval.pixel_format & 0xFF,
7171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    (frameInterval.pixel_format >> 8) & 0xFF,
7181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    (frameInterval.pixel_format >> 16) & 0xFF,
7191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    (frameInterval.pixel_format >> 24) & 0xFF,
7201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    frameInterval.width, frameInterval.height, framerate);
721134093a43fa3430c913eb3b48726c42510a1e6adYin-Chia Yeh                format->frameRates.push_back(fr);
7221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            }
7231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
7241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
7251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
7261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    if (format->frameRates.empty()) {
7271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
7281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                __FUNCTION__,
7291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                frameInterval.pixel_format & 0xFF,
7301903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (frameInterval.pixel_format >> 8) & 0xFF,
7311903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (frameInterval.pixel_format >> 16) & 0xFF,
7321903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (frameInterval.pixel_format >> 24) & 0xFF,
7331903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                frameInterval.width, frameInterval.height);
7341903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
7351903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
7361903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
7373aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yehvoid ExternalCameraDevice::trimSupportedFormats(
7383aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        CroppingType cropType,
7393aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        /*inout*/std::vector<SupportedV4L2Format>* pFmts) {
7403aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    std::vector<SupportedV4L2Format>& sortedFmts = *pFmts;
7413aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    if (cropType == VERTICAL) {
7423aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        std::sort(sortedFmts.begin(), sortedFmts.end(),
7433aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
7443aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    if (a.width == b.width) {
7453aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                        return a.height < b.height;
7463aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    }
7473aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    return a.width < b.width;
7483aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                });
7493aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    } else {
7503aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        std::sort(sortedFmts.begin(), sortedFmts.end(),
7513aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                [](const SupportedV4L2Format& a, const SupportedV4L2Format& b) -> bool {
7523aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    if (a.height == b.height) {
7533aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                        return a.width < b.width;
7543aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    }
7553aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                    return a.height < b.height;
7563aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                });
7573aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    }
7583aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
7593aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    if (sortedFmts.size() == 0) {
7603aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        ALOGE("%s: input format list is empty!", __FUNCTION__);
7613aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        return;
7623aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    }
7633aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
76453f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh    const auto& maxSize = sortedFmts[sortedFmts.size() - 1];
76553f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh    float maxSizeAr = ASPECT_RATIO(maxSize);
7663aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
7673aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    // Remove formats that has aspect ratio not croppable from largest size
7683aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    std::vector<SupportedV4L2Format> out;
76953f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh    for (const auto& fmt : sortedFmts) {
77053f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh        float ar = ASPECT_RATIO(fmt);
7713aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        if (isAspectRatioClose(ar, maxSizeAr)) {
7723aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            out.push_back(fmt);
7733aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        } else if (cropType == HORIZONTAL && ar < maxSizeAr) {
7743aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            out.push_back(fmt);
7753aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        } else if (cropType == VERTICAL && ar > maxSizeAr) {
7763aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            out.push_back(fmt);
77753f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh        } else {
7783aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            ALOGV("%s: size (%d,%d) is removed due to unable to crop %s from (%d,%d)",
7793aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                __FUNCTION__, fmt.width, fmt.height,
7803aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                cropType == VERTICAL ? "vertically" : "horizontally",
7813aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                maxSize.width, maxSize.height);
78253f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh        }
78353f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh    }
7843aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    sortedFmts = out;
78553f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh}
78653f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
7873aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yehstd::vector<SupportedV4L2Format>
7883aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia YehExternalCameraDevice::getCandidateSupportedFormatsLocked(
7893aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        int fd, CroppingType cropType,
7903aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits) {
7913aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    std::vector<SupportedV4L2Format> outFmts;
7921903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    struct v4l2_fmtdesc fmtdesc {
7931903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .index = 0,
7941903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        .type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
7951903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    int ret = 0;
7961903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    while (ret == 0) {
7971903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
7983aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        ALOGV("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
7991903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                fmtdesc.pixelformat & 0xFF,
8001903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (fmtdesc.pixelformat >> 8) & 0xFF,
8011903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (fmtdesc.pixelformat >> 16) & 0xFF,
8021903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                (fmtdesc.pixelformat >> 24) & 0xFF);
8031903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
8041903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            auto it = std::find (
8051903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
8061903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            if (it != kSupportedFourCCs.end()) {
8071903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                // Found supported format
8081903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                v4l2_frmsizeenum frameSize {
8091903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        .index = 0,
8101903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        .pixel_format = fmtdesc.pixelformat};
8111903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
8121903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        ++frameSize.index) {
8131903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
81453f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                        ALOGV("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
8151903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            fmtdesc.pixelformat & 0xFF,
8161903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            (fmtdesc.pixelformat >> 8) & 0xFF,
8171903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            (fmtdesc.pixelformat >> 16) & 0xFF,
8181903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            (fmtdesc.pixelformat >> 24) & 0xFF,
8191903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            frameSize.discrete.width, frameSize.discrete.height);
8201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        // Disregard h > w formats so all aspect ratio (h/w) <= 1.0
8211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        // This will simplify the crop/scaling logic down the road
8221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        if (frameSize.discrete.height > frameSize.discrete.width) {
8231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            continue;
8241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        }
8251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        SupportedV4L2Format format {
8261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            .width = frameSize.discrete.width,
8271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            .height = frameSize.discrete.height,
8281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                            .fourcc = fmtdesc.pixelformat
8291903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        };
83053f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
8313aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                        double fpsUpperBound = -1.0;
8323aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                        for (const auto& limit : fpsLimits) {
8333aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                            if (cropType == VERTICAL) {
8343aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                if (format.width <= limit.size.width) {
8353aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                    fpsUpperBound = limit.fpsUpperBound;
8363aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                    break;
8373aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                }
8383aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                            } else { // HORIZONTAL
8393aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                if (format.height <= limit.size.height) {
8403aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                    fpsUpperBound = limit.fpsUpperBound;
8413aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                    break;
8423aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                                }
84353f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                            }
8443aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
84553f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                        }
84653f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                        if (fpsUpperBound < 0.f) {
84753f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                            continue;
84853f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                        }
84953f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
85053f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh                        getFrameRateList(fd, fpsUpperBound, &format);
8511903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        if (!format.frameRates.empty()) {
8523aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh                            outFmts.push_back(format);
8531903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                        }
8541903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                    }
8551903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh                }
8561903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh            }
8571903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        }
8581903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh        fmtdesc.index++;
8591903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh    }
8603aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    trimSupportedFormats(cropType, &outFmts);
8613aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    return outFmts;
8623aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh}
86353f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
8643aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yehvoid ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
8653aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
8663aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    std::vector<SupportedV4L2Format> horizontalFmts =
8673aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits);
8683aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    std::vector<SupportedV4L2Format> verticalFmts =
8693aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits);
8703aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
8713aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    size_t horiSize = horizontalFmts.size();
8723aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    size_t vertSize = verticalFmts.size();
8733aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
8743aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    if (horiSize == 0 && vertSize == 0) {
8753aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        ALOGE("%s: cannot find suitable cropping type!", __FUNCTION__);
8763aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        return;
8773aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    }
87853f4cb140a6254f9c41b140fd2d49eb0177ebd69Yin-Chia Yeh
8793aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    if (horiSize == 0) {
8803aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mSupportedFormats = verticalFmts;
8813aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mCroppingType = VERTICAL;
8823aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        return;
8833aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    } else if (vertSize == 0) {
8843aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mSupportedFormats = horizontalFmts;
8853aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mCroppingType = HORIZONTAL;
8863aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        return;
8873aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    }
8883aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
8893aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    const auto& maxHoriSize = horizontalFmts[horizontalFmts.size() - 1];
8903aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    const auto& maxVertSize = verticalFmts[verticalFmts.size() - 1];
8913aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh
8923aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    // Try to keep largest possible output size
8933aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    // When they are the same or ambiguous, pick the one support more sizes
8943aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    if (maxHoriSize.width == maxVertSize.width &&
8953aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            maxHoriSize.height == maxVertSize.height) {
8963aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        if (horiSize > vertSize) {
8973aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mSupportedFormats = horizontalFmts;
8983aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mCroppingType = HORIZONTAL;
8993aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        } else {
9003aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mSupportedFormats = verticalFmts;
9013aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mCroppingType = VERTICAL;
9023aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        }
9033aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    } else if (maxHoriSize.width >= maxVertSize.width &&
9043aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            maxHoriSize.height >= maxVertSize.height) {
9053aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mSupportedFormats = horizontalFmts;
9063aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mCroppingType = HORIZONTAL;
9073aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    } else if (maxHoriSize.width <= maxVertSize.width &&
9083aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            maxHoriSize.height <= maxVertSize.height) {
9093aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mSupportedFormats = verticalFmts;
9103aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        mCroppingType = VERTICAL;
9113aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    } else {
9123aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        if (horiSize > vertSize) {
9133aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mSupportedFormats = horizontalFmts;
9143aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mCroppingType = HORIZONTAL;
9153aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        } else {
9163aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mSupportedFormats = verticalFmts;
9173aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh            mCroppingType = VERTICAL;
9183aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh        }
9193aa9ae979c4250afa58572ef04671d905d9e4f74Yin-Chia Yeh    }
9201903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}
9211903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
9221903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace implementation
9231903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace V3_4
9241903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace device
9251903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace camera
9261903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace hardware
9271903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh}  // namespace android
9281903059507815cc89e9cf268f73d86b2bb3feef7Yin-Chia Yeh
929