Home | History | Annotate | Download | only in default
      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 
     17 #define LOG_TAG "ExtCamDevSsn (at) 3.5"
     18 #include <android/log.h>
     19 
     20 #include <utils/Trace.h>
     21 #include "ExternalCameraDeviceSession.h"
     22 
     23 namespace android {
     24 namespace hardware {
     25 namespace camera {
     26 namespace device {
     27 namespace V3_5 {
     28 namespace implementation {
     29 
     30 ExternalCameraDeviceSession::ExternalCameraDeviceSession(
     31         const sp<V3_2::ICameraDeviceCallback>& callback,
     32         const ExternalCameraConfig& cfg,
     33         const std::vector<SupportedV4L2Format>& sortedFormats,
     34         const CroppingType& croppingType,
     35         const common::V1_0::helper::CameraMetadata& chars,
     36         const std::string& cameraId,
     37         unique_fd v4l2Fd) :
     38         V3_4::implementation::ExternalCameraDeviceSession(
     39                 callback, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd)) {
     40 
     41     mCallback_3_5 = nullptr;
     42 
     43     auto castResult = V3_5::ICameraDeviceCallback::castFrom(callback);
     44     if (castResult.isOk()) {
     45         sp<V3_5::ICameraDeviceCallback> callback3_5 = castResult;
     46         if (callback3_5 != nullptr) {
     47             mCallback_3_5 = callback3_5;
     48         }
     49     }
     50 
     51     if (mCallback_3_5 != nullptr) {
     52         mSupportBufMgr = true;
     53     }
     54 }
     55 
     56 ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
     57     closeOutputThreadImpl();
     58 }
     59 
     60 Return<void> ExternalCameraDeviceSession::configureStreams_3_5(
     61         const StreamConfiguration& requestedConfiguration,
     62         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
     63     return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
     64 }
     65 
     66 Return<void> ExternalCameraDeviceSession::signalStreamFlush(
     67         const hidl_vec<int32_t>& /*streamIds*/, uint32_t /*streamConfigCounter*/) {
     68     return Void();
     69 }
     70 
     71 Status ExternalCameraDeviceSession::importRequestLocked(
     72         const CaptureRequest& request,
     73         hidl_vec<buffer_handle_t*>& allBufPtrs,
     74         hidl_vec<int>& allFences) {
     75     if (mSupportBufMgr) {
     76         return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
     77     }
     78     return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
     79 }
     80 
     81 
     82 ExternalCameraDeviceSession::BufferRequestThread::BufferRequestThread(
     83         wp<ExternalCameraDeviceSession> parent,
     84         sp<V3_5::ICameraDeviceCallback> callbacks) :
     85         mParent(parent),
     86         mCallbacks(callbacks) {}
     87 
     88 int ExternalCameraDeviceSession::BufferRequestThread::requestBufferStart(
     89         const std::vector<HalStreamBuffer>& bufReqs) {
     90     if (bufReqs.empty()) {
     91         ALOGE("%s: bufReqs is empty!", __FUNCTION__);
     92         return -1;
     93     }
     94 
     95     {
     96         std::lock_guard<std::mutex> lk(mLock);
     97         if (mRequestingBuffer) {
     98             ALOGE("%s: BufferRequestThread does not support more than one concurrent request!",
     99                     __FUNCTION__);
    100             return -1;
    101         }
    102 
    103         mBufferReqs = bufReqs;
    104         mRequestingBuffer = true;
    105     }
    106     mRequestCond.notify_one();
    107     return 0;
    108 }
    109 
    110 int ExternalCameraDeviceSession::BufferRequestThread::waitForBufferRequestDone(
    111         std::vector<HalStreamBuffer>* outBufReq) {
    112     std::unique_lock<std::mutex> lk(mLock);
    113     if (!mRequestingBuffer) {
    114         ALOGE("%s: no pending buffer request!", __FUNCTION__);
    115         return -1;
    116     }
    117 
    118     if (mPendingReturnBufferReqs.empty()) {
    119         std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqProcTimeoutMs);
    120         auto st = mRequestDoneCond.wait_for(lk, timeout);
    121         if (st == std::cv_status::timeout) {
    122             ALOGE("%s: wait for buffer request finish timeout!", __FUNCTION__);
    123             return -1;
    124         }
    125     }
    126     mRequestingBuffer = false;
    127     *outBufReq = std::move(mPendingReturnBufferReqs);
    128     mPendingReturnBufferReqs.clear();
    129     return 0;
    130 }
    131 
    132 void ExternalCameraDeviceSession::BufferRequestThread::waitForNextRequest() {
    133     ATRACE_CALL();
    134     std::unique_lock<std::mutex> lk(mLock);
    135     int waitTimes = 0;
    136     while (mBufferReqs.empty()) {
    137         if (exitPending()) {
    138             return;
    139         }
    140         std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs);
    141         auto st = mRequestCond.wait_for(lk, timeout);
    142         if (st == std::cv_status::timeout) {
    143             waitTimes++;
    144             if (waitTimes == kReqWaitTimesWarn) {
    145                 // BufferRequestThread just wait forever for new buffer request
    146                 // But it will print some periodic warning indicating it's waiting
    147                 ALOGV("%s: still waiting for new buffer request", __FUNCTION__);
    148                 waitTimes = 0;
    149             }
    150         }
    151     }
    152 
    153     // Fill in hidl BufferRequest
    154     mHalBufferReqs.resize(mBufferReqs.size());
    155     for (size_t i = 0; i < mHalBufferReqs.size(); i++) {
    156         mHalBufferReqs[i].streamId = mBufferReqs[i].streamId;
    157         mHalBufferReqs[i].numBuffersRequested = 1;
    158     }
    159 }
    160 
    161 bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() {
    162     waitForNextRequest();
    163     if (exitPending()) {
    164         return false;
    165     }
    166 
    167     ATRACE_BEGIN("HIDL requestStreamBuffers");
    168     BufferRequestStatus status;
    169     hidl_vec<StreamBufferRet> bufRets;
    170     auto err = mCallbacks->requestStreamBuffers(mHalBufferReqs,
    171             [&status, &bufRets]
    172             (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
    173                 status = s;
    174                 bufRets = std::move(rets);
    175             });
    176     ATRACE_END();
    177     if (!err.isOk()) {
    178         ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
    179         return false;
    180     }
    181 
    182     std::unique_lock<std::mutex> lk(mLock);
    183     if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
    184         if (bufRets.size() != mHalBufferReqs.size()) {
    185             ALOGE("%s: expect %zu buffer requests returned, only got %zu",
    186                     __FUNCTION__, mHalBufferReqs.size(), bufRets.size());
    187             return false;
    188         }
    189 
    190         auto parent = mParent.promote();
    191         if (parent == nullptr) {
    192             ALOGE("%s: session has been disconnected!", __FUNCTION__);
    193             return false;
    194         }
    195 
    196         hidl_vec<int> importedFences;
    197         importedFences.resize(bufRets.size());
    198         for (size_t i = 0; i < bufRets.size(); i++) {
    199             int streamId = bufRets[i].streamId;
    200             switch (bufRets[i].val.getDiscriminator()) {
    201                 case StreamBuffersVal::hidl_discriminator::error:
    202                     continue;
    203                 case StreamBuffersVal::hidl_discriminator::buffers: {
    204                     const hidl_vec<V3_2::StreamBuffer>& hBufs = bufRets[i].val.buffers();
    205                     if (hBufs.size() != 1) {
    206                         ALOGE("%s: expect 1 buffer returned, got %zu!", __FUNCTION__, hBufs.size());
    207                         return false;
    208                     }
    209                     const V3_2::StreamBuffer& hBuf = hBufs[0];
    210 
    211                     mBufferReqs[i].bufferId = hBuf.bufferId;
    212                     // TODO: create a batch import API so we don't need to lock/unlock mCbsLock
    213                     // repeatedly?
    214                     lk.unlock();
    215                     Status s = parent->importBuffer(streamId,
    216                             hBuf.bufferId, hBuf.buffer.getNativeHandle(),
    217                             /*out*/&mBufferReqs[i].bufPtr,
    218                             /*allowEmptyBuf*/false);
    219                     lk.lock();
    220 
    221                     if (s != Status::OK) {
    222                         ALOGE("%s: stream %d import buffer failed!", __FUNCTION__, streamId);
    223                         cleanupInflightFences(importedFences, i - 1);
    224                         return false;
    225                     }
    226                     if (!sHandleImporter.importFence(hBuf.acquireFence,
    227                             mBufferReqs[i].acquireFence)) {
    228                         ALOGE("%s: stream %d import fence failed!", __FUNCTION__, streamId);
    229                         cleanupInflightFences(importedFences, i - 1);
    230                         return false;
    231                     }
    232                     importedFences[i] = mBufferReqs[i].acquireFence;
    233                 }
    234                 break;
    235                 default:
    236                     ALOGE("%s: unkown StreamBuffersVal discrimator!", __FUNCTION__);
    237                     return false;
    238             }
    239         }
    240     } else {
    241         ALOGE("%s: requestStreamBuffers call failed!", __FUNCTION__);
    242     }
    243 
    244     mPendingReturnBufferReqs = std::move(mBufferReqs);
    245     mBufferReqs.clear();
    246 
    247     lk.unlock();
    248     mRequestDoneCond.notify_one();
    249     return true;
    250 }
    251 
    252 void ExternalCameraDeviceSession::initOutputThread() {
    253     if (mSupportBufMgr) {
    254         mBufferRequestThread = new BufferRequestThread(this, mCallback_3_5);
    255         mBufferRequestThread->run("ExtCamBufReq", PRIORITY_DISPLAY);
    256     }
    257     mOutputThread = new OutputThread(this, mCroppingType, mBufferRequestThread);
    258 }
    259 
    260 void ExternalCameraDeviceSession::closeOutputThreadImpl() {
    261     if (mBufferRequestThread) {
    262         mBufferRequestThread->requestExit();
    263         mBufferRequestThread->join();
    264         mBufferRequestThread.clear();
    265     }
    266 }
    267 
    268 void ExternalCameraDeviceSession::closeOutputThread() {
    269     closeOutputThreadImpl();
    270     V3_4::implementation::ExternalCameraDeviceSession::closeOutputThread();
    271 }
    272 
    273 ExternalCameraDeviceSession::OutputThread::OutputThread(
    274         wp<ExternalCameraDeviceSession> parent,
    275         CroppingType ct,
    276         sp<BufferRequestThread> bufReqThread) :
    277         V3_4::implementation::ExternalCameraDeviceSession::OutputThread(parent, ct),
    278         mBufferRequestThread(bufReqThread) {}
    279 
    280 ExternalCameraDeviceSession::OutputThread::~OutputThread() {}
    281 
    282 int ExternalCameraDeviceSession::OutputThread::requestBufferStart(
    283         const std::vector<HalStreamBuffer>& bufs) {
    284     if (mBufferRequestThread != nullptr) {
    285         return mBufferRequestThread->requestBufferStart(bufs);
    286     }
    287     return 0;
    288 }
    289 
    290 int ExternalCameraDeviceSession::OutputThread::waitForBufferRequestDone(
    291         /*out*/std::vector<HalStreamBuffer>* outBufs) {
    292     if (mBufferRequestThread != nullptr) {
    293         return mBufferRequestThread->waitForBufferRequestDone(outBufs);
    294     }
    295     return 0;
    296 }
    297 
    298 Return<void> ExternalCameraDeviceSession::isReconfigurationRequired(
    299         const V3_2::CameraMetadata& /*oldSessionParams*/,
    300         const V3_2::CameraMetadata& /*newSessionParams*/,
    301         ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) {
    302     //Stub implementation
    303     _hidl_cb(Status::OK, true);
    304     return Void();
    305 }
    306 
    307 } // namespace implementation
    308 }  // namespace V3_5
    309 }  // namespace device
    310 }  // namespace camera
    311 }  // namespace hardware
    312 }  // namespace android
    313