ExternalCameraDeviceSession.cpp revision 5d901420712fca4fe97b14e8364c6d68d47b53c7
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#define LOG_TAG "ExtCamDevSsn@3.4"
17//#define LOG_NDEBUG 0
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19#include <log/log.h>
20
21#include <inttypes.h>
22#include "ExternalCameraDeviceSession.h"
23
24#include "android-base/macros.h"
25#include <utils/Timers.h>
26#include <utils/Trace.h>
27#include <linux/videodev2.h>
28#include <sync/sync.h>
29
30#define HAVE_JPEG // required for libyuv.h to export MJPEG decode APIs
31#include <libyuv.h>
32
33#include <jpeglib.h>
34
35
36namespace android {
37namespace hardware {
38namespace camera {
39namespace device {
40namespace V3_4 {
41namespace implementation {
42
43namespace {
44// Size of request/result metadata fast message queue. Change to 0 to always use hwbinder buffer.
45static constexpr size_t kMetadataMsgQueueSize = 1 << 18 /* 256kB */;
46
47const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get rid of some initial
48                                       // bad frames. TODO: develop a better bad frame detection
49                                       // method
50constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some
51                             // webcam showing temporarily ioctl failures.
52constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 0.5 seconds
53
54// Constants for tryLock during dumpstate
55static constexpr int kDumpLockRetries = 50;
56static constexpr int kDumpLockSleep = 60000;
57
58bool tryLock(Mutex& mutex)
59{
60    bool locked = false;
61    for (int i = 0; i < kDumpLockRetries; ++i) {
62        if (mutex.tryLock() == NO_ERROR) {
63            locked = true;
64            break;
65        }
66        usleep(kDumpLockSleep);
67    }
68    return locked;
69}
70
71bool tryLock(std::mutex& mutex)
72{
73    bool locked = false;
74    for (int i = 0; i < kDumpLockRetries; ++i) {
75        if (mutex.try_lock()) {
76            locked = true;
77            break;
78        }
79        usleep(kDumpLockSleep);
80    }
81    return locked;
82}
83
84} // Anonymous namespace
85
86// Static instances
87const int ExternalCameraDeviceSession::kMaxProcessedStream;
88const int ExternalCameraDeviceSession::kMaxStallStream;
89HandleImporter ExternalCameraDeviceSession::sHandleImporter;
90
91ExternalCameraDeviceSession::ExternalCameraDeviceSession(
92        const sp<ICameraDeviceCallback>& callback,
93        const ExternalCameraConfig& cfg,
94        const std::vector<SupportedV4L2Format>& sortedFormats,
95        const CroppingType& croppingType,
96        const common::V1_0::helper::CameraMetadata& chars,
97        const std::string& cameraId,
98        unique_fd v4l2Fd) :
99        mCallback(callback),
100        mCfg(cfg),
101        mCameraCharacteristics(chars),
102        mSupportedFormats(sortedFormats),
103        mCroppingType(croppingType),
104        mCameraId(cameraId),
105        mV4l2Fd(std::move(v4l2Fd)),
106        mOutputThread(new OutputThread(this, mCroppingType)),
107        mMaxThumbResolution(getMaxThumbResolution()),
108        mMaxJpegResolution(getMaxJpegResolution()) {
109    mInitFail = initialize();
110}
111
112bool ExternalCameraDeviceSession::initialize() {
113    if (mV4l2Fd.get() < 0) {
114        ALOGE("%s: invalid v4l2 device fd %d!", __FUNCTION__, mV4l2Fd.get());
115        return true;
116    }
117
118    struct v4l2_capability capability;
119    int ret = ioctl(mV4l2Fd.get(), VIDIOC_QUERYCAP, &capability);
120    std::string make, model;
121    if (ret < 0) {
122        ALOGW("%s v4l2 QUERYCAP failed", __FUNCTION__);
123        make = "Generic UVC webcam";
124        model = "Generic UVC webcam";
125    } else {
126        // capability.card is UTF-8 encoded
127        char card[32];
128        int j = 0;
129        for (int i = 0; i < 32; i++) {
130            if (capability.card[i] < 128) {
131                card[j++] = capability.card[i];
132            }
133            if (capability.card[i] == '\0') {
134                break;
135            }
136        }
137        if (j == 0 || card[j - 1] != '\0') {
138            make = "Generic UVC webcam";
139            model = "Generic UVC webcam";
140        } else {
141            make = card;
142            model = card;
143        }
144    }
145    mOutputThread->setExifMakeModel(make, model);
146
147    status_t status = initDefaultRequests();
148    if (status != OK) {
149        ALOGE("%s: init default requests failed!", __FUNCTION__);
150        return true;
151    }
152
153    mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
154            kMetadataMsgQueueSize, false /* non blocking */);
155    if (!mRequestMetadataQueue->isValid()) {
156        ALOGE("%s: invalid request fmq", __FUNCTION__);
157        return true;
158    }
159    mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
160            kMetadataMsgQueueSize, false /* non blocking */);
161    if (!mResultMetadataQueue->isValid()) {
162        ALOGE("%s: invalid result fmq", __FUNCTION__);
163        return true;
164    }
165
166    // TODO: check is PRIORITY_DISPLAY enough?
167    mOutputThread->run("ExtCamOut", PRIORITY_DISPLAY);
168    return false;
169}
170
171Status ExternalCameraDeviceSession::initStatus() const {
172    Mutex::Autolock _l(mLock);
173    Status status = Status::OK;
174    if (mInitFail || mClosed) {
175        ALOGI("%s: sesssion initFailed %d closed %d", __FUNCTION__, mInitFail, mClosed);
176        status = Status::INTERNAL_ERROR;
177    }
178    return status;
179}
180
181ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
182    if (!isClosed()) {
183        ALOGE("ExternalCameraDeviceSession deleted before close!");
184        close();
185    }
186}
187
188
189void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) {
190    if (handle->numFds != 1 || handle->numInts != 0) {
191        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
192                __FUNCTION__, handle->numFds, handle->numInts);
193        return;
194    }
195    int fd = handle->data[0];
196
197    bool intfLocked = tryLock(mInterfaceLock);
198    if (!intfLocked) {
199        dprintf(fd, "!! ExternalCameraDeviceSession interface may be deadlocked !!\n");
200    }
201
202    if (isClosed()) {
203        dprintf(fd, "External camera %s is closed\n", mCameraId.c_str());
204        return;
205    }
206
207    bool streaming = false;
208    size_t v4L2BufferCount = 0;
209    SupportedV4L2Format streamingFmt;
210    {
211        bool sessionLocked = tryLock(mLock);
212        if (!sessionLocked) {
213            dprintf(fd, "!! ExternalCameraDeviceSession mLock may be deadlocked !!\n");
214        }
215        streaming = mV4l2Streaming;
216        streamingFmt = mV4l2StreamingFmt;
217        v4L2BufferCount = mV4L2BufferCount;
218
219        if (sessionLocked) {
220            mLock.unlock();
221        }
222    }
223
224    std::unordered_set<uint32_t>  inflightFrames;
225    {
226        bool iffLocked = tryLock(mInflightFramesLock);
227        if (!iffLocked) {
228            dprintf(fd,
229                    "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n");
230        }
231        inflightFrames = mInflightFrames;
232        if (iffLocked) {
233            mInflightFramesLock.unlock();
234        }
235    }
236
237    dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n",
238            mCameraId.c_str(), mV4l2Fd.get(),
239            (mCroppingType == VERTICAL) ? "vertical" : "horizontal",
240            streaming ? "streaming" : "not streaming");
241    if (streaming) {
242        // TODO: dump fps later
243        dprintf(fd, "Current V4L2 format %c%c%c%c %dx%d @ %ffps\n",
244                streamingFmt.fourcc & 0xFF,
245                (streamingFmt.fourcc >> 8) & 0xFF,
246                (streamingFmt.fourcc >> 16) & 0xFF,
247                (streamingFmt.fourcc >> 24) & 0xFF,
248                streamingFmt.width, streamingFmt.height,
249                mV4l2StreamingFps);
250
251        size_t numDequeuedV4l2Buffers = 0;
252        {
253            std::lock_guard<std::mutex> lk(mV4l2BufferLock);
254            numDequeuedV4l2Buffers = mNumDequeuedV4l2Buffers;
255        }
256        dprintf(fd, "V4L2 buffer queue size %zu, dequeued %zu\n",
257                v4L2BufferCount, numDequeuedV4l2Buffers);
258    }
259
260    dprintf(fd, "In-flight frames (not sorted):");
261    for (const auto& frameNumber : inflightFrames) {
262        dprintf(fd, "%d, ", frameNumber);
263    }
264    dprintf(fd, "\n");
265    mOutputThread->dump(fd);
266    dprintf(fd, "\n");
267
268    if (intfLocked) {
269        mInterfaceLock.unlock();
270    }
271
272    return;
273}
274
275Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings(
276        V3_2::RequestTemplate type,
277        V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
278    V3_2::CameraMetadata outMetadata;
279    Status status = constructDefaultRequestSettingsRaw(
280            static_cast<RequestTemplate>(type), &outMetadata);
281    _hidl_cb(status, outMetadata);
282    return Void();
283}
284
285Status ExternalCameraDeviceSession::constructDefaultRequestSettingsRaw(RequestTemplate type,
286        V3_2::CameraMetadata *outMetadata) {
287    CameraMetadata emptyMd;
288    Status status = initStatus();
289    if (status != Status::OK) {
290        return status;
291    }
292
293    switch (type) {
294        case RequestTemplate::PREVIEW:
295        case RequestTemplate::STILL_CAPTURE:
296        case RequestTemplate::VIDEO_RECORD:
297        case RequestTemplate::VIDEO_SNAPSHOT: {
298            *outMetadata = mDefaultRequests[type];
299            break;
300        }
301        case RequestTemplate::MANUAL:
302        case RequestTemplate::ZERO_SHUTTER_LAG:
303            // Don't support MANUAL, ZSL templates
304            status = Status::ILLEGAL_ARGUMENT;
305            break;
306        default:
307            ALOGE("%s: unknown request template type %d", __FUNCTION__, static_cast<int>(type));
308            status = Status::ILLEGAL_ARGUMENT;
309            break;
310    }
311    return status;
312}
313
314Return<void> ExternalCameraDeviceSession::configureStreams(
315        const V3_2::StreamConfiguration& streams,
316        ICameraDeviceSession::configureStreams_cb _hidl_cb) {
317    V3_2::HalStreamConfiguration outStreams;
318    V3_3::HalStreamConfiguration outStreams_v33;
319    Mutex::Autolock _il(mInterfaceLock);
320
321    Status status = configureStreams(streams, &outStreams_v33);
322    size_t size = outStreams_v33.streams.size();
323    outStreams.streams.resize(size);
324    for (size_t i = 0; i < size; i++) {
325        outStreams.streams[i] = outStreams_v33.streams[i].v3_2;
326    }
327    _hidl_cb(status, outStreams);
328    return Void();
329}
330
331Return<void> ExternalCameraDeviceSession::configureStreams_3_3(
332        const V3_2::StreamConfiguration& streams,
333        ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb) {
334    V3_3::HalStreamConfiguration outStreams;
335    Mutex::Autolock _il(mInterfaceLock);
336
337    Status status = configureStreams(streams, &outStreams);
338    _hidl_cb(status, outStreams);
339    return Void();
340}
341
342Return<void> ExternalCameraDeviceSession::configureStreams_3_4(
343        const V3_4::StreamConfiguration& requestedConfiguration,
344        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
345    V3_2::StreamConfiguration config_v32;
346    V3_3::HalStreamConfiguration outStreams_v33;
347    Mutex::Autolock _il(mInterfaceLock);
348
349    config_v32.operationMode = requestedConfiguration.operationMode;
350    config_v32.streams.resize(requestedConfiguration.streams.size());
351    for (size_t i = 0; i < config_v32.streams.size(); i++) {
352        config_v32.streams[i] = requestedConfiguration.streams[i].v3_2;
353    }
354
355    Status status = configureStreams(config_v32, &outStreams_v33);
356
357    V3_4::HalStreamConfiguration outStreams;
358    outStreams.streams.resize(outStreams_v33.streams.size());
359    for (size_t i = 0; i < outStreams.streams.size(); i++) {
360        outStreams.streams[i].v3_3 = outStreams_v33.streams[i];
361    }
362    _hidl_cb(status, outStreams);
363    return Void();
364}
365
366Return<void> ExternalCameraDeviceSession::getCaptureRequestMetadataQueue(
367    ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
368    Mutex::Autolock _il(mInterfaceLock);
369    _hidl_cb(*mRequestMetadataQueue->getDesc());
370    return Void();
371}
372
373Return<void> ExternalCameraDeviceSession::getCaptureResultMetadataQueue(
374    ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
375    Mutex::Autolock _il(mInterfaceLock);
376    _hidl_cb(*mResultMetadataQueue->getDesc());
377    return Void();
378}
379
380Return<void> ExternalCameraDeviceSession::processCaptureRequest(
381        const hidl_vec<CaptureRequest>& requests,
382        const hidl_vec<BufferCache>& cachesToRemove,
383        ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
384    Mutex::Autolock _il(mInterfaceLock);
385    updateBufferCaches(cachesToRemove);
386
387    uint32_t numRequestProcessed = 0;
388    Status s = Status::OK;
389    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
390        s = processOneCaptureRequest(requests[i]);
391        if (s != Status::OK) {
392            break;
393        }
394    }
395
396    _hidl_cb(s, numRequestProcessed);
397    return Void();
398}
399
400Return<void> ExternalCameraDeviceSession::processCaptureRequest_3_4(
401        const hidl_vec<V3_4::CaptureRequest>& requests,
402        const hidl_vec<V3_2::BufferCache>& cachesToRemove,
403        ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
404    Mutex::Autolock _il(mInterfaceLock);
405    updateBufferCaches(cachesToRemove);
406
407    uint32_t numRequestProcessed = 0;
408    Status s = Status::OK;
409    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
410        s = processOneCaptureRequest(requests[i].v3_2);
411        if (s != Status::OK) {
412            break;
413        }
414    }
415
416    _hidl_cb(s, numRequestProcessed);
417    return Void();
418}
419
420Return<Status> ExternalCameraDeviceSession::flush() {
421    ATRACE_CALL();
422    Mutex::Autolock _il(mInterfaceLock);
423    Status status = initStatus();
424    if (status != Status::OK) {
425        return status;
426    }
427    mOutputThread->flush();
428    return Status::OK;
429}
430
431Return<void> ExternalCameraDeviceSession::close() {
432    Mutex::Autolock _il(mInterfaceLock);
433    bool closed = isClosed();
434    if (!closed) {
435        mOutputThread->flush();
436        mOutputThread->requestExit();
437        mOutputThread->join();
438
439        Mutex::Autolock _l(mLock);
440        // free all buffers
441        for(auto pair : mStreamMap) {
442            cleanupBuffersLocked(/*Stream ID*/pair.first);
443        }
444        v4l2StreamOffLocked();
445        ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get());
446        mV4l2Fd.reset();
447        mClosed = true;
448    }
449    return Void();
450}
451
452Status ExternalCameraDeviceSession::importRequest(
453        const CaptureRequest& request,
454        hidl_vec<buffer_handle_t*>& allBufPtrs,
455        hidl_vec<int>& allFences) {
456    size_t numOutputBufs = request.outputBuffers.size();
457    size_t numBufs = numOutputBufs;
458    // Validate all I/O buffers
459    hidl_vec<buffer_handle_t> allBufs;
460    hidl_vec<uint64_t> allBufIds;
461    allBufs.resize(numBufs);
462    allBufIds.resize(numBufs);
463    allBufPtrs.resize(numBufs);
464    allFences.resize(numBufs);
465    std::vector<int32_t> streamIds(numBufs);
466
467    for (size_t i = 0; i < numOutputBufs; i++) {
468        allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
469        allBufIds[i] = request.outputBuffers[i].bufferId;
470        allBufPtrs[i] = &allBufs[i];
471        streamIds[i] = request.outputBuffers[i].streamId;
472    }
473
474    for (size_t i = 0; i < numBufs; i++) {
475        buffer_handle_t buf = allBufs[i];
476        uint64_t bufId = allBufIds[i];
477        CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
478        if (cbs.count(bufId) == 0) {
479            if (buf == nullptr) {
480                ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
481                return Status::ILLEGAL_ARGUMENT;
482            }
483            // Register a newly seen buffer
484            buffer_handle_t importedBuf = buf;
485            sHandleImporter.importBuffer(importedBuf);
486            if (importedBuf == nullptr) {
487                ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
488                return Status::INTERNAL_ERROR;
489            } else {
490                cbs[bufId] = importedBuf;
491            }
492        }
493        allBufPtrs[i] = &cbs[bufId];
494    }
495
496    // All buffers are imported. Now validate output buffer acquire fences
497    for (size_t i = 0; i < numOutputBufs; i++) {
498        if (!sHandleImporter.importFence(
499                request.outputBuffers[i].acquireFence, allFences[i])) {
500            ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
501            cleanupInflightFences(allFences, i);
502            return Status::INTERNAL_ERROR;
503        }
504    }
505    return Status::OK;
506}
507
508void ExternalCameraDeviceSession::cleanupInflightFences(
509        hidl_vec<int>& allFences, size_t numFences) {
510    for (size_t j = 0; j < numFences; j++) {
511        sHandleImporter.closeFence(allFences[j]);
512    }
513}
514
515int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) {
516    ATRACE_CALL();
517    std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
518    mLock.unlock();
519    auto st = mV4L2BufferReturned.wait_for(lk, timeout);
520    // Here we introduce a order where mV4l2BufferLock is acquired before mLock, while
521    // the normal lock acquisition order is reversed. This is fine because in most of
522    // cases we are protected by mInterfaceLock. The only thread that can cause deadlock
523    // is the OutputThread, where we do need to make sure we don't acquire mLock then
524    // mV4l2BufferLock
525    mLock.lock();
526    if (st == std::cv_status::timeout) {
527        ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__);
528        return -1;
529    }
530    return 0;
531}
532
533Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request)  {
534    ATRACE_CALL();
535    Status status = initStatus();
536    if (status != Status::OK) {
537        return status;
538    }
539
540    if (request.inputBuffer.streamId != -1) {
541        ALOGE("%s: external camera does not support reprocessing!", __FUNCTION__);
542        return Status::ILLEGAL_ARGUMENT;
543    }
544
545    Mutex::Autolock _l(mLock);
546    if (!mV4l2Streaming) {
547        ALOGE("%s: cannot process request in streamOff state!", __FUNCTION__);
548        return Status::INTERNAL_ERROR;
549    }
550
551    const camera_metadata_t *rawSettings = nullptr;
552    bool converted = true;
553    CameraMetadata settingsFmq;  // settings from FMQ
554    if (request.fmqSettingsSize > 0) {
555        // non-blocking read; client must write metadata before calling
556        // processOneCaptureRequest
557        settingsFmq.resize(request.fmqSettingsSize);
558        bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
559        if (read) {
560            converted = V3_2::implementation::convertFromHidl(settingsFmq, &rawSettings);
561        } else {
562            ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
563            converted = false;
564        }
565    } else {
566        converted = V3_2::implementation::convertFromHidl(request.settings, &rawSettings);
567    }
568
569    if (converted && rawSettings != nullptr) {
570        mLatestReqSetting = rawSettings;
571    }
572
573    if (!converted) {
574        ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
575        return Status::ILLEGAL_ARGUMENT;
576    }
577
578    if (mFirstRequest && rawSettings == nullptr) {
579        ALOGE("%s: capture request settings must not be null for first request!",
580                __FUNCTION__);
581        return Status::ILLEGAL_ARGUMENT;
582    }
583
584    hidl_vec<buffer_handle_t*> allBufPtrs;
585    hidl_vec<int> allFences;
586    size_t numOutputBufs = request.outputBuffers.size();
587
588    if (numOutputBufs == 0) {
589        ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
590        return Status::ILLEGAL_ARGUMENT;
591    }
592
593    camera_metadata_entry fpsRange = mLatestReqSetting.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
594    if (fpsRange.count == 2) {
595        double requestFpsMax = fpsRange.data.i32[1];
596        double closestFps = 0.0;
597        double fpsError = 1000.0;
598        bool fpsSupported = false;
599        for (const auto& fr : mV4l2StreamingFmt.frameRates) {
600            double f = fr.getDouble();
601            if (std::fabs(requestFpsMax - f) < 1.0) {
602                fpsSupported = true;
603                break;
604            }
605            if (std::fabs(requestFpsMax - f) < fpsError) {
606                fpsError = std::fabs(requestFpsMax - f);
607                closestFps = f;
608            }
609        }
610        if (!fpsSupported) {
611            /* This can happen in a few scenarios:
612             * 1. The application is sending a FPS range not supported by the configured outputs.
613             * 2. The application is sending a valid FPS range for all cofigured outputs, but
614             *    the selected V4L2 size can only run at slower speed. This should be very rare
615             *    though: for this to happen a sensor needs to support at least 3 different aspect
616             *    ratio outputs, and when (at least) two outputs are both not the main aspect ratio
617             *    of the webcam, a third size that's larger might be picked and runs into this
618             *    issue.
619             */
620            ALOGW("%s: cannot reach fps %d! Will do %f instead",
621                    __FUNCTION__, fpsRange.data.i32[1], closestFps);
622            requestFpsMax = closestFps;
623        }
624
625        if (requestFpsMax != mV4l2StreamingFps) {
626            {
627                std::unique_lock<std::mutex> lk(mV4l2BufferLock);
628                while (mNumDequeuedV4l2Buffers != 0) {
629                    // Wait until pipeline is idle before reconfigure stream
630                    int waitRet = waitForV4L2BufferReturnLocked(lk);
631                    if (waitRet != 0) {
632                        ALOGE("%s: wait for pipeline idle failed!", __FUNCTION__);
633                        return Status::INTERNAL_ERROR;
634                    }
635                }
636            }
637            configureV4l2StreamLocked(mV4l2StreamingFmt, requestFpsMax);
638        }
639    }
640
641    status = importRequest(request, allBufPtrs, allFences);
642    if (status != Status::OK) {
643        return status;
644    }
645
646    nsecs_t shutterTs = 0;
647    sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked(&shutterTs);
648    if ( frameIn == nullptr) {
649        ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__);
650        return Status::INTERNAL_ERROR;
651    }
652
653    std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>();
654    halReq->frameNumber = request.frameNumber;
655    halReq->setting = mLatestReqSetting;
656    halReq->frameIn = frameIn;
657    halReq->shutterTs = shutterTs;
658    halReq->buffers.resize(numOutputBufs);
659    for (size_t i = 0; i < numOutputBufs; i++) {
660        HalStreamBuffer& halBuf = halReq->buffers[i];
661        int streamId = halBuf.streamId = request.outputBuffers[i].streamId;
662        halBuf.bufferId = request.outputBuffers[i].bufferId;
663        const Stream& stream = mStreamMap[streamId];
664        halBuf.width = stream.width;
665        halBuf.height = stream.height;
666        halBuf.format = stream.format;
667        halBuf.usage = stream.usage;
668        halBuf.bufPtr = allBufPtrs[i];
669        halBuf.acquireFence = allFences[i];
670        halBuf.fenceTimeout = false;
671    }
672    {
673        std::lock_guard<std::mutex> lk(mInflightFramesLock);
674        mInflightFrames.insert(halReq->frameNumber);
675    }
676    // Send request to OutputThread for the rest of processing
677    mOutputThread->submitRequest(halReq);
678    mFirstRequest = false;
679    return Status::OK;
680}
681
682void ExternalCameraDeviceSession::notifyShutter(uint32_t frameNumber, nsecs_t shutterTs) {
683    NotifyMsg msg;
684    msg.type = MsgType::SHUTTER;
685    msg.msg.shutter.frameNumber = frameNumber;
686    msg.msg.shutter.timestamp = shutterTs;
687    mCallback->notify({msg});
688}
689
690void ExternalCameraDeviceSession::notifyError(
691        uint32_t frameNumber, int32_t streamId, ErrorCode ec) {
692    NotifyMsg msg;
693    msg.type = MsgType::ERROR;
694    msg.msg.error.frameNumber = frameNumber;
695    msg.msg.error.errorStreamId = streamId;
696    msg.msg.error.errorCode = ec;
697    mCallback->notify({msg});
698}
699
700//TODO: refactor with processCaptureResult
701Status ExternalCameraDeviceSession::processCaptureRequestError(
702        const std::shared_ptr<HalRequest>& req) {
703    ATRACE_CALL();
704    // Return V4L2 buffer to V4L2 buffer queue
705    enqueueV4l2Frame(req->frameIn);
706
707    // NotifyShutter
708    notifyShutter(req->frameNumber, req->shutterTs);
709
710    notifyError(/*frameNum*/req->frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST);
711
712    // Fill output buffers
713    hidl_vec<CaptureResult> results;
714    results.resize(1);
715    CaptureResult& result = results[0];
716    result.frameNumber = req->frameNumber;
717    result.partialResult = 1;
718    result.inputBuffer.streamId = -1;
719    result.outputBuffers.resize(req->buffers.size());
720    for (size_t i = 0; i < req->buffers.size(); i++) {
721        result.outputBuffers[i].streamId = req->buffers[i].streamId;
722        result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
723        result.outputBuffers[i].status = BufferStatus::ERROR;
724        if (req->buffers[i].acquireFence >= 0) {
725            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
726            handle->data[0] = req->buffers[i].acquireFence;
727            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
728        }
729    }
730
731    // update inflight records
732    {
733        std::lock_guard<std::mutex> lk(mInflightFramesLock);
734        mInflightFrames.erase(req->frameNumber);
735    }
736
737    // Callback into framework
738    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
739    freeReleaseFences(results);
740    return Status::OK;
741}
742
743Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequest>& req) {
744    ATRACE_CALL();
745    // Return V4L2 buffer to V4L2 buffer queue
746    enqueueV4l2Frame(req->frameIn);
747
748    // NotifyShutter
749    notifyShutter(req->frameNumber, req->shutterTs);
750
751    // Fill output buffers
752    hidl_vec<CaptureResult> results;
753    results.resize(1);
754    CaptureResult& result = results[0];
755    result.frameNumber = req->frameNumber;
756    result.partialResult = 1;
757    result.inputBuffer.streamId = -1;
758    result.outputBuffers.resize(req->buffers.size());
759    for (size_t i = 0; i < req->buffers.size(); i++) {
760        result.outputBuffers[i].streamId = req->buffers[i].streamId;
761        result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
762        if (req->buffers[i].fenceTimeout) {
763            result.outputBuffers[i].status = BufferStatus::ERROR;
764            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
765            handle->data[0] = req->buffers[i].acquireFence;
766            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
767            notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER);
768        } else {
769            result.outputBuffers[i].status = BufferStatus::OK;
770            // TODO: refactor
771            if (req->buffers[i].acquireFence > 0) {
772                native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
773                handle->data[0] = req->buffers[i].acquireFence;
774                result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
775            }
776        }
777    }
778
779    // Fill capture result metadata
780    fillCaptureResult(req->setting, req->shutterTs);
781    const camera_metadata_t *rawResult = req->setting.getAndLock();
782    V3_2::implementation::convertToHidl(rawResult, &result.result);
783    req->setting.unlock(rawResult);
784
785    // update inflight records
786    {
787        std::lock_guard<std::mutex> lk(mInflightFramesLock);
788        mInflightFrames.erase(req->frameNumber);
789    }
790
791    // Callback into framework
792    invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
793    freeReleaseFences(results);
794    return Status::OK;
795}
796
797void ExternalCameraDeviceSession::invokeProcessCaptureResultCallback(
798        hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
799    if (mProcessCaptureResultLock.tryLock() != OK) {
800        const nsecs_t NS_TO_SECOND = 1000000000;
801        ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
802        if (mProcessCaptureResultLock.timedLock(/* 1s */NS_TO_SECOND) != OK) {
803            ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
804                    __FUNCTION__);
805            return;
806        }
807    }
808    if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
809        for (CaptureResult &result : results) {
810            if (result.result.size() > 0) {
811                if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
812                    result.fmqResultSize = result.result.size();
813                    result.result.resize(0);
814                } else {
815                    ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
816                    result.fmqResultSize = 0;
817                }
818            } else {
819                result.fmqResultSize = 0;
820            }
821        }
822    }
823    auto status = mCallback->processCaptureResult(results);
824    if (!status.isOk()) {
825        ALOGE("%s: processCaptureResult ERROR : %s", __FUNCTION__,
826              status.description().c_str());
827    }
828
829    mProcessCaptureResultLock.unlock();
830}
831
832void ExternalCameraDeviceSession::freeReleaseFences(hidl_vec<CaptureResult>& results) {
833    for (auto& result : results) {
834        if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
835            native_handle_t* handle = const_cast<native_handle_t*>(
836                    result.inputBuffer.releaseFence.getNativeHandle());
837            native_handle_close(handle);
838            native_handle_delete(handle);
839        }
840        for (auto& buf : result.outputBuffers) {
841            if (buf.releaseFence.getNativeHandle() != nullptr) {
842                native_handle_t* handle = const_cast<native_handle_t*>(
843                        buf.releaseFence.getNativeHandle());
844                native_handle_close(handle);
845                native_handle_delete(handle);
846            }
847        }
848    }
849    return;
850}
851
852ExternalCameraDeviceSession::OutputThread::OutputThread(
853        wp<ExternalCameraDeviceSession> parent,
854        CroppingType ct) : mParent(parent), mCroppingType(ct) {}
855
856ExternalCameraDeviceSession::OutputThread::~OutputThread() {}
857
858void ExternalCameraDeviceSession::OutputThread::setExifMakeModel(
859        const std::string& make, const std::string& model) {
860    mExifMake = make;
861    mExifModel = model;
862}
863
864uint32_t ExternalCameraDeviceSession::OutputThread::getFourCcFromLayout(
865        const YCbCrLayout& layout) {
866    intptr_t cb = reinterpret_cast<intptr_t>(layout.cb);
867    intptr_t cr = reinterpret_cast<intptr_t>(layout.cr);
868    if (std::abs(cb - cr) == 1 && layout.chromaStep == 2) {
869        // Interleaved format
870        if (layout.cb > layout.cr) {
871            return V4L2_PIX_FMT_NV21;
872        } else {
873            return V4L2_PIX_FMT_NV12;
874        }
875    } else if (layout.chromaStep == 1) {
876        // Planar format
877        if (layout.cb > layout.cr) {
878            return V4L2_PIX_FMT_YVU420; // YV12
879        } else {
880            return V4L2_PIX_FMT_YUV420; // YU12
881        }
882    } else {
883        return FLEX_YUV_GENERIC;
884    }
885}
886
887int ExternalCameraDeviceSession::OutputThread::getCropRect(
888        CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out) {
889    if (out == nullptr) {
890        ALOGE("%s: out is null", __FUNCTION__);
891        return -1;
892    }
893
894    uint32_t inW = inSize.width;
895    uint32_t inH = inSize.height;
896    uint32_t outW = outSize.width;
897    uint32_t outH = outSize.height;
898
899    // Handle special case where aspect ratio is close to input but scaled
900    // dimension is slightly larger than input
901    float arIn = ASPECT_RATIO(inSize);
902    float arOut = ASPECT_RATIO(outSize);
903    if (isAspectRatioClose(arIn, arOut)) {
904        out->left = 0;
905        out->top = 0;
906        out->width = inW;
907        out->height = inH;
908        return 0;
909    }
910
911    if (ct == VERTICAL) {
912        uint64_t scaledOutH = static_cast<uint64_t>(outH) * inW / outW;
913        if (scaledOutH > inH) {
914            ALOGE("%s: Output size %dx%d cannot be vertically cropped from input size %dx%d",
915                    __FUNCTION__, outW, outH, inW, inH);
916            return -1;
917        }
918        scaledOutH = scaledOutH & ~0x1; // make it multiple of 2
919
920        out->left = 0;
921        out->top = ((inH - scaledOutH) / 2) & ~0x1;
922        out->width = inW;
923        out->height = static_cast<int32_t>(scaledOutH);
924        ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledH %d",
925                __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutH));
926    } else {
927        uint64_t scaledOutW = static_cast<uint64_t>(outW) * inH / outH;
928        if (scaledOutW > inW) {
929            ALOGE("%s: Output size %dx%d cannot be horizontally cropped from input size %dx%d",
930                    __FUNCTION__, outW, outH, inW, inH);
931            return -1;
932        }
933        scaledOutW = scaledOutW & ~0x1; // make it multiple of 2
934
935        out->left = ((inW - scaledOutW) / 2) & ~0x1;
936        out->top = 0;
937        out->width = static_cast<int32_t>(scaledOutW);
938        out->height = inH;
939        ALOGV("%s: crop %dx%d to %dx%d: top %d, scaledW %d",
940                __FUNCTION__, inW, inH, outW, outH, out->top, static_cast<int32_t>(scaledOutW));
941    }
942
943    return 0;
944}
945
946int ExternalCameraDeviceSession::OutputThread::cropAndScaleLocked(
947        sp<AllocatedFrame>& in, const Size& outSz, YCbCrLayout* out) {
948    Size inSz = {in->mWidth, in->mHeight};
949
950    int ret;
951    if (inSz == outSz) {
952        ret = in->getLayout(out);
953        if (ret != 0) {
954            ALOGE("%s: failed to get input image layout", __FUNCTION__);
955            return ret;
956        }
957        return ret;
958    }
959
960    // Cropping to output aspect ratio
961    IMapper::Rect inputCrop;
962    ret = getCropRect(mCroppingType, inSz, outSz, &inputCrop);
963    if (ret != 0) {
964        ALOGE("%s: failed to compute crop rect for output size %dx%d",
965                __FUNCTION__, outSz.width, outSz.height);
966        return ret;
967    }
968
969    YCbCrLayout croppedLayout;
970    ret = in->getCroppedLayout(inputCrop, &croppedLayout);
971    if (ret != 0) {
972        ALOGE("%s: failed to crop input image %dx%d to output size %dx%d",
973                __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height);
974        return ret;
975    }
976
977    if ((mCroppingType == VERTICAL && inSz.width == outSz.width) ||
978            (mCroppingType == HORIZONTAL && inSz.height == outSz.height)) {
979        // No scale is needed
980        *out = croppedLayout;
981        return 0;
982    }
983
984    auto it = mScaledYu12Frames.find(outSz);
985    sp<AllocatedFrame> scaledYu12Buf;
986    if (it != mScaledYu12Frames.end()) {
987        scaledYu12Buf = it->second;
988    } else {
989        it = mIntermediateBuffers.find(outSz);
990        if (it == mIntermediateBuffers.end()) {
991            ALOGE("%s: failed to find intermediate buffer size %dx%d",
992                    __FUNCTION__, outSz.width, outSz.height);
993            return -1;
994        }
995        scaledYu12Buf = it->second;
996    }
997    // Scale
998    YCbCrLayout outLayout;
999    ret = scaledYu12Buf->getLayout(&outLayout);
1000    if (ret != 0) {
1001        ALOGE("%s: failed to get output buffer layout", __FUNCTION__);
1002        return ret;
1003    }
1004
1005    ret = libyuv::I420Scale(
1006            static_cast<uint8_t*>(croppedLayout.y),
1007            croppedLayout.yStride,
1008            static_cast<uint8_t*>(croppedLayout.cb),
1009            croppedLayout.cStride,
1010            static_cast<uint8_t*>(croppedLayout.cr),
1011            croppedLayout.cStride,
1012            inputCrop.width,
1013            inputCrop.height,
1014            static_cast<uint8_t*>(outLayout.y),
1015            outLayout.yStride,
1016            static_cast<uint8_t*>(outLayout.cb),
1017            outLayout.cStride,
1018            static_cast<uint8_t*>(outLayout.cr),
1019            outLayout.cStride,
1020            outSz.width,
1021            outSz.height,
1022            // TODO: b/72261744 see if we can use better filter without losing too much perf
1023            libyuv::FilterMode::kFilterNone);
1024
1025    if (ret != 0) {
1026        ALOGE("%s: failed to scale buffer from %dx%d to %dx%d. Ret %d",
1027                __FUNCTION__, inputCrop.width, inputCrop.height,
1028                outSz.width, outSz.height, ret);
1029        return ret;
1030    }
1031
1032    *out = outLayout;
1033    mScaledYu12Frames.insert({outSz, scaledYu12Buf});
1034    return 0;
1035}
1036
1037
1038int ExternalCameraDeviceSession::OutputThread::cropAndScaleThumbLocked(
1039        sp<AllocatedFrame>& in, const Size &outSz, YCbCrLayout* out) {
1040    Size inSz  {in->mWidth, in->mHeight};
1041
1042    if ((outSz.width * outSz.height) >
1043        (mYu12ThumbFrame->mWidth * mYu12ThumbFrame->mHeight)) {
1044        ALOGE("%s: Requested thumbnail size too big (%d,%d) > (%d,%d)",
1045              __FUNCTION__, outSz.width, outSz.height,
1046              mYu12ThumbFrame->mWidth, mYu12ThumbFrame->mHeight);
1047        return -1;
1048    }
1049
1050    int ret;
1051
1052    /* This will crop-and-zoom the input YUV frame to the thumbnail size
1053     * Based on the following logic:
1054     *  1) Square pixels come in, square pixels come out, therefore single
1055     *  scale factor is computed to either make input bigger or smaller
1056     *  depending on if we are upscaling or downscaling
1057     *  2) That single scale factor would either make height too tall or width
1058     *  too wide so we need to crop the input either horizontally or vertically
1059     *  but not both
1060     */
1061
1062    /* Convert the input and output dimensions into floats for ease of math */
1063    float fWin = static_cast<float>(inSz.width);
1064    float fHin = static_cast<float>(inSz.height);
1065    float fWout = static_cast<float>(outSz.width);
1066    float fHout = static_cast<float>(outSz.height);
1067
1068    /* Compute the one scale factor from (1) above, it will be the smaller of
1069     * the two possibilities. */
1070    float scaleFactor = std::min( fHin / fHout, fWin / fWout );
1071
1072    /* Since we are crop-and-zooming (as opposed to letter/pillar boxing) we can
1073     * simply multiply the output by our scaleFactor to get the cropped input
1074     * size. Note that at least one of {fWcrop, fHcrop} is going to wind up
1075     * being {fWin, fHin} respectively because fHout or fWout cancels out the
1076     * scaleFactor calculation above.
1077     *
1078     * Specifically:
1079     *  if ( fHin / fHout ) < ( fWin / fWout ) we crop the sides off
1080     * input, in which case
1081     *    scaleFactor = fHin / fHout
1082     *    fWcrop = fHin / fHout * fWout
1083     *    fHcrop = fHin
1084     *
1085     * Note that fWcrop <= fWin ( because ( fHin / fHout ) * fWout < fWin, which
1086     * is just the inequality above with both sides multiplied by fWout
1087     *
1088     * on the other hand if ( fWin / fWout ) < ( fHin / fHout) we crop the top
1089     * and the bottom off of input, and
1090     *    scaleFactor = fWin / fWout
1091     *    fWcrop = fWin
1092     *    fHCrop = fWin / fWout * fHout
1093     */
1094    float fWcrop = scaleFactor * fWout;
1095    float fHcrop = scaleFactor * fHout;
1096
1097    /* Convert to integer and truncate to an even number */
1098    Size cropSz = { 2*static_cast<uint32_t>(fWcrop/2.0f),
1099                    2*static_cast<uint32_t>(fHcrop/2.0f) };
1100
1101    /* Convert to a centered rectange with even top/left */
1102    IMapper::Rect inputCrop {
1103        2*static_cast<int32_t>((inSz.width - cropSz.width)/4),
1104        2*static_cast<int32_t>((inSz.height - cropSz.height)/4),
1105        static_cast<int32_t>(cropSz.width),
1106        static_cast<int32_t>(cropSz.height) };
1107
1108    if ((inputCrop.top < 0) ||
1109        (inputCrop.top >= static_cast<int32_t>(inSz.height)) ||
1110        (inputCrop.left < 0) ||
1111        (inputCrop.left >= static_cast<int32_t>(inSz.width)) ||
1112        (inputCrop.width <= 0) ||
1113        (inputCrop.width + inputCrop.left > static_cast<int32_t>(inSz.width)) ||
1114        (inputCrop.height <= 0) ||
1115        (inputCrop.height + inputCrop.top > static_cast<int32_t>(inSz.height)))
1116    {
1117        ALOGE("%s: came up with really wrong crop rectangle",__FUNCTION__);
1118        ALOGE("%s: input layout %dx%d to for output size %dx%d",
1119             __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height);
1120        ALOGE("%s: computed input crop +%d,+%d %dx%d",
1121             __FUNCTION__, inputCrop.left, inputCrop.top,
1122             inputCrop.width, inputCrop.height);
1123        return -1;
1124    }
1125
1126    YCbCrLayout inputLayout;
1127    ret = in->getCroppedLayout(inputCrop, &inputLayout);
1128    if (ret != 0) {
1129        ALOGE("%s: failed to crop input layout %dx%d to for output size %dx%d",
1130             __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height);
1131        ALOGE("%s: computed input crop +%d,+%d %dx%d",
1132             __FUNCTION__, inputCrop.left, inputCrop.top,
1133             inputCrop.width, inputCrop.height);
1134        return ret;
1135    }
1136    ALOGV("%s: crop input layout %dx%d to for output size %dx%d",
1137          __FUNCTION__, inSz.width, inSz.height, outSz.width, outSz.height);
1138    ALOGV("%s: computed input crop +%d,+%d %dx%d",
1139          __FUNCTION__, inputCrop.left, inputCrop.top,
1140          inputCrop.width, inputCrop.height);
1141
1142
1143    // Scale
1144    YCbCrLayout outFullLayout;
1145
1146    ret = mYu12ThumbFrame->getLayout(&outFullLayout);
1147    if (ret != 0) {
1148        ALOGE("%s: failed to get output buffer layout", __FUNCTION__);
1149        return ret;
1150    }
1151
1152
1153    ret = libyuv::I420Scale(
1154            static_cast<uint8_t*>(inputLayout.y),
1155            inputLayout.yStride,
1156            static_cast<uint8_t*>(inputLayout.cb),
1157            inputLayout.cStride,
1158            static_cast<uint8_t*>(inputLayout.cr),
1159            inputLayout.cStride,
1160            inputCrop.width,
1161            inputCrop.height,
1162            static_cast<uint8_t*>(outFullLayout.y),
1163            outFullLayout.yStride,
1164            static_cast<uint8_t*>(outFullLayout.cb),
1165            outFullLayout.cStride,
1166            static_cast<uint8_t*>(outFullLayout.cr),
1167            outFullLayout.cStride,
1168            outSz.width,
1169            outSz.height,
1170            libyuv::FilterMode::kFilterNone);
1171
1172    if (ret != 0) {
1173        ALOGE("%s: failed to scale buffer from %dx%d to %dx%d. Ret %d",
1174                __FUNCTION__, inputCrop.width, inputCrop.height,
1175                outSz.width, outSz.height, ret);
1176        return ret;
1177    }
1178
1179    *out = outFullLayout;
1180    return 0;
1181}
1182
1183int ExternalCameraDeviceSession::OutputThread::formatConvertLocked(
1184        const YCbCrLayout& in, const YCbCrLayout& out, Size sz, uint32_t format) {
1185    int ret = 0;
1186    switch (format) {
1187        case V4L2_PIX_FMT_NV21:
1188            ret = libyuv::I420ToNV21(
1189                    static_cast<uint8_t*>(in.y),
1190                    in.yStride,
1191                    static_cast<uint8_t*>(in.cb),
1192                    in.cStride,
1193                    static_cast<uint8_t*>(in.cr),
1194                    in.cStride,
1195                    static_cast<uint8_t*>(out.y),
1196                    out.yStride,
1197                    static_cast<uint8_t*>(out.cr),
1198                    out.cStride,
1199                    sz.width,
1200                    sz.height);
1201            if (ret != 0) {
1202                ALOGE("%s: convert to NV21 buffer failed! ret %d",
1203                            __FUNCTION__, ret);
1204                return ret;
1205            }
1206            break;
1207        case V4L2_PIX_FMT_NV12:
1208            ret = libyuv::I420ToNV12(
1209                    static_cast<uint8_t*>(in.y),
1210                    in.yStride,
1211                    static_cast<uint8_t*>(in.cb),
1212                    in.cStride,
1213                    static_cast<uint8_t*>(in.cr),
1214                    in.cStride,
1215                    static_cast<uint8_t*>(out.y),
1216                    out.yStride,
1217                    static_cast<uint8_t*>(out.cb),
1218                    out.cStride,
1219                    sz.width,
1220                    sz.height);
1221            if (ret != 0) {
1222                ALOGE("%s: convert to NV12 buffer failed! ret %d",
1223                            __FUNCTION__, ret);
1224                return ret;
1225            }
1226            break;
1227        case V4L2_PIX_FMT_YVU420: // YV12
1228        case V4L2_PIX_FMT_YUV420: // YU12
1229            // TODO: maybe we can speed up here by somehow save this copy?
1230            ret = libyuv::I420Copy(
1231                    static_cast<uint8_t*>(in.y),
1232                    in.yStride,
1233                    static_cast<uint8_t*>(in.cb),
1234                    in.cStride,
1235                    static_cast<uint8_t*>(in.cr),
1236                    in.cStride,
1237                    static_cast<uint8_t*>(out.y),
1238                    out.yStride,
1239                    static_cast<uint8_t*>(out.cb),
1240                    out.cStride,
1241                    static_cast<uint8_t*>(out.cr),
1242                    out.cStride,
1243                    sz.width,
1244                    sz.height);
1245            if (ret != 0) {
1246                ALOGE("%s: copy to YV12 or YU12 buffer failed! ret %d",
1247                            __FUNCTION__, ret);
1248                return ret;
1249            }
1250            break;
1251        case FLEX_YUV_GENERIC:
1252            // TODO: b/72261744 write to arbitrary flexible YUV layout. Slow.
1253            ALOGE("%s: unsupported flexible yuv layout"
1254                    " y %p cb %p cr %p y_str %d c_str %d c_step %d",
1255                    __FUNCTION__, out.y, out.cb, out.cr,
1256                    out.yStride, out.cStride, out.chromaStep);
1257            return -1;
1258        default:
1259            ALOGE("%s: unknown YUV format 0x%x!", __FUNCTION__, format);
1260            return -1;
1261    }
1262    return 0;
1263}
1264
1265int ExternalCameraDeviceSession::OutputThread::encodeJpegYU12(
1266        const Size & inSz, const YCbCrLayout& inLayout,
1267        int jpegQuality, const void *app1Buffer, size_t app1Size,
1268        void *out, const size_t maxOutSize, size_t &actualCodeSize)
1269{
1270    /* libjpeg is a C library so we use C-style "inheritance" by
1271     * putting libjpeg's jpeg_destination_mgr first in our custom
1272     * struct. This allows us to cast jpeg_destination_mgr* to
1273     * CustomJpegDestMgr* when we get it passed to us in a callback */
1274    struct CustomJpegDestMgr {
1275        struct jpeg_destination_mgr mgr;
1276        JOCTET *mBuffer;
1277        size_t mBufferSize;
1278        size_t mEncodedSize;
1279        bool mSuccess;
1280    } dmgr;
1281
1282    jpeg_compress_struct cinfo = {};
1283    jpeg_error_mgr jerr;
1284
1285    /* Initialize error handling with standard callbacks, but
1286     * then override output_message (to print to ALOG) and
1287     * error_exit to set a flag and print a message instead
1288     * of killing the whole process */
1289    cinfo.err = jpeg_std_error(&jerr);
1290
1291    cinfo.err->output_message = [](j_common_ptr cinfo) {
1292        char buffer[JMSG_LENGTH_MAX];
1293
1294        /* Create the message */
1295        (*cinfo->err->format_message)(cinfo, buffer);
1296        ALOGE("libjpeg error: %s", buffer);
1297    };
1298    cinfo.err->error_exit = [](j_common_ptr cinfo) {
1299        (*cinfo->err->output_message)(cinfo);
1300        if(cinfo->client_data) {
1301            auto & dmgr =
1302                *reinterpret_cast<CustomJpegDestMgr*>(cinfo->client_data);
1303            dmgr.mSuccess = false;
1304        }
1305    };
1306    /* Now that we initialized some callbacks, let's create our compressor */
1307    jpeg_create_compress(&cinfo);
1308
1309    /* Initialize our destination manager */
1310    dmgr.mBuffer = static_cast<JOCTET*>(out);
1311    dmgr.mBufferSize = maxOutSize;
1312    dmgr.mEncodedSize = 0;
1313    dmgr.mSuccess = true;
1314    cinfo.client_data = static_cast<void*>(&dmgr);
1315
1316    /* These lambdas become C-style function pointers and as per C++11 spec
1317     * may not capture anything */
1318    dmgr.mgr.init_destination = [](j_compress_ptr cinfo) {
1319        auto & dmgr = reinterpret_cast<CustomJpegDestMgr&>(*cinfo->dest);
1320        dmgr.mgr.next_output_byte = dmgr.mBuffer;
1321        dmgr.mgr.free_in_buffer = dmgr.mBufferSize;
1322        ALOGV("%s:%d jpeg start: %p [%zu]",
1323              __FUNCTION__, __LINE__, dmgr.mBuffer, dmgr.mBufferSize);
1324    };
1325
1326    dmgr.mgr.empty_output_buffer = [](j_compress_ptr cinfo __unused) {
1327        ALOGV("%s:%d Out of buffer", __FUNCTION__, __LINE__);
1328        return 0;
1329    };
1330
1331    dmgr.mgr.term_destination = [](j_compress_ptr cinfo) {
1332        auto & dmgr = reinterpret_cast<CustomJpegDestMgr&>(*cinfo->dest);
1333        dmgr.mEncodedSize = dmgr.mBufferSize - dmgr.mgr.free_in_buffer;
1334        ALOGV("%s:%d Done with jpeg: %zu", __FUNCTION__, __LINE__, dmgr.mEncodedSize);
1335    };
1336    cinfo.dest = reinterpret_cast<struct jpeg_destination_mgr*>(&dmgr);
1337
1338    /* We are going to be using JPEG in raw data mode, so we are passing
1339     * straight subsampled planar YCbCr and it will not touch our pixel
1340     * data or do any scaling or anything */
1341    cinfo.image_width = inSz.width;
1342    cinfo.image_height = inSz.height;
1343    cinfo.input_components = 3;
1344    cinfo.in_color_space = JCS_YCbCr;
1345
1346    /* Initialize defaults and then override what we want */
1347    jpeg_set_defaults(&cinfo);
1348
1349    jpeg_set_quality(&cinfo, jpegQuality, 1);
1350    jpeg_set_colorspace(&cinfo, JCS_YCbCr);
1351    cinfo.raw_data_in = 1;
1352    cinfo.dct_method = JDCT_IFAST;
1353
1354    /* Configure sampling factors. The sampling factor is JPEG subsampling 420
1355     * because the source format is YUV420. Note that libjpeg sampling factors
1356     * are... a little weird. Sampling of Y=2,U=1,V=1 means there is 1 U and
1357     * 1 V value for each 2 Y values */
1358    cinfo.comp_info[0].h_samp_factor = 2;
1359    cinfo.comp_info[0].v_samp_factor = 2;
1360    cinfo.comp_info[1].h_samp_factor = 1;
1361    cinfo.comp_info[1].v_samp_factor = 1;
1362    cinfo.comp_info[2].h_samp_factor = 1;
1363    cinfo.comp_info[2].v_samp_factor = 1;
1364
1365    /* Let's not hardcode YUV420 in 6 places... 5 was enough */
1366    int maxVSampFactor = std::max( {
1367        cinfo.comp_info[0].v_samp_factor,
1368        cinfo.comp_info[1].v_samp_factor,
1369        cinfo.comp_info[2].v_samp_factor
1370    });
1371    int cVSubSampling = cinfo.comp_info[0].v_samp_factor /
1372                        cinfo.comp_info[1].v_samp_factor;
1373
1374    /* Start the compressor */
1375    jpeg_start_compress(&cinfo, TRUE);
1376
1377    /* Compute our macroblock height, so we can pad our input to be vertically
1378     * macroblock aligned.
1379     * TODO: Does it need to be horizontally MCU aligned too? */
1380
1381    size_t mcuV = DCTSIZE*maxVSampFactor;
1382    size_t paddedHeight = mcuV * ((inSz.height + mcuV - 1) / mcuV);
1383
1384    /* libjpeg uses arrays of row pointers, which makes it really easy to pad
1385     * data vertically (unfortunately doesn't help horizontally) */
1386    std::vector<JSAMPROW> yLines (paddedHeight);
1387    std::vector<JSAMPROW> cbLines(paddedHeight/cVSubSampling);
1388    std::vector<JSAMPROW> crLines(paddedHeight/cVSubSampling);
1389
1390    uint8_t *py = static_cast<uint8_t*>(inLayout.y);
1391    uint8_t *pcr = static_cast<uint8_t*>(inLayout.cr);
1392    uint8_t *pcb = static_cast<uint8_t*>(inLayout.cb);
1393
1394    for(uint32_t i = 0; i < paddedHeight; i++)
1395    {
1396        /* Once we are in the padding territory we still point to the last line
1397         * effectively replicating it several times ~ CLAMP_TO_EDGE */
1398        int li = std::min(i, inSz.height - 1);
1399        yLines[i]  = static_cast<JSAMPROW>(py + li * inLayout.yStride);
1400        if(i < paddedHeight / cVSubSampling)
1401        {
1402            crLines[i] = static_cast<JSAMPROW>(pcr + li * inLayout.cStride);
1403            cbLines[i] = static_cast<JSAMPROW>(pcb + li * inLayout.cStride);
1404        }
1405    }
1406
1407    /* If APP1 data was passed in, use it */
1408    if(app1Buffer && app1Size)
1409    {
1410        jpeg_write_marker(&cinfo, JPEG_APP0 + 1,
1411             static_cast<const JOCTET*>(app1Buffer), app1Size);
1412    }
1413
1414    /* While we still have padded height left to go, keep giving it one
1415     * macroblock at a time. */
1416    while (cinfo.next_scanline < cinfo.image_height) {
1417        const uint32_t batchSize = DCTSIZE * maxVSampFactor;
1418        const uint32_t nl = cinfo.next_scanline;
1419        JSAMPARRAY planes[3]{ &yLines[nl],
1420                              &cbLines[nl/cVSubSampling],
1421                              &crLines[nl/cVSubSampling] };
1422
1423        uint32_t done = jpeg_write_raw_data(&cinfo, planes, batchSize);
1424
1425        if (done != batchSize) {
1426            ALOGE("%s: compressed %u lines, expected %u (total %u/%u)",
1427              __FUNCTION__, done, batchSize, cinfo.next_scanline,
1428              cinfo.image_height);
1429            return -1;
1430        }
1431    }
1432
1433    /* This will flush everything */
1434    jpeg_finish_compress(&cinfo);
1435
1436    /* Grab the actual code size and set it */
1437    actualCodeSize = dmgr.mEncodedSize;
1438
1439    return 0;
1440}
1441
1442/*
1443 * TODO: There needs to be a mechanism to discover allocated buffer size
1444 * in the HAL.
1445 *
1446 * This is very fragile because it is duplicated computation from:
1447 * frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
1448 *
1449 */
1450
1451/* This assumes mSupportedFormats have all been declared as supporting
1452 * HAL_PIXEL_FORMAT_BLOB to the framework */
1453Size ExternalCameraDeviceSession::getMaxJpegResolution() const {
1454    Size ret { 0, 0 };
1455    for(auto & fmt : mSupportedFormats) {
1456        if(fmt.width * fmt.height > ret.width * ret.height) {
1457            ret = Size { fmt.width, fmt.height };
1458        }
1459    }
1460    return ret;
1461}
1462
1463Size ExternalCameraDeviceSession::getMaxThumbResolution() const {
1464    Size thumbSize { 0, 0 };
1465    camera_metadata_ro_entry entry =
1466        mCameraCharacteristics.find(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES);
1467    for(uint32_t i = 0; i < entry.count; i += 2) {
1468        Size sz { static_cast<uint32_t>(entry.data.i32[i]),
1469                  static_cast<uint32_t>(entry.data.i32[i+1]) };
1470        if(sz.width * sz.height > thumbSize.width * thumbSize.height) {
1471            thumbSize = sz;
1472        }
1473    }
1474
1475    if (thumbSize.width * thumbSize.height == 0) {
1476        ALOGW("%s: non-zero thumbnail size not available", __FUNCTION__);
1477    }
1478
1479    return thumbSize;
1480}
1481
1482
1483ssize_t ExternalCameraDeviceSession::getJpegBufferSize(
1484        uint32_t width, uint32_t height) const {
1485    // Constant from camera3.h
1486    const ssize_t kMinJpegBufferSize = 256 * 1024 + sizeof(CameraBlob);
1487    // Get max jpeg size (area-wise).
1488    if (mMaxJpegResolution.width == 0) {
1489        ALOGE("%s: Do not have a single supported JPEG stream",
1490                __FUNCTION__);
1491        return BAD_VALUE;
1492    }
1493
1494    // Get max jpeg buffer size
1495    ssize_t maxJpegBufferSize = 0;
1496    camera_metadata_ro_entry jpegBufMaxSize =
1497            mCameraCharacteristics.find(ANDROID_JPEG_MAX_SIZE);
1498    if (jpegBufMaxSize.count == 0) {
1499        ALOGE("%s: Can't find maximum JPEG size in static metadata!",
1500              __FUNCTION__);
1501        return BAD_VALUE;
1502    }
1503    maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
1504
1505    if (maxJpegBufferSize <= kMinJpegBufferSize) {
1506        ALOGE("%s: ANDROID_JPEG_MAX_SIZE (%zd) <= kMinJpegBufferSize (%zd)",
1507              __FUNCTION__, maxJpegBufferSize, kMinJpegBufferSize);
1508        return BAD_VALUE;
1509    }
1510
1511    // Calculate final jpeg buffer size for the given resolution.
1512    float scaleFactor = ((float) (width * height)) /
1513            (mMaxJpegResolution.width * mMaxJpegResolution.height);
1514    ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
1515            kMinJpegBufferSize;
1516    if (jpegBufferSize > maxJpegBufferSize) {
1517        jpegBufferSize = maxJpegBufferSize;
1518    }
1519
1520    return jpegBufferSize;
1521}
1522
1523int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
1524        HalStreamBuffer &halBuf,
1525        const std::shared_ptr<HalRequest>& req)
1526{
1527    ATRACE_CALL();
1528    int ret;
1529    auto lfail = [&](auto... args) {
1530        ALOGE(args...);
1531
1532        return 1;
1533    };
1534    auto parent = mParent.promote();
1535    if (parent == nullptr) {
1536       ALOGE("%s: session has been disconnected!", __FUNCTION__);
1537       return 1;
1538    }
1539
1540    ALOGV("%s: HAL buffer sid: %d bid: %" PRIu64 " w: %u h: %u",
1541          __FUNCTION__, halBuf.streamId, static_cast<uint64_t>(halBuf.bufferId),
1542          halBuf.width, halBuf.height);
1543    ALOGV("%s: HAL buffer fmt: %x usage: %" PRIx64 " ptr: %p",
1544          __FUNCTION__, halBuf.format, static_cast<uint64_t>(halBuf.usage),
1545          halBuf.bufPtr);
1546    ALOGV("%s: YV12 buffer %d x %d",
1547          __FUNCTION__,
1548          mYu12Frame->mWidth, mYu12Frame->mHeight);
1549
1550    int jpegQuality, thumbQuality;
1551    Size thumbSize;
1552    bool outputThumbnail = true;
1553
1554    if (req->setting.exists(ANDROID_JPEG_QUALITY)) {
1555        camera_metadata_entry entry =
1556            req->setting.find(ANDROID_JPEG_QUALITY);
1557        jpegQuality = entry.data.u8[0];
1558    } else {
1559        return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__);
1560    }
1561
1562    if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) {
1563        camera_metadata_entry entry =
1564            req->setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY);
1565        thumbQuality = entry.data.u8[0];
1566    } else {
1567        return lfail(
1568            "%s: ANDROID_JPEG_THUMBNAIL_QUALITY not set",
1569            __FUNCTION__);
1570    }
1571
1572    if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) {
1573        camera_metadata_entry entry =
1574            req->setting.find(ANDROID_JPEG_THUMBNAIL_SIZE);
1575        thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]),
1576                           static_cast<uint32_t>(entry.data.i32[1])
1577        };
1578        if (thumbSize.width == 0 && thumbSize.height == 0) {
1579            outputThumbnail = false;
1580        }
1581    } else {
1582        return lfail(
1583            "%s: ANDROID_JPEG_THUMBNAIL_SIZE not set", __FUNCTION__);
1584    }
1585
1586    /* Cropped and scaled YU12 buffer for main and thumbnail */
1587    YCbCrLayout yu12Main;
1588    Size jpegSize { halBuf.width, halBuf.height };
1589
1590    /* Compute temporary buffer sizes accounting for the following:
1591     * thumbnail can't exceed APP1 size of 64K
1592     * main image needs to hold APP1, headers, and at most a poorly
1593     * compressed image */
1594    const ssize_t maxThumbCodeSize = 64 * 1024;
1595    const ssize_t maxJpegCodeSize = parent->getJpegBufferSize(jpegSize.width,
1596                                                             jpegSize.height);
1597
1598    /* Check that getJpegBufferSize did not return an error */
1599    if (maxJpegCodeSize < 0) {
1600        return lfail(
1601            "%s: getJpegBufferSize returned %zd",__FUNCTION__,maxJpegCodeSize);
1602    }
1603
1604
1605    /* Hold actual thumbnail and main image code sizes */
1606    size_t thumbCodeSize = 0, jpegCodeSize = 0;
1607    /* Temporary thumbnail code buffer */
1608    std::vector<uint8_t> thumbCode(outputThumbnail ? maxThumbCodeSize : 0);
1609
1610    YCbCrLayout yu12Thumb;
1611    if (outputThumbnail) {
1612        ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb);
1613
1614        if (ret != 0) {
1615            return lfail(
1616                "%s: crop and scale thumbnail failed!", __FUNCTION__);
1617        }
1618    }
1619
1620    /* Scale and crop main jpeg */
1621    ret = cropAndScaleLocked(mYu12Frame, jpegSize, &yu12Main);
1622
1623    if (ret != 0) {
1624        return lfail("%s: crop and scale main failed!", __FUNCTION__);
1625    }
1626
1627    /* Encode the thumbnail image */
1628    if (outputThumbnail) {
1629        ret = encodeJpegYU12(thumbSize, yu12Thumb,
1630                thumbQuality, 0, 0,
1631                &thumbCode[0], maxThumbCodeSize, thumbCodeSize);
1632
1633        if (ret != 0) {
1634            return lfail("%s: thumbnail encodeJpegYU12 failed with %d",__FUNCTION__, ret);
1635        }
1636    }
1637
1638    /* Combine camera characteristics with request settings to form EXIF
1639     * metadata */
1640    common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics);
1641    meta.append(req->setting);
1642
1643    /* Generate EXIF object */
1644    std::unique_ptr<ExifUtils> utils(ExifUtils::create());
1645    /* Make sure it's initialized */
1646    utils->initialize();
1647
1648    utils->setFromMetadata(meta, jpegSize.width, jpegSize.height);
1649    utils->setMake(mExifMake);
1650    utils->setModel(mExifModel);
1651
1652    ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize);
1653
1654    if (!ret) {
1655        return lfail("%s: generating APP1 failed", __FUNCTION__);
1656    }
1657
1658    /* Get internal buffer */
1659    size_t exifDataSize = utils->getApp1Length();
1660    const uint8_t* exifData = utils->getApp1Buffer();
1661
1662    /* Lock the HAL jpeg code buffer */
1663    void *bufPtr = sHandleImporter.lock(
1664            *(halBuf.bufPtr), halBuf.usage, maxJpegCodeSize);
1665
1666    if (!bufPtr) {
1667        return lfail("%s: could not lock %zu bytes", __FUNCTION__, maxJpegCodeSize);
1668    }
1669
1670    /* Encode the main jpeg image */
1671    ret = encodeJpegYU12(jpegSize, yu12Main,
1672            jpegQuality, exifData, exifDataSize,
1673            bufPtr, maxJpegCodeSize, jpegCodeSize);
1674
1675    /* TODO: Not sure this belongs here, maybe better to pass jpegCodeSize out
1676     * and do this when returning buffer to parent */
1677    CameraBlob blob { CameraBlobId::JPEG, static_cast<uint32_t>(jpegCodeSize) };
1678    void *blobDst =
1679        reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(bufPtr) +
1680                           maxJpegCodeSize -
1681                           sizeof(CameraBlob));
1682    memcpy(blobDst, &blob, sizeof(CameraBlob));
1683
1684    /* Unlock the HAL jpeg code buffer */
1685    int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
1686    if (relFence > 0) {
1687        halBuf.acquireFence = relFence;
1688    }
1689
1690    /* Check if our JPEG actually succeeded */
1691    if (ret != 0) {
1692        return lfail(
1693            "%s: encodeJpegYU12 failed with %d",__FUNCTION__, ret);
1694    }
1695
1696    ALOGV("%s: encoded JPEG (ret:%d) with Q:%d max size: %zu",
1697          __FUNCTION__, ret, jpegQuality, maxJpegCodeSize);
1698
1699    return 0;
1700}
1701
1702bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
1703    std::shared_ptr<HalRequest> req;
1704    auto parent = mParent.promote();
1705    if (parent == nullptr) {
1706       ALOGE("%s: session has been disconnected!", __FUNCTION__);
1707       return false;
1708    }
1709
1710    // TODO: maybe we need to setup a sensor thread to dq/enq v4l frames
1711    //       regularly to prevent v4l buffer queue filled with stale buffers
1712    //       when app doesn't program a preveiw request
1713    waitForNextRequest(&req);
1714    if (req == nullptr) {
1715        // No new request, wait again
1716        return true;
1717    }
1718
1719    auto onDeviceError = [&](auto... args) {
1720        ALOGE(args...);
1721        parent->notifyError(
1722                req->frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
1723        signalRequestDone();
1724        return false;
1725    };
1726
1727    if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
1728        return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
1729                req->frameIn->mFourcc & 0xFF,
1730                (req->frameIn->mFourcc >> 8) & 0xFF,
1731                (req->frameIn->mFourcc >> 16) & 0xFF,
1732                (req->frameIn->mFourcc >> 24) & 0xFF);
1733    }
1734
1735    std::unique_lock<std::mutex> lk(mBufferLock);
1736    // Convert input V4L2 frame to YU12 of the same size
1737    // TODO: see if we can save some computation by converting to YV12 here
1738    uint8_t* inData;
1739    size_t inDataSize;
1740    req->frameIn->map(&inData, &inDataSize);
1741    // TODO: in some special case maybe we can decode jpg directly to gralloc output?
1742    ATRACE_BEGIN("MJPGtoI420");
1743    int res = libyuv::MJPGToI420(
1744            inData, inDataSize,
1745            static_cast<uint8_t*>(mYu12FrameLayout.y),
1746            mYu12FrameLayout.yStride,
1747            static_cast<uint8_t*>(mYu12FrameLayout.cb),
1748            mYu12FrameLayout.cStride,
1749            static_cast<uint8_t*>(mYu12FrameLayout.cr),
1750            mYu12FrameLayout.cStride,
1751            mYu12Frame->mWidth, mYu12Frame->mHeight,
1752            mYu12Frame->mWidth, mYu12Frame->mHeight);
1753    ATRACE_END();
1754
1755    if (res != 0) {
1756        // For some webcam, the first few V4L2 frames might be malformed...
1757        ALOGE("%s: Convert V4L2 frame to YU12 failed! res %d", __FUNCTION__, res);
1758        lk.unlock();
1759        Status st = parent->processCaptureRequestError(req);
1760        if (st != Status::OK) {
1761            return onDeviceError("%s: failed to process capture request error!", __FUNCTION__);
1762        }
1763        signalRequestDone();
1764        return true;
1765    }
1766
1767    ALOGV("%s processing new request", __FUNCTION__);
1768    const int kSyncWaitTimeoutMs = 500;
1769    for (auto& halBuf : req->buffers) {
1770        if (halBuf.acquireFence != -1) {
1771            int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
1772            if (ret) {
1773                halBuf.fenceTimeout = true;
1774            } else {
1775                ::close(halBuf.acquireFence);
1776                halBuf.acquireFence = -1;
1777            }
1778        }
1779
1780        if (halBuf.fenceTimeout) {
1781            continue;
1782        }
1783
1784        // Gralloc lockYCbCr the buffer
1785        switch (halBuf.format) {
1786            case PixelFormat::BLOB: {
1787                int ret = createJpegLocked(halBuf, req);
1788
1789                if(ret != 0) {
1790                    lk.unlock();
1791                    return onDeviceError("%s: createJpegLocked failed with %d",
1792                          __FUNCTION__, ret);
1793                }
1794            } break;
1795            case PixelFormat::YCBCR_420_888:
1796            case PixelFormat::YV12: {
1797                IMapper::Rect outRect {0, 0,
1798                        static_cast<int32_t>(halBuf.width),
1799                        static_cast<int32_t>(halBuf.height)};
1800                YCbCrLayout outLayout = sHandleImporter.lockYCbCr(
1801                        *(halBuf.bufPtr), halBuf.usage, outRect);
1802                ALOGV("%s: outLayout y %p cb %p cr %p y_str %d c_str %d c_step %d",
1803                        __FUNCTION__, outLayout.y, outLayout.cb, outLayout.cr,
1804                        outLayout.yStride, outLayout.cStride, outLayout.chromaStep);
1805
1806                // Convert to output buffer size/format
1807                uint32_t outputFourcc = getFourCcFromLayout(outLayout);
1808                ALOGV("%s: converting to format %c%c%c%c", __FUNCTION__,
1809                        outputFourcc & 0xFF,
1810                        (outputFourcc >> 8) & 0xFF,
1811                        (outputFourcc >> 16) & 0xFF,
1812                        (outputFourcc >> 24) & 0xFF);
1813
1814                YCbCrLayout cropAndScaled;
1815                ATRACE_BEGIN("cropAndScaleLocked");
1816                int ret = cropAndScaleLocked(
1817                        mYu12Frame,
1818                        Size { halBuf.width, halBuf.height },
1819                        &cropAndScaled);
1820                ATRACE_END();
1821                if (ret != 0) {
1822                    lk.unlock();
1823                    return onDeviceError("%s: crop and scale failed!", __FUNCTION__);
1824                }
1825
1826                Size sz {halBuf.width, halBuf.height};
1827                ATRACE_BEGIN("formatConvertLocked");
1828                ret = formatConvertLocked(cropAndScaled, outLayout, sz, outputFourcc);
1829                ATRACE_END();
1830                if (ret != 0) {
1831                    lk.unlock();
1832                    return onDeviceError("%s: format coversion failed!", __FUNCTION__);
1833                }
1834                int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
1835                if (relFence > 0) {
1836                    halBuf.acquireFence = relFence;
1837                }
1838            } break;
1839            default:
1840                lk.unlock();
1841                return onDeviceError("%s: unknown output format %x", __FUNCTION__, halBuf.format);
1842        }
1843    } // for each buffer
1844    mScaledYu12Frames.clear();
1845
1846    // Don't hold the lock while calling back to parent
1847    lk.unlock();
1848    Status st = parent->processCaptureResult(req);
1849    if (st != Status::OK) {
1850        return onDeviceError("%s: failed to process capture result!", __FUNCTION__);
1851    }
1852    signalRequestDone();
1853    return true;
1854}
1855
1856Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers(
1857        const Size& v4lSize, const Size& thumbSize,
1858        const hidl_vec<Stream>& streams) {
1859    std::lock_guard<std::mutex> lk(mBufferLock);
1860    if (mScaledYu12Frames.size() != 0) {
1861        ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)",
1862                __FUNCTION__, mScaledYu12Frames.size());
1863        return Status::INTERNAL_ERROR;
1864    }
1865
1866    // Allocating intermediate YU12 frame
1867    if (mYu12Frame == nullptr || mYu12Frame->mWidth != v4lSize.width ||
1868            mYu12Frame->mHeight != v4lSize.height) {
1869        mYu12Frame.clear();
1870        mYu12Frame = new AllocatedFrame(v4lSize.width, v4lSize.height);
1871        int ret = mYu12Frame->allocate(&mYu12FrameLayout);
1872        if (ret != 0) {
1873            ALOGE("%s: allocating YU12 frame failed!", __FUNCTION__);
1874            return Status::INTERNAL_ERROR;
1875        }
1876    }
1877
1878    // Allocating intermediate YU12 thumbnail frame
1879    if (mYu12ThumbFrame == nullptr ||
1880        mYu12ThumbFrame->mWidth != thumbSize.width ||
1881        mYu12ThumbFrame->mHeight != thumbSize.height) {
1882        mYu12ThumbFrame.clear();
1883        mYu12ThumbFrame = new AllocatedFrame(thumbSize.width, thumbSize.height);
1884        int ret = mYu12ThumbFrame->allocate(&mYu12ThumbFrameLayout);
1885        if (ret != 0) {
1886            ALOGE("%s: allocating YU12 thumb frame failed!", __FUNCTION__);
1887            return Status::INTERNAL_ERROR;
1888        }
1889    }
1890
1891    // Allocating scaled buffers
1892    for (const auto& stream : streams) {
1893        Size sz = {stream.width, stream.height};
1894        if (sz == v4lSize) {
1895            continue; // Don't need an intermediate buffer same size as v4lBuffer
1896        }
1897        if (mIntermediateBuffers.count(sz) == 0) {
1898            // Create new intermediate buffer
1899            sp<AllocatedFrame> buf = new AllocatedFrame(stream.width, stream.height);
1900            int ret = buf->allocate();
1901            if (ret != 0) {
1902                ALOGE("%s: allocating intermediate YU12 frame %dx%d failed!",
1903                            __FUNCTION__, stream.width, stream.height);
1904                return Status::INTERNAL_ERROR;
1905            }
1906            mIntermediateBuffers[sz] = buf;
1907        }
1908    }
1909
1910    // Remove unconfigured buffers
1911    auto it = mIntermediateBuffers.begin();
1912    while (it != mIntermediateBuffers.end()) {
1913        bool configured = false;
1914        auto sz = it->first;
1915        for (const auto& stream : streams) {
1916            if (stream.width == sz.width && stream.height == sz.height) {
1917                configured = true;
1918                break;
1919            }
1920        }
1921        if (configured) {
1922            it++;
1923        } else {
1924            it = mIntermediateBuffers.erase(it);
1925        }
1926    }
1927    return Status::OK;
1928}
1929
1930Status ExternalCameraDeviceSession::OutputThread::submitRequest(
1931        const std::shared_ptr<HalRequest>& req) {
1932    std::unique_lock<std::mutex> lk(mRequestListLock);
1933    mRequestList.push_back(req);
1934    lk.unlock();
1935    mRequestCond.notify_one();
1936    return Status::OK;
1937}
1938
1939void ExternalCameraDeviceSession::OutputThread::flush() {
1940    ATRACE_CALL();
1941    auto parent = mParent.promote();
1942    if (parent == nullptr) {
1943       ALOGE("%s: session has been disconnected!", __FUNCTION__);
1944       return;
1945    }
1946
1947    std::unique_lock<std::mutex> lk(mRequestListLock);
1948    std::list<std::shared_ptr<HalRequest>> reqs = std::move(mRequestList);
1949    mRequestList.clear();
1950    if (mProcessingRequest) {
1951        std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec);
1952        auto st = mRequestDoneCond.wait_for(lk, timeout);
1953        if (st == std::cv_status::timeout) {
1954            ALOGE("%s: wait for inflight request finish timeout!", __FUNCTION__);
1955        }
1956    }
1957
1958    ALOGV("%s: flusing inflight requests", __FUNCTION__);
1959    lk.unlock();
1960    for (const auto& req : reqs) {
1961        parent->processCaptureRequestError(req);
1962    }
1963}
1964
1965void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(
1966        std::shared_ptr<HalRequest>* out) {
1967    ATRACE_CALL();
1968    if (out == nullptr) {
1969        ALOGE("%s: out is null", __FUNCTION__);
1970        return;
1971    }
1972
1973    std::unique_lock<std::mutex> lk(mRequestListLock);
1974    int waitTimes = 0;
1975    while (mRequestList.empty()) {
1976        if (exitPending()) {
1977            return;
1978        }
1979        std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs);
1980        auto st = mRequestCond.wait_for(lk, timeout);
1981        if (st == std::cv_status::timeout) {
1982            waitTimes++;
1983            if (waitTimes == kReqWaitTimesMax) {
1984                // no new request, return
1985                return;
1986            }
1987        }
1988    }
1989    *out = mRequestList.front();
1990    mRequestList.pop_front();
1991    mProcessingRequest = true;
1992    mProcessingFrameNumer = (*out)->frameNumber;
1993}
1994
1995void ExternalCameraDeviceSession::OutputThread::signalRequestDone() {
1996    std::unique_lock<std::mutex> lk(mRequestListLock);
1997    mProcessingRequest = false;
1998    mProcessingFrameNumer = 0;
1999    lk.unlock();
2000    mRequestDoneCond.notify_one();
2001}
2002
2003void ExternalCameraDeviceSession::OutputThread::dump(int fd) {
2004    std::lock_guard<std::mutex> lk(mRequestListLock);
2005    if (mProcessingRequest) {
2006        dprintf(fd, "OutputThread processing frame %d\n", mProcessingFrameNumer);
2007    } else {
2008        dprintf(fd, "OutputThread not processing any frames\n");
2009    }
2010    dprintf(fd, "OutputThread request list contains frame: ");
2011    for (const auto& req : mRequestList) {
2012        dprintf(fd, "%d, ", req->frameNumber);
2013    }
2014    dprintf(fd, "\n");
2015}
2016
2017void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) {
2018    for (auto& pair : mCirculatingBuffers.at(id)) {
2019        sHandleImporter.freeBuffer(pair.second);
2020    }
2021    mCirculatingBuffers[id].clear();
2022    mCirculatingBuffers.erase(id);
2023}
2024
2025void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
2026    Mutex::Autolock _l(mLock);
2027    for (auto& cache : cachesToRemove) {
2028        auto cbsIt = mCirculatingBuffers.find(cache.streamId);
2029        if (cbsIt == mCirculatingBuffers.end()) {
2030            // The stream could have been removed
2031            continue;
2032        }
2033        CirculatingBuffers& cbs = cbsIt->second;
2034        auto it = cbs.find(cache.bufferId);
2035        if (it != cbs.end()) {
2036            sHandleImporter.freeBuffer(it->second);
2037            cbs.erase(it);
2038        } else {
2039            ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
2040                    __FUNCTION__, cache.streamId, cache.bufferId);
2041        }
2042    }
2043}
2044
2045bool ExternalCameraDeviceSession::isSupported(const Stream& stream) {
2046    int32_t ds = static_cast<int32_t>(stream.dataSpace);
2047    PixelFormat fmt = stream.format;
2048    uint32_t width = stream.width;
2049    uint32_t height = stream.height;
2050    // TODO: check usage flags
2051
2052    if (stream.streamType != StreamType::OUTPUT) {
2053        ALOGE("%s: does not support non-output stream type", __FUNCTION__);
2054        return false;
2055    }
2056
2057    if (stream.rotation != StreamRotation::ROTATION_0) {
2058        ALOGE("%s: does not support stream rotation", __FUNCTION__);
2059        return false;
2060    }
2061
2062    if (ds & Dataspace::DEPTH) {
2063        ALOGI("%s: does not support depth output", __FUNCTION__);
2064        return false;
2065    }
2066
2067    switch (fmt) {
2068        case PixelFormat::BLOB:
2069            if (ds != static_cast<int32_t>(Dataspace::V0_JFIF)) {
2070                ALOGI("%s: BLOB format does not support dataSpace %x", __FUNCTION__, ds);
2071                return false;
2072            }
2073        case PixelFormat::IMPLEMENTATION_DEFINED:
2074        case PixelFormat::YCBCR_420_888:
2075        case PixelFormat::YV12:
2076            // TODO: check what dataspace we can support here.
2077            // intentional no-ops.
2078            break;
2079        default:
2080            ALOGI("%s: does not support format %x", __FUNCTION__, fmt);
2081            return false;
2082    }
2083
2084    // Assume we can convert any V4L2 format to any of supported output format for now, i.e,
2085    // ignoring v4l2Fmt.fourcc for now. Might need more subtle check if we support more v4l format
2086    // in the futrue.
2087    for (const auto& v4l2Fmt : mSupportedFormats) {
2088        if (width == v4l2Fmt.width && height == v4l2Fmt.height) {
2089            return true;
2090        }
2091    }
2092    ALOGI("%s: resolution %dx%d is not supported", __FUNCTION__, width, height);
2093    return false;
2094}
2095
2096int ExternalCameraDeviceSession::v4l2StreamOffLocked() {
2097    if (!mV4l2Streaming) {
2098        return OK;
2099    }
2100
2101    {
2102        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
2103        if (mNumDequeuedV4l2Buffers != 0)  {
2104            ALOGE("%s: there are %zu inflight V4L buffers",
2105                __FUNCTION__, mNumDequeuedV4l2Buffers);
2106            return -1;
2107        }
2108    }
2109    mV4L2BufferCount = 0;
2110
2111    // VIDIOC_STREAMOFF
2112    v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2113    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMOFF, &capture_type)) < 0) {
2114        ALOGE("%s: STREAMOFF failed: %s", __FUNCTION__, strerror(errno));
2115        return -errno;
2116    }
2117
2118    // VIDIOC_REQBUFS: clear buffers
2119    v4l2_requestbuffers req_buffers{};
2120    req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2121    req_buffers.memory = V4L2_MEMORY_MMAP;
2122    req_buffers.count = 0;
2123    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
2124        ALOGE("%s: REQBUFS failed: %s", __FUNCTION__, strerror(errno));
2125        return -errno;
2126    }
2127
2128    mV4l2Streaming = false;
2129    return OK;
2130}
2131
2132int ExternalCameraDeviceSession::setV4l2FpsLocked(double fps) {
2133    // VIDIOC_G_PARM/VIDIOC_S_PARM: set fps
2134    v4l2_streamparm streamparm = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
2135    // The following line checks that the driver knows about framerate get/set.
2136    int ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_G_PARM, &streamparm));
2137    if (ret != 0) {
2138        if (errno == -EINVAL) {
2139            ALOGW("%s: device does not support VIDIOC_G_PARM", __FUNCTION__);
2140        }
2141        return -errno;
2142    }
2143    // Now check if the device is able to accept a capture framerate set.
2144    if (!(streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) {
2145        ALOGW("%s: device does not support V4L2_CAP_TIMEPERFRAME", __FUNCTION__);
2146        return -EINVAL;
2147    }
2148
2149    // fps is float, approximate by a fraction.
2150    const int kFrameRatePrecision = 10000;
2151    streamparm.parm.capture.timeperframe.numerator = kFrameRatePrecision;
2152    streamparm.parm.capture.timeperframe.denominator =
2153        (fps * kFrameRatePrecision);
2154
2155    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_PARM, &streamparm)) < 0) {
2156        ALOGE("%s: failed to set framerate to %f: %s", __FUNCTION__, fps, strerror(errno));
2157        return -1;
2158    }
2159
2160    double retFps = streamparm.parm.capture.timeperframe.denominator /
2161            static_cast<double>(streamparm.parm.capture.timeperframe.numerator);
2162    if (std::fabs(fps - retFps) > 1.0) {
2163        ALOGE("%s: expect fps %f, got %f instead", __FUNCTION__, fps, retFps);
2164        return -1;
2165    }
2166    mV4l2StreamingFps = fps;
2167    return 0;
2168}
2169
2170int ExternalCameraDeviceSession::configureV4l2StreamLocked(
2171        const SupportedV4L2Format& v4l2Fmt, double requestFps) {
2172    ATRACE_CALL();
2173    int ret = v4l2StreamOffLocked();
2174    if (ret != OK) {
2175        ALOGE("%s: stop v4l2 streaming failed: ret %d", __FUNCTION__, ret);
2176        return ret;
2177    }
2178
2179    // VIDIOC_S_FMT w/h/fmt
2180    v4l2_format fmt;
2181    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2182    fmt.fmt.pix.width = v4l2Fmt.width;
2183    fmt.fmt.pix.height = v4l2Fmt.height;
2184    fmt.fmt.pix.pixelformat = v4l2Fmt.fourcc;
2185    ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt));
2186    if (ret < 0) {
2187        int numAttempt = 0;
2188        while (ret < 0) {
2189            ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__);
2190            usleep(IOCTL_RETRY_SLEEP_US); // sleep and try again
2191            ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt));
2192            if (numAttempt == MAX_RETRY) {
2193                break;
2194            }
2195            numAttempt++;
2196        }
2197        if (ret < 0) {
2198            ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno));
2199            return -errno;
2200        }
2201    }
2202
2203    if (v4l2Fmt.width != fmt.fmt.pix.width || v4l2Fmt.height != fmt.fmt.pix.height ||
2204            v4l2Fmt.fourcc != fmt.fmt.pix.pixelformat) {
2205        ALOGE("%s: S_FMT expect %c%c%c%c %dx%d, got %c%c%c%c %dx%d instead!", __FUNCTION__,
2206                v4l2Fmt.fourcc & 0xFF,
2207                (v4l2Fmt.fourcc >> 8) & 0xFF,
2208                (v4l2Fmt.fourcc >> 16) & 0xFF,
2209                (v4l2Fmt.fourcc >> 24) & 0xFF,
2210                v4l2Fmt.width, v4l2Fmt.height,
2211                fmt.fmt.pix.pixelformat & 0xFF,
2212                (fmt.fmt.pix.pixelformat >> 8) & 0xFF,
2213                (fmt.fmt.pix.pixelformat >> 16) & 0xFF,
2214                (fmt.fmt.pix.pixelformat >> 24) & 0xFF,
2215                fmt.fmt.pix.width, fmt.fmt.pix.height);
2216        return -EINVAL;
2217    }
2218    uint32_t bufferSize = fmt.fmt.pix.sizeimage;
2219    ALOGI("%s: V4L2 buffer size is %d", __FUNCTION__, bufferSize);
2220    uint32_t expectedMaxBufferSize = kMaxBytesPerPixel * fmt.fmt.pix.width * fmt.fmt.pix.height;
2221    if ((bufferSize == 0) || (bufferSize > expectedMaxBufferSize)) {
2222        ALOGE("%s: V4L2 buffer size: %u looks invalid. Expected maximum size: %u", __FUNCTION__,
2223                bufferSize, expectedMaxBufferSize);
2224        return -EINVAL;
2225    }
2226    mMaxV4L2BufferSize = bufferSize;
2227
2228    const double kDefaultFps = 30.0;
2229    double fps = 1000.0;
2230    if (requestFps != 0.0) {
2231        fps = requestFps;
2232    } else {
2233        double maxFps = -1.0;
2234        // Try to pick the slowest fps that is at least 30
2235        for (const auto& fr : v4l2Fmt.frameRates) {
2236            double f = fr.getDouble();
2237            if (maxFps < f) {
2238                maxFps = f;
2239            }
2240            if (f >= kDefaultFps && f < fps) {
2241                fps = f;
2242            }
2243        }
2244        if (fps == 1000.0) {
2245            fps = maxFps;
2246        }
2247    }
2248
2249    int fpsRet = setV4l2FpsLocked(fps);
2250    if (fpsRet != 0 && fpsRet != -EINVAL) {
2251        ALOGE("%s: set fps failed: %s", __FUNCTION__, strerror(fpsRet));
2252        return fpsRet;
2253    }
2254
2255    uint32_t v4lBufferCount = (fps >= kDefaultFps) ?
2256            mCfg.numVideoBuffers : mCfg.numStillBuffers;
2257    // VIDIOC_REQBUFS: create buffers
2258    v4l2_requestbuffers req_buffers{};
2259    req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2260    req_buffers.memory = V4L2_MEMORY_MMAP;
2261    req_buffers.count = v4lBufferCount;
2262    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
2263        ALOGE("%s: VIDIOC_REQBUFS failed: %s", __FUNCTION__, strerror(errno));
2264        return -errno;
2265    }
2266
2267    // Driver can indeed return more buffer if it needs more to operate
2268    if (req_buffers.count < v4lBufferCount) {
2269        ALOGE("%s: VIDIOC_REQBUFS expected %d buffers, got %d instead",
2270                __FUNCTION__, v4lBufferCount, req_buffers.count);
2271        return NO_MEMORY;
2272    }
2273
2274    // VIDIOC_QUERYBUF:  get buffer offset in the V4L2 fd
2275    // VIDIOC_QBUF: send buffer to driver
2276    mV4L2BufferCount = req_buffers.count;
2277    for (uint32_t i = 0; i < req_buffers.count; i++) {
2278        v4l2_buffer buffer = {
2279            .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
2280            .index = i,
2281            .memory = V4L2_MEMORY_MMAP};
2282
2283        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
2284            ALOGE("%s: QUERYBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
2285            return -errno;
2286        }
2287
2288        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
2289            ALOGE("%s: QBUF %d failed: %s", __FUNCTION__, i,  strerror(errno));
2290            return -errno;
2291        }
2292    }
2293
2294    // VIDIOC_STREAMON: start streaming
2295    v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2296    ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type));
2297    if (ret < 0) {
2298        int numAttempt = 0;
2299        while (ret < 0) {
2300            ALOGW("%s: VIDIOC_STREAMON failed, wait 33ms and try again", __FUNCTION__);
2301            usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again
2302            ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type));
2303            if (numAttempt == MAX_RETRY) {
2304                break;
2305            }
2306            numAttempt++;
2307        }
2308        if (ret < 0) {
2309            ALOGE("%s: VIDIOC_STREAMON ioctl failed: %s", __FUNCTION__, strerror(errno));
2310            return -errno;
2311        }
2312    }
2313
2314    // Swallow first few frames after streamOn to account for bad frames from some devices
2315    for (int i = 0; i < kBadFramesAfterStreamOn; i++) {
2316        v4l2_buffer buffer{};
2317        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2318        buffer.memory = V4L2_MEMORY_MMAP;
2319        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
2320            ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
2321            return -errno;
2322        }
2323
2324        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
2325            ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, buffer.index, strerror(errno));
2326            return -errno;
2327        }
2328    }
2329
2330    ALOGI("%s: start V4L2 streaming %dx%d@%ffps",
2331                __FUNCTION__, v4l2Fmt.width, v4l2Fmt.height, fps);
2332    mV4l2StreamingFmt = v4l2Fmt;
2333    mV4l2Streaming = true;
2334    return OK;
2335}
2336
2337sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs) {
2338    ATRACE_CALL();
2339    sp<V4L2Frame> ret = nullptr;
2340
2341    if (shutterTs == nullptr) {
2342        ALOGE("%s: shutterTs must not be null!", __FUNCTION__);
2343        return ret;
2344    }
2345
2346    {
2347        std::unique_lock<std::mutex> lk(mV4l2BufferLock);
2348        if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) {
2349            int waitRet = waitForV4L2BufferReturnLocked(lk);
2350            if (waitRet != 0) {
2351                return ret;
2352            }
2353        }
2354    }
2355
2356    ATRACE_BEGIN("VIDIOC_DQBUF");
2357    v4l2_buffer buffer{};
2358    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2359    buffer.memory = V4L2_MEMORY_MMAP;
2360    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_DQBUF, &buffer)) < 0) {
2361        ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
2362        return ret;
2363    }
2364    ATRACE_END();
2365
2366    if (buffer.index >= mV4L2BufferCount) {
2367        ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
2368        return ret;
2369    }
2370
2371    if (buffer.flags & V4L2_BUF_FLAG_ERROR) {
2372        ALOGE("%s: v4l2 buf error! buf flag 0x%x", __FUNCTION__, buffer.flags);
2373        // TODO: try to dequeue again
2374    }
2375
2376    if (buffer.bytesused > mMaxV4L2BufferSize) {
2377        ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
2378                mMaxV4L2BufferSize);
2379        return ret;
2380    }
2381
2382    if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
2383        // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
2384        // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
2385        *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec)*1000000000LL +
2386                buffer.timestamp.tv_usec * 1000LL;
2387    } else {
2388        *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
2389    }
2390
2391    {
2392        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
2393        mNumDequeuedV4l2Buffers++;
2394    }
2395    return new V4L2Frame(
2396            mV4l2StreamingFmt.width, mV4l2StreamingFmt.height, mV4l2StreamingFmt.fourcc,
2397            buffer.index, mV4l2Fd.get(), buffer.bytesused, buffer.m.offset);
2398}
2399
2400void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
2401    ATRACE_CALL();
2402    frame->unmap();
2403    ATRACE_BEGIN("VIDIOC_QBUF");
2404    v4l2_buffer buffer{};
2405    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2406    buffer.memory = V4L2_MEMORY_MMAP;
2407    buffer.index = frame->mBufferIndex;
2408    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
2409        ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__,
2410                frame->mBufferIndex, strerror(errno));
2411        return;
2412    }
2413    ATRACE_END();
2414
2415    {
2416        std::lock_guard<std::mutex> lk(mV4l2BufferLock);
2417        mNumDequeuedV4l2Buffers--;
2418    }
2419    mV4L2BufferReturned.notify_one();
2420}
2421
2422Status ExternalCameraDeviceSession::configureStreams(
2423        const V3_2::StreamConfiguration& config, V3_3::HalStreamConfiguration* out) {
2424    ATRACE_CALL();
2425    if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) {
2426        ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode);
2427        return Status::ILLEGAL_ARGUMENT;
2428    }
2429
2430    if (config.streams.size() == 0) {
2431        ALOGE("%s: cannot configure zero stream", __FUNCTION__);
2432        return Status::ILLEGAL_ARGUMENT;
2433    }
2434
2435    int numProcessedStream = 0;
2436    int numStallStream = 0;
2437    for (const auto& stream : config.streams) {
2438        // Check if the format/width/height combo is supported
2439        if (!isSupported(stream)) {
2440            return Status::ILLEGAL_ARGUMENT;
2441        }
2442        if (stream.format == PixelFormat::BLOB) {
2443            numStallStream++;
2444        } else {
2445            numProcessedStream++;
2446        }
2447    }
2448
2449    if (numProcessedStream > kMaxProcessedStream) {
2450        ALOGE("%s: too many processed streams (expect <= %d, got %d)", __FUNCTION__,
2451                kMaxProcessedStream, numProcessedStream);
2452        return Status::ILLEGAL_ARGUMENT;
2453    }
2454
2455    if (numStallStream > kMaxStallStream) {
2456        ALOGE("%s: too many stall streams (expect <= %d, got %d)", __FUNCTION__,
2457                kMaxStallStream, numStallStream);
2458        return Status::ILLEGAL_ARGUMENT;
2459    }
2460
2461    Status status = initStatus();
2462    if (status != Status::OK) {
2463        return status;
2464    }
2465
2466
2467    {
2468        std::lock_guard<std::mutex> lk(mInflightFramesLock);
2469        if (!mInflightFrames.empty()) {
2470            ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
2471                    __FUNCTION__, mInflightFrames.size());
2472            return Status::INTERNAL_ERROR;
2473        }
2474    }
2475
2476    Mutex::Autolock _l(mLock);
2477    // Add new streams
2478    for (const auto& stream : config.streams) {
2479        if (mStreamMap.count(stream.id) == 0) {
2480            mStreamMap[stream.id] = stream;
2481            mCirculatingBuffers.emplace(stream.id, CirculatingBuffers{});
2482        }
2483    }
2484
2485    // Cleanup removed streams
2486    for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
2487        int id = it->first;
2488        bool found = false;
2489        for (const auto& stream : config.streams) {
2490            if (id == stream.id) {
2491                found = true;
2492                break;
2493            }
2494        }
2495        if (!found) {
2496            // Unmap all buffers of deleted stream
2497            cleanupBuffersLocked(id);
2498            it = mStreamMap.erase(it);
2499        } else {
2500            ++it;
2501        }
2502    }
2503
2504    // Now select a V4L2 format to produce all output streams
2505    float desiredAr = (mCroppingType == VERTICAL) ? kMaxAspectRatio : kMinAspectRatio;
2506    uint32_t maxDim = 0;
2507    for (const auto& stream : config.streams) {
2508        float aspectRatio = ASPECT_RATIO(stream);
2509        ALOGI("%s: request stream %dx%d", __FUNCTION__, stream.width, stream.height);
2510        if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) ||
2511                (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) {
2512            desiredAr = aspectRatio;
2513        }
2514
2515        // The dimension that's not cropped
2516        uint32_t dim = (mCroppingType == VERTICAL) ? stream.width : stream.height;
2517        if (dim > maxDim) {
2518            maxDim = dim;
2519        }
2520    }
2521    // Find the smallest format that matches the desired aspect ratio and is wide/high enough
2522    SupportedV4L2Format v4l2Fmt {.width = 0, .height = 0};
2523    for (const auto& fmt : mSupportedFormats) {
2524        uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height;
2525        if (dim >= maxDim) {
2526            float aspectRatio = ASPECT_RATIO(fmt);
2527            if (isAspectRatioClose(aspectRatio, desiredAr)) {
2528                v4l2Fmt = fmt;
2529                // since mSupportedFormats is sorted by width then height, the first matching fmt
2530                // will be the smallest one with matching aspect ratio
2531                break;
2532            }
2533        }
2534    }
2535    if (v4l2Fmt.width == 0) {
2536        // Cannot find exact good aspect ratio candidate, try to find a close one
2537        for (const auto& fmt : mSupportedFormats) {
2538            uint32_t dim = (mCroppingType == VERTICAL) ? fmt.width : fmt.height;
2539            if (dim >= maxDim) {
2540                float aspectRatio = ASPECT_RATIO(fmt);
2541                if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) ||
2542                        (mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) {
2543                    v4l2Fmt = fmt;
2544                    break;
2545                }
2546            }
2547        }
2548    }
2549
2550    if (v4l2Fmt.width == 0) {
2551        ALOGE("%s: unable to find a resolution matching (%s at least %d, aspect ratio %f)"
2552                , __FUNCTION__, (mCroppingType == VERTICAL) ? "width" : "height",
2553                maxDim, desiredAr);
2554        return Status::ILLEGAL_ARGUMENT;
2555    }
2556
2557    if (configureV4l2StreamLocked(v4l2Fmt) != 0) {
2558        ALOGE("V4L configuration failed!, format:%c%c%c%c, w %d, h %d",
2559            v4l2Fmt.fourcc & 0xFF,
2560            (v4l2Fmt.fourcc >> 8) & 0xFF,
2561            (v4l2Fmt.fourcc >> 16) & 0xFF,
2562            (v4l2Fmt.fourcc >> 24) & 0xFF,
2563            v4l2Fmt.width, v4l2Fmt.height);
2564        return Status::INTERNAL_ERROR;
2565    }
2566
2567    Size v4lSize = {v4l2Fmt.width, v4l2Fmt.height};
2568    Size thumbSize { 0, 0 };
2569    camera_metadata_ro_entry entry =
2570        mCameraCharacteristics.find(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES);
2571    for(uint32_t i = 0; i < entry.count; i += 2) {
2572        Size sz { static_cast<uint32_t>(entry.data.i32[i]),
2573                  static_cast<uint32_t>(entry.data.i32[i+1]) };
2574        if(sz.width * sz.height > thumbSize.width * thumbSize.height) {
2575            thumbSize = sz;
2576        }
2577    }
2578
2579    if (thumbSize.width * thumbSize.height == 0) {
2580        ALOGE("%s: non-zero thumbnail size not available", __FUNCTION__);
2581        return Status::INTERNAL_ERROR;
2582    }
2583
2584    status = mOutputThread->allocateIntermediateBuffers(v4lSize,
2585                mMaxThumbResolution, config.streams);
2586    if (status != Status::OK) {
2587        ALOGE("%s: allocating intermediate buffers failed!", __FUNCTION__);
2588        return status;
2589    }
2590
2591    out->streams.resize(config.streams.size());
2592    for (size_t i = 0; i < config.streams.size(); i++) {
2593        out->streams[i].overrideDataSpace = config.streams[i].dataSpace;
2594        out->streams[i].v3_2.id = config.streams[i].id;
2595        // TODO: double check should we add those CAMERA flags
2596        mStreamMap[config.streams[i].id].usage =
2597                out->streams[i].v3_2.producerUsage = config.streams[i].usage |
2598                BufferUsage::CPU_WRITE_OFTEN |
2599                BufferUsage::CAMERA_OUTPUT;
2600        out->streams[i].v3_2.consumerUsage = 0;
2601        out->streams[i].v3_2.maxBuffers  = mV4L2BufferCount;
2602
2603        switch (config.streams[i].format) {
2604            case PixelFormat::BLOB:
2605            case PixelFormat::YCBCR_420_888:
2606            case PixelFormat::YV12: // Used by SurfaceTexture
2607                // No override
2608                out->streams[i].v3_2.overrideFormat = config.streams[i].format;
2609                break;
2610            case PixelFormat::IMPLEMENTATION_DEFINED:
2611                // Override based on VIDEO or not
2612                out->streams[i].v3_2.overrideFormat =
2613                        (config.streams[i].usage & BufferUsage::VIDEO_ENCODER) ?
2614                        PixelFormat::YCBCR_420_888 : PixelFormat::YV12;
2615                // Save overridden formt in mStreamMap
2616                mStreamMap[config.streams[i].id].format = out->streams[i].v3_2.overrideFormat;
2617                break;
2618            default:
2619                ALOGE("%s: unsupported format 0x%x", __FUNCTION__, config.streams[i].format);
2620                return Status::ILLEGAL_ARGUMENT;
2621        }
2622    }
2623
2624    mFirstRequest = true;
2625    return Status::OK;
2626}
2627
2628bool ExternalCameraDeviceSession::isClosed() {
2629    Mutex::Autolock _l(mLock);
2630    return mClosed;
2631}
2632
2633#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
2634#define UPDATE(md, tag, data, size)               \
2635do {                                              \
2636    if ((md).update((tag), (data), (size))) {     \
2637        ALOGE("Update " #tag " failed!");         \
2638        return BAD_VALUE;                         \
2639    }                                             \
2640} while (0)
2641
2642status_t ExternalCameraDeviceSession::initDefaultRequests() {
2643    ::android::hardware::camera::common::V1_0::helper::CameraMetadata md;
2644
2645    const uint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;
2646    UPDATE(md, ANDROID_COLOR_CORRECTION_ABERRATION_MODE, &aberrationMode, 1);
2647
2648    const int32_t exposureCompensation = 0;
2649    UPDATE(md, ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, &exposureCompensation, 1);
2650
2651    const uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
2652    UPDATE(md, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, &videoStabilizationMode, 1);
2653
2654    const uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;
2655    UPDATE(md, ANDROID_CONTROL_AWB_MODE, &awbMode, 1);
2656
2657    const uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
2658    UPDATE(md, ANDROID_CONTROL_AE_MODE, &aeMode, 1);
2659
2660    const uint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
2661    UPDATE(md, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &aePrecaptureTrigger, 1);
2662
2663    const uint8_t afMode = ANDROID_CONTROL_AF_MODE_AUTO;
2664    UPDATE(md, ANDROID_CONTROL_AF_MODE, &afMode, 1);
2665
2666    const uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;
2667    UPDATE(md, ANDROID_CONTROL_AF_TRIGGER, &afTrigger, 1);
2668
2669    const uint8_t sceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
2670    UPDATE(md, ANDROID_CONTROL_SCENE_MODE, &sceneMode, 1);
2671
2672    const uint8_t effectMode = ANDROID_CONTROL_EFFECT_MODE_OFF;
2673    UPDATE(md, ANDROID_CONTROL_EFFECT_MODE, &effectMode, 1);
2674
2675    const uint8_t flashMode = ANDROID_FLASH_MODE_OFF;
2676    UPDATE(md, ANDROID_FLASH_MODE, &flashMode, 1);
2677
2678    const int32_t thumbnailSize[] = {240, 180};
2679    UPDATE(md, ANDROID_JPEG_THUMBNAIL_SIZE, thumbnailSize, 2);
2680
2681    const uint8_t jpegQuality = 90;
2682    UPDATE(md, ANDROID_JPEG_QUALITY, &jpegQuality, 1);
2683    UPDATE(md, ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
2684
2685    const int32_t jpegOrientation = 0;
2686    UPDATE(md, ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
2687
2688    const uint8_t oisMode = ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
2689    UPDATE(md, ANDROID_LENS_OPTICAL_STABILIZATION_MODE, &oisMode, 1);
2690
2691    const uint8_t nrMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
2692    UPDATE(md, ANDROID_NOISE_REDUCTION_MODE, &nrMode, 1);
2693
2694    const int32_t testPatternModes = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
2695    UPDATE(md, ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes, 1);
2696
2697    const uint8_t fdMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
2698    UPDATE(md, ANDROID_STATISTICS_FACE_DETECT_MODE, &fdMode, 1);
2699
2700    const uint8_t hotpixelMode = ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
2701    UPDATE(md, ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, &hotpixelMode, 1);
2702
2703    bool support30Fps = false;
2704    int32_t maxFps = std::numeric_limits<int32_t>::min();
2705    for (const auto& supportedFormat : mSupportedFormats) {
2706        for (const auto& fr : supportedFormat.frameRates) {
2707            int32_t framerateInt = static_cast<int32_t>(fr.getDouble());
2708            if (maxFps < framerateInt) {
2709                maxFps = framerateInt;
2710            }
2711            if (framerateInt == 30) {
2712                support30Fps = true;
2713                break;
2714            }
2715        }
2716        if (support30Fps) {
2717            break;
2718        }
2719    }
2720    int32_t defaultFramerate = support30Fps ? 30 : maxFps;
2721    int32_t defaultFpsRange[] = {defaultFramerate / 2, defaultFramerate};
2722    UPDATE(md, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, defaultFpsRange, ARRAY_SIZE(defaultFpsRange));
2723
2724    uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
2725    UPDATE(md, ANDROID_CONTROL_AE_ANTIBANDING_MODE, &antibandingMode, 1);
2726
2727    const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
2728    UPDATE(md, ANDROID_CONTROL_MODE, &controlMode, 1);
2729
2730    auto requestTemplates = hidl_enum_iterator<RequestTemplate>();
2731    for (RequestTemplate type : requestTemplates) {
2732        ::android::hardware::camera::common::V1_0::helper::CameraMetadata mdCopy = md;
2733        uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
2734        switch (type) {
2735            case RequestTemplate::PREVIEW:
2736                intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
2737                break;
2738            case RequestTemplate::STILL_CAPTURE:
2739                intent = ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
2740                break;
2741            case RequestTemplate::VIDEO_RECORD:
2742                intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
2743                break;
2744            case RequestTemplate::VIDEO_SNAPSHOT:
2745                intent = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT;
2746                break;
2747            default:
2748                ALOGV("%s: unsupported RequestTemplate type %d", __FUNCTION__, type);
2749                continue;
2750        }
2751        UPDATE(mdCopy, ANDROID_CONTROL_CAPTURE_INTENT, &intent, 1);
2752
2753        camera_metadata_t* rawMd = mdCopy.release();
2754        CameraMetadata hidlMd;
2755        hidlMd.setToExternal(
2756                (uint8_t*) rawMd, get_camera_metadata_size(rawMd));
2757        mDefaultRequests[type] = hidlMd;
2758        free_camera_metadata(rawMd);
2759    }
2760
2761    return OK;
2762}
2763
2764status_t ExternalCameraDeviceSession::fillCaptureResult(
2765        common::V1_0::helper::CameraMetadata &md, nsecs_t timestamp) {
2766    // android.control
2767    // For USB camera, we don't know the AE state. Set the state to converged to
2768    // indicate the frame should be good to use. Then apps don't have to wait the
2769    // AE state.
2770    const uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED;
2771    UPDATE(md, ANDROID_CONTROL_AE_STATE, &aeState, 1);
2772
2773    const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
2774    UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
2775
2776    bool afTrigger = false;
2777    {
2778        std::lock_guard<std::mutex> lk(mAfTriggerLock);
2779        afTrigger = mAfTrigger;
2780        if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
2781            camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
2782            if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
2783                mAfTrigger = afTrigger = true;
2784            } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
2785                mAfTrigger = afTrigger = false;
2786            }
2787        }
2788    }
2789
2790    // For USB camera, the USB camera handles everything and we don't have control
2791    // over AF. We only simply fake the AF metadata based on the request
2792    // received here.
2793    uint8_t afState;
2794    if (afTrigger) {
2795        afState = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
2796    } else {
2797        afState = ANDROID_CONTROL_AF_STATE_INACTIVE;
2798    }
2799    UPDATE(md, ANDROID_CONTROL_AF_STATE, &afState, 1);
2800
2801    // Set AWB state to converged to indicate the frame should be good to use.
2802    const uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED;
2803    UPDATE(md, ANDROID_CONTROL_AWB_STATE, &awbState, 1);
2804
2805    const uint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;
2806    UPDATE(md, ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
2807
2808    camera_metadata_ro_entry active_array_size =
2809        mCameraCharacteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
2810
2811    if (active_array_size.count == 0) {
2812        ALOGE("%s: cannot find active array size!", __FUNCTION__);
2813        return -EINVAL;
2814    }
2815
2816    const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
2817    UPDATE(md, ANDROID_FLASH_STATE, &flashState, 1);
2818
2819    // This means pipeline latency of X frame intervals. The maximum number is 4.
2820    const uint8_t requestPipelineMaxDepth = 4;
2821    UPDATE(md, ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
2822
2823    // android.scaler
2824    const int32_t crop_region[] = {
2825          active_array_size.data.i32[0], active_array_size.data.i32[1],
2826          active_array_size.data.i32[2], active_array_size.data.i32[3],
2827    };
2828    UPDATE(md, ANDROID_SCALER_CROP_REGION, crop_region, ARRAY_SIZE(crop_region));
2829
2830    // android.sensor
2831    UPDATE(md, ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
2832
2833    // android.statistics
2834    const uint8_t lensShadingMapMode = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
2835    UPDATE(md, ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, &lensShadingMapMode, 1);
2836
2837    const uint8_t sceneFlicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;
2838    UPDATE(md, ANDROID_STATISTICS_SCENE_FLICKER, &sceneFlicker, 1);
2839
2840    return OK;
2841}
2842
2843#undef ARRAY_SIZE
2844#undef UPDATE
2845
2846}  // namespace implementation
2847}  // namespace V3_4
2848}  // namespace device
2849}  // namespace camera
2850}  // namespace hardware
2851}  // namespace android
2852