基于Android Camera2 RequestThread预览流程分析

999 阅读29分钟

基于Android Q分析

开启预览的流程:

openCamera -- onOpened -->

CameraCaptureSession/CameraCaptureRequest -- onConfigured -->

setRepeatingRequest

request的整体处理流程:

Camera model.png

1 CameraDeviceImpl.setRepeatingRequest()

setRepeatingRequest方法的实现是由CameraCaptureSessionImpl来完成;

public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
        Executor executor) throws CameraAccessException {
    List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
    requestList.add(request);
    return submitCaptureRequest(requestList, callback, executor, /*streaming*/true);
}

第一个参数CaptureRequest只有一个Request,然后将request包装成List,那么很明显,List的元素个数就只有一个,然后传入到submitCaptureRequest()方法中,

private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
        Executor executor, boolean repeating) throws CameraAccessException {
​
    // Need a valid executor, or current thread needs to have a looper, if
    // callback is valid
    executor = checkExecutor(executor, callback);
​
    synchronized(mInterfaceLock) {
        checkIfCameraClosedOrInError();
​
        // Make sure that there all requests have at least 1 surface; all surfaces are non-null;
        // 对addTarget()方法传入的Surface list进行检查
        for (CaptureRequest request : requestList) {
            if (request.getTargets().isEmpty()) {
                throw new IllegalArgumentException(
                        "Each request must have at least one Surface target");
            }
​
            for (Surface surface : request.getTargets()) {
                // 需要确保所有的surface都是非空
                if (surface == null) {
                    throw new IllegalArgumentException("Null Surface targets are not allowed");
                }
            }
        }
​
        if (repeating) {
            stopRepeating();
        }
​
        // 用于接收request submit之后的信息
        SubmitInfo requestInfo;
​
        CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
        // Convert Surface to streamIdx and surfaceIdx
        for (CaptureRequest request : requestArray) {
            request.convertSurfaceToStreamId(mConfiguredOutputs);
        }
​
        requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
        if (DEBUG) {
            Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
        }
​
        for (CaptureRequest request : requestArray) {
            // 与convertSurfaceToStreamId()方法成对出现
            request.recoverStreamIdToSurface();
        }
​
        // 一般在setRepeatingRequest时,callback为null
        if (callback != null) {
            mCaptureCallbackMap.put(requestInfo.getRequestId(),
                    new CaptureCallbackHolder(
                        callback, requestList, executor, repeating, mNextSessionId - 1));
        } else {
            if (DEBUG) {
                Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
            }
        }
​
        // repeating表示是否重复,也就是预览,repeating 为入参属性,默认值为true
        // repeating决定当前request插入到哪个队列当中
        if (repeating) {
            if (mRepeatingRequestId != REQUEST_ID_NONE) {
                checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId,
                        requestInfo.getLastFrameNumber(),
                        mRepeatingRequestTypes);
            }
            mRepeatingRequestId = requestInfo.getRequestId();
            // 获取request数组的Type属性数组,一般只有一个request,所以对应只有一个type值的数组
            mRepeatingRequestTypes = getRequestTypes(requestArray);
        } else {
            mRequestLastFrameNumbersList.add(
                new RequestLastFrameNumbersHolder(requestList, requestInfo));
        }
​
        if (mIdle) {
            mDeviceExecutor.execute(mCallOnActive);
        }
        mIdle = false;
​
        return requestInfo.getRequestId();
    }
}

该方法先对handler、Surface参数进行检查,如果检查出错,就直接抛出异常,request.getTargets()得到的就是我们在APP层放进去的Surface对象了;参数检查完成后,又将它转换成数组,然后调用mRemoteDevice.submitRequestList(requestArray, repeating)提交到CameraServer进程当中。第二个参数repeating表示是否重复,也就是预览的意思,该参数的两种取值为true就表示是预览请求,需要重复;为false表示是拍照,只有一帧,不需要重复,该参数往下传递,会在CameraServer中决定当前Request插入到哪个队列当中;

2 CameraDeivceClient.submitRequestList()

binder::Status CameraDeviceClient::submitRequestList(
        const std::vector<hardware::camera2::CaptureRequest>& requests,
        bool streaming,
        /*out*/
        hardware::camera2::utils::SubmitInfo *submitInfo) {
    ATRACE_CALL();
    ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
​
    binder::Status res = binder::Status::ok();
    status_t err;
    if ( !(res = checkPidStatus(__FUNCTION__) ).isOk()) {
        return res;
    }
​
    Mutex::Autolock icl(mBinderSerializationLock);
​
    if (!mDevice.get()) {
        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
    }
​
    if (requests.empty()) {
        ALOGE("%s: Camera %s: Sent null request. Rejecting request.",
              __FUNCTION__, mCameraIdStr.string());
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
    }
​
    List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
    std::list<const SurfaceMap> surfaceMapList;
    submitInfo->mRequestId = mRequestIdCounter;
    uint32_t loopCounter = 0;
​
    for (auto&& request: requests) {
        if (request.mIsReprocess) {
            if (!mInputStream.configured) {
                ALOGE("%s: Camera %s: no input stream is configured.", __FUNCTION__,
                        mCameraIdStr.string());
                return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                        "No input configured for camera %s but request is for reprocessing",
                        mCameraIdStr.string());
            } else if (streaming) {
                ALOGE("%s: Camera %s: streaming reprocess requests not supported.", __FUNCTION__,
                        mCameraIdStr.string());
                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                        "Repeating reprocess requests not supported");
            } else if (request.mPhysicalCameraSettings.size() > 1) {
                ALOGE("%s: Camera %s: reprocess requests not supported for "
                        "multiple physical cameras.", __FUNCTION__,
                        mCameraIdStr.string());
                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                        "Reprocess requests not supported for multiple cameras");
            }
        }
​
        if (request.mPhysicalCameraSettings.empty()) {
            ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
                    mCameraIdStr.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                    "Request doesn't contain any settings");
        }
​
        //The first capture settings should always match the logical camera id
        String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
        if (mDevice->getId() != logicalId) {
            ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
                    mCameraIdStr.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                    "Invalid camera request settings");
        }
​
        if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
            ALOGE("%s: Camera %s: Requests must have at least one surface target. "
                    "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                    "Request has no output targets");
        }
​
        /**
         * Write in the output stream IDs and map from stream ID to surface ID
         * which we calculate from the capture request's list of surface target
         */
        SurfaceMap surfaceMap;
        Vector<int32_t> outputStreamIds;
        std::vector<std::string> requestedPhysicalIds;
        if (request.mSurfaceList.size() > 0) {
            for (const sp<Surface>& surface : request.mSurfaceList) {
                if (surface == 0) continue;
​
                int32_t streamId;
                sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
                res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds, &streamId);
                if (!res.isOk()) {
                    return res;
                }
​
                ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
                if (index >= 0) {
                    String8 requestedPhysicalId(
                            mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
                    requestedPhysicalIds.push_back(requestedPhysicalId.string());
                } else {
                    ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
                }
            }
        } else {
            for (size_t i = 0; i < request.mStreamIdxList.size(); i++) {
                int streamId = request.mStreamIdxList.itemAt(i);
                int surfaceIdx = request.mSurfaceIdxList.itemAt(i);
​
                ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
                if (index < 0) {
                    ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                            " we have not called createStream on: stream %d",
                            __FUNCTION__, mCameraIdStr.string(), streamId);
                    return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                            "Request targets Surface that is not part of current capture session");
                }
​
                const auto& gbps = mConfiguredOutputs.valueAt(index).getGraphicBufferProducers();
                if ((size_t)surfaceIdx >= gbps.size()) {
                    ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                            " we have not called createStream on: stream %d, surfaceIdx %d",
                            __FUNCTION__, mCameraIdStr.string(), streamId, surfaceIdx);
                    return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                            "Request targets Surface has invalid surface index");
                }
​
                res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
                if (!res.isOk()) {
                    return res;
                }
​
                String8 requestedPhysicalId(
                        mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
                requestedPhysicalIds.push_back(requestedPhysicalId.string());
            }
        }
​
        CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
        for (const auto& it : request.mPhysicalCameraSettings) {
            if (it.settings.isEmpty()) {
                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
                        __FUNCTION__, mCameraIdStr.string());
                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                        "Request settings are empty");
            }
​
            String8 physicalId(it.id.c_str());
            if (physicalId != mDevice->getId()) {
                auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
                        it.id);
                if (found == requestedPhysicalIds.end()) {
                    ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
                            __FUNCTION__, mCameraIdStr.string(), physicalId.string());
                    return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                            "Invalid physical camera id");
                }
​
                if (!mSupportedPhysicalRequestKeys.empty()) {
                    // Filter out any unsupported physical request keys.
                    CameraMetadata filteredParams(mSupportedPhysicalRequestKeys.size());
                    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
                            filteredParams.getAndLock());
                    set_camera_metadata_vendor_id(meta, mDevice->getVendorTagId());
                    filteredParams.unlock(meta);
​
                    for (const auto& keyIt : mSupportedPhysicalRequestKeys) {
                        camera_metadata_ro_entry entry = it.settings.find(keyIt);
                        if (entry.count > 0) {
                            filteredParams.update(entry);
                        }
                    }
​
                    physicalSettingsList.push_back({it.id, filteredParams});
                }
            } else {
                physicalSettingsList.push_back({it.id, it.settings});
            }
        }
​
        if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
            // Callee logs
            return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
                    "Caller does not have permission to change restricted controls");
        }
​
        physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
                &outputStreamIds[0], outputStreamIds.size());
​
        if (request.mIsReprocess) {
            physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_INPUT_STREAMS,
                    &mInputStream.id, 1);
        }
​
        physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_ID,
                &(submitInfo->mRequestId), /*size*/1);
        loopCounter++; // loopCounter starts from 1
        ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
                __FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
                loopCounter, requests.size());
​
        // for循环是对函数入参requests的一些检查
        // 完成后填充到局部变量metadataRequestList、surfaceMapList中
        metadataRequestList.push_back(physicalSettingsList);
        surfaceMapList.push_back(surfaceMap);
    }
    mRequestIdCounter++;
​
    // streaming 其实就是参数 repeating
    if (streaming) {
        err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
                &(submitInfo->mLastFrameNumber));
        if (err != OK) {
            String8 msg = String8::format(
                "Camera %s:  Got error %s (%d) after trying to set streaming request",
                mCameraIdStr.string(), strerror(-err), err);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
                    msg.string());
        } else {
            Mutex::Autolock idLock(mStreamingRequestIdLock);
            mStreamingRequestId = submitInfo->mRequestId;
        }
    } else {
        err = mDevice->captureList(metadataRequestList, surfaceMapList,
                &(submitInfo->mLastFrameNumber));
        if (err != OK) {
            String8 msg = String8::format(
                "Camera %s: Got error %s (%d) after trying to submit capture request",
                mCameraIdStr.string(), strerror(-err), err);
            ALOGE("%s: %s", __FUNCTION__, msg.string());
            res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
                    msg.string());
        }
        ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
    }
​
    ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.string());
    return res;
}

进来还是先进行参数检查,mDevice成员变量是在构造参数时赋值好的,是在父类Camera2ClientBase对象的构造函数中new出来的;要提交request,那么参数requests肯定不能为空了。接下来的for循环是对函数入参requests的一些检查,完成后填充到局部变量metadataRequestList、surfaceMapList中,作为参数继续调用mDevice的方法进一步处理,进一步处理的分类判断条件非常明确,就是我们在Framework中传入的参数repeating,如果是预览,就调用mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList, &(submitInfo->mLastFrameNumber)),如果是拍照就调用mDevice->captureList(metadataRequestList, surfaceMapList, &(submitInfo->mLastFrameNumber));

接下来就是重点,我们在上层只调用了一次setRepeatingRequest,而且只有一个Request,但是预览帧数据却源源不断的输出上来,我们就从这里往下分析一下Request循环的原理;

3 setStreamingRequestList()

status_t Camera3Device::setStreamingRequestList(
        const List<const PhysicalCameraSettingsList> &requestsList,
        const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
    ATRACE_CALL();
​
    return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
}

很简单,都是直接调用submitRequestsHelper方法来进一步处理的,submitRequestsHelper方法的源码如下:

status_t Camera3Device::submitRequestsHelper(
        const List<const PhysicalCameraSettingsList> &requests,
        const std::list<const SurfaceMap> &surfaceMaps,
        bool repeating,
        /*out*/
        int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);
​
    status_t res = checkStatusOkToCaptureLocked();
    if (res != OK) {
        // error logged by previous call
        return res;
    }
​
    // 自定义的一个Request链表结构
    RequestList requestList;
​
    // 进行Metadata转换
    res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
            repeating, /*out*/&requestList);
    if (res != OK) {
        // error logged by previous call
        return res;
    }
​
    if (repeating) {
        res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
    } else {
        res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
    }
​
    if (res == OK) {
        // 等待直到mStatus为active为止
        waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
        if (res != OK) {
            SET_ERR_L("Can't transition to active in %f seconds!",
                    kActiveTimeout/1e9);
        }
        ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
              (*(requestList.begin()))->mResultExtras.requestId);
    } else {
        CLOGE("Cannot queue request. Impossible.");
        return BAD_VALUE;
    }
​
    return res;
}

3.1 RequestThread::queueRequestList()

我们首先看拍照时的queueRequestList方法:

status_t Camera3Device::RequestThread::queueRequestList(
        List<sp<CaptureRequest> > &requests,
        /*out*/
        int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock l(mRequestLock);
    // for循环中就是将入参requests放入到成员变量mRequestQueue当中
    // mRequestQueue是存储拍照Request的
    for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end();
            ++it) {
        mRequestQueue.push_back(*it);
    }
​
    // 第一次进入,lastFrameNumber为null
    if (lastFrameNumber != NULL) {
        // 给输出参数lastFrameNumber赋值,mFrameNumber就是当前的帧号,它是从0开始递增的一个整数
        *lastFrameNumber = mFrameNumber + mRequestQueue.size() - 1;
        ALOGV("%s: requestId %d, mFrameNumber %" PRId32 ", lastFrameNumber %" PRId64 ".",
              __FUNCTION__, (*(requests.begin()))->mResultExtras.requestId, mFrameNumber,
              *lastFrameNumber);
    }
​
    unpauseForNewRequests();
​
    return OK;
}

该方法中的逻辑非常清晰,for循环中就是将入参requests放入到成员变量mRequestQueue当中,所以这里大家一定要注意,mRequestQueue是存储拍照Request的,然后给输出参数lastFrameNumber赋值,mFrameNumber就是当前的帧号,它是从0开始递增的一个整数,它的递增也是在有效的预览循环开始后开始递增的;

3.2 RequestThread::setRepeatingRequests()

接着看setRepeatingRequests方法,源码如下:

status_t Camera3Device::RequestThread::setRepeatingRequests(
        const RequestList &requests,
        /*out*/
        int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock l(mRequestLock);
    if (lastFrameNumber != NULL) {
        *lastFrameNumber = mRepeatingLastFrameNumber;
    }
    mRepeatingRequests.clear();
    mRepeatingRequests.insert(mRepeatingRequests.begin(),
            requests.begin(), requests.end());
​
    unpauseForNewRequests();
​
    mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
    return OK;
}

这里是把mRepeatingLastFrameNumber赋值给输出参数lastFrameNumber,然后将mRepeatingRequests清空,再将入参requests放入到mRepeatingRequests当中,从这里和queueRequestList方法的实现对比,就可以看出来,mRepeatingRequests是用来存储预览Request的,这就是两个成员变量不同的作用了;

这里有些奇怪,为什么只是将requests插入到队列中就完了呢?我们来看一下RequestThread就明白了;

4 RequestThread

RequestThread就是我们本节最重点的对象了,它是一条线程,是在Camera3Device构造成功,调用initializeCommonLocked进行初始化时构造的,initializeCommonLocked方法的源码如下:

status_t Camera3Device::initializeCommonLocked() {
​
    /** Start up status tracker thread */
    mStatusTracker = new StatusTracker(this);
    status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
    if (res != OK) {
        SET_ERR_L("Unable to start status tracking thread: %s (%d)",
                strerror(-res), res);
        mInterface->close();
        mStatusTracker.clear();
        return res;
    }
​
    /** Register in-flight map to the status tracker */
    mInFlightStatusId = mStatusTracker->addComponent();
​
    if (mUseHalBufManager) {
        res = mRequestBufferSM.initialize(mStatusTracker);
        if (res != OK) {
            SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
                    strerror(-res), res);
            mInterface->close();
            mStatusTracker.clear();
            return res;
        }
    }
​
    /** Create buffer manager */
    mBufferManager = new Camera3BufferManager();
​
    Vector<int32_t> sessionParamKeys;
    camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
            ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
    if (sessionKeysEntry.count > 0) {
        sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
    }
​
    /** Start up request queue thread */
    mRequestThread = new RequestThread(
            this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
    // 传入的参数就是当前线程的名字
    // 可以使用ps -T 【pid】来查看当前进程的所有线程
    // 有一条以“ReqQueue”名字结尾的线程,也就是RequestThread,RequestThread是预览循环的主体
    res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
    if (res != OK) {
        SET_ERR_L("Unable to start request queue thread: %s (%d)",
                strerror(-res), res);
        mInterface->close();
        mRequestThread.clear();
        return res;
    }
​
    mPreparerThread = new PreparerThread();
​
    internalUpdateStatusLocked(STATUS_UNCONFIGURED);
    mNextStreamId = 0;
    mDummyStreamId = NO_STREAM;
    mNeedConfig = true;
    mPauseStateNotify = false;
​
    // Measure the clock domain offset between camera and video/hw_composer
    camera_metadata_entry timestampSource =
            mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
    if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
            ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
        mTimestampOffset = getMonoToBoottimeOffset();
    }
​
    // Will the HAL be sending in early partial result metadata?
    camera_metadata_entry partialResultsCount =
            mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
    if (partialResultsCount.count > 0) {
        mNumPartialResults = partialResultsCount.data.i32[0];
        mUsePartialResult = (mNumPartialResults > 1);
    }
​
    camera_metadata_entry configs =
            mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
    for (uint32_t i = 0; i < configs.count; i += 4) {
        if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
                configs.data.i32[i + 3] ==
                ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
            mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
                    configs.data.i32[i + 2]));
        }
    }
​
    bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
    if (usePrecorrectArray) {
        res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
        if (res != OK) {
            SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
            return res;
        }
    }
​
    mZoomRatioMappers[mId.c_str()] = ZoomRatioMapper(&mDeviceInfo,
            mSupportNativeZoomRatio, usePrecorrectArray);
​
    if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
        mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
    }
​
    return OK;
}

调用mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string())方法时,传入的参数就是当前线程的名字,所以我们也可以使用ps -T 【pid】来查看当前进程的所有线程,就可以看到有一条以“ReqQueue”名字结尾的线程,也就是RequestThread了,而且它是在Camera3Device初始化时就启动的了,它也是我们预览循环的主体。

RequestThread是继承Android的Thread类的,主函数就是threadLoop,我们来看一下RequestThread的threadLoop函数的实现,源码如下:

bool Camera3Device::RequestThread::threadLoop() {
    ATRACE_CALL();
    status_t res;
    // Any function called from threadLoop() must not hold mInterfaceLock since
    // it could lead to deadlocks (disconnect() -> hold mInterfaceMutex -> wait for request thread
    // to finish -> request thread waits on mInterfaceMutex) http://b/143513518
​
    // Handle paused state.
    // pause状态下直接返回
    if (waitIfPaused()) {
        return true;
    }
​
    // Wait for the next batch of requests.
    // 准备下一次的Request请求
    waitForNextRequestBatch();
    if (mNextRequests.size() == 0) {
        return true;
    }
​
    // Get the latest request ID, if any
    int latestRequestId;
    camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
            captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
    if (requestIdEntry.count > 0) {
        latestRequestId = requestIdEntry.data.i32[0];
    } else {
        ALOGW("%s: Did not have android.request.id set in the request.", __FUNCTION__);
        latestRequestId = NAME_NOT_FOUND;
    }
​
    // 'mNextRequests' will at this point contain either a set of HFR batched requests
    //  or a single request from streaming or burst. In either case the first element
    //  should contain the latest camera settings that we need to check for any session
    //  parameter updates.
    if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
        res = OK;
​
        //Input stream buffers are already acquired at this point so an input stream
        //will not be able to move to idle state unless we force it.
        if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
            res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
            if (res != OK) {
                ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
                cleanUpFailedRequests(/*sendRequestError*/ false);
                return false;
            }
        }
​
        if (res == OK) {
            sp<Camera3Device> parent = mParent.promote();
            if (parent != nullptr) {
                mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
            }
            setPaused(false);
​
            if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
                mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
                if (res != OK) {
                    ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
                    cleanUpFailedRequests(/*sendRequestError*/ false);
                    return false;
                }
            }
        }
    }
​
    // Prepare a batch of HAL requests and output buffers.
    // 为上一步准备好的Request请求的hal_request赋值,继续完善这个Request
    res = prepareHalRequests();
    if (res == TIMED_OUT) {
        // Not a fatal error if getting output buffers time out.
        cleanUpFailedRequests(/*sendRequestError*/ true);
        // Check if any stream is abandoned.
        checkAndStopRepeatingRequest();
        return true;
    } else if (res != OK) {
        cleanUpFailedRequests(/*sendRequestError*/ false);
        return false;
    }
​
    // Inform waitUntilRequestProcessed thread of a new request ID
    {
        Mutex::Autolock al(mLatestRequestMutex);
​
        mLatestRequestId = latestRequestId;
        mLatestRequestSignal.signal();
    }
​
    // Submit a batch of requests to HAL.
    // Use flush lock only when submitting multilple requests in a batch.
    // TODO: The problem with flush lock is flush() will be blocked by process_capture_request()
    // which may take a long time to finish so synchronizing flush() and
    // process_capture_request() defeats the purpose of cancelling requests ASAP with flush().
    // For now, only synchronize for high speed recording and we should figure something out for
    // removing the synchronization.
    bool useFlushLock = mNextRequests.size() > 1;
​
    if (useFlushLock) {
        mFlushLock.lock();
    }
​
    ALOGVV("%s: %d: submitting %zu requests in a batch.", __FUNCTION__, __LINE__,
            mNextRequests.size());
​
    sp<Camera3Device> parent = mParent.promote();
    if (parent != nullptr) {
        parent->mRequestBufferSM.onSubmittingRequest();
    }
​
    bool submitRequestSuccess = false;
    nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
    
    /* Android O 处理逻辑,和Android Q 处理逻辑有一定的区别,需要注意
        if (mInterface->supportBatchRequest()) {
            submitRequestSuccess = sendRequestsBatch();
        } else {
            submitRequestSuccess = sendRequestsOneByOne();
        }
    */
    submitRequestSuccess = sendRequestsBatch();
​
    nsecs_t tRequestEnd = systemTime(SYSTEM_TIME_MONOTONIC);
    mRequestLatency.add(tRequestStart, tRequestEnd);
​
    if (useFlushLock) {
        mFlushLock.unlock();
    }
​
    // Unset as current request
    {
        Mutex::Autolock l(mRequestLock);
        // 每一帧处理完成后,会将mNextRequests清空
        mNextRequests.clear();
    }
    mRequestSubmittedSignal.signal();
​
    return submitRequestSuccess;
}

waitIfPaused方法表示如果是pause状态的话,就什么不作,直接返回true,刚好该返回值就决定了线程是否要继续循环;所以如果是pause状态的话,就继续进行线程循环。

刚开始初始化完成,预览还未下发的时候,这里就会一直空处理,啥逻辑也没有,直接返回,那不是白白浪费CPU时间片吗?不急,我们耐心看一下waitIfPaused方法的实现就明白了,Google的精英们是绝不会犯这样低级的错误的,waitIfPaused方法的源码如下:

bool Camera3Device::RequestThread::waitIfPaused() {
    ATRACE_CALL();
    status_t res;
    Mutex::Autolock l(mPauseLock);
    // 好像初始化为true,需要确认一下
    while (mDoPause) {
        if (mPaused == false) {
            mPaused = true;
            ALOGV("%s: RequestThread: Paused", __FUNCTION__);
            if (mNotifyPipelineDrain) {
                mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
                mNotifyPipelineDrain = false;
                mStreamIdsToBeDrained.clear();
            }
            // Let the tracker know
            sp<StatusTracker> statusTracker = mStatusTracker.promote();
            if (statusTracker != 0) {
                statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
            }
            sp<Camera3Device> parent = mParent.promote();
            if (parent != nullptr) {
                parent->mRequestBufferSM.onRequestThreadPaused();
            }
        }
​
        res = mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout);
        if (res == TIMED_OUT || exitPending()) {
            return true;
        }
    }
    // We don't set mPaused to false here, because waitForNextRequest needs
    // to further manage the paused state in case of starvation.
    return false;
}

如果是上面所说的情况下,就会执行mDoPauseSignal.waitRelative(mPauseLock, kRequestTimeout)等待,kRequestTimeout是定义在Camera3Device.h头文件中,定义的源码如下:

static const nsecs_t kRequestTimeout = 50e6; // 50 ms

所以这里就可以看到,如果没有Request请求时,将会等待50ms,再进行下一次判断;

继续回到threadLoop方法中,我们先不细看,根据该方法中的实现理一下大体的思路,有几个比较关键的点:

  1. waitForNextRequestBatch准备下一次的Request请求;
  2. prepareHalRequests为上一步准备好的Request请求的hal_request赋值,继续完善这个Request;
  3. 根据mInterface->supportBatchRequest()是否支持批处理,分别调用sendRequestsBatch、sendRequestsOneByOne将准备好的Request发送到HAL进程,也就是CameraHalServer当中去处理了,最终返回submitRequestSuccess,如果该值为true,那么继续循环,如果为false,那么肯定是中间出问题,RequestThread线程就会退出了;

理清了这个思路,我们大体也就明白了,相机整个预览循环的工作就是在这里完成的,也全部是围绕着mNextRequests成员变量来进行的。下面我们就来仔细看一下waitForNextRequestBatch、prepareHalRequests、sendRequestsBatch(我们假定支持批处理)三个函数的实现;

4.1 waitForNextRequestBatch()

void Camera3Device::RequestThread::waitForNextRequestBatch() {
    ATRACE_CALL();
    // Optimized a bit for the simple steady-state case (single repeating
    // request), to avoid putting that request in the queue temporarily.
    Mutex::Autolock l(mRequestLock);
​
    // 断言mNextRequests中的元素为空
    assert(mNextRequests.empty());
​
    NextRequest nextRequest;
    // nextRequest变量为需要添加到mNextRequests中的目标
    nextRequest.captureRequest = waitForNextRequestLocked();
    if (nextRequest.captureRequest == nullptr) {
        return;
    }
​
    // halRequest成员变量是通过camera3_capture_request_t结构体构造的,但是它当中的所有参数都没有赋值,所以在这里它还只是个空壳子
    nextRequest.halRequest = camera3_capture_request_t();
    // submitted表示是否提交处理了,在这里肯定是false
    // 该Request提交给HAL进程进行处理,处理了之后,它才会为true
    nextRequest.submitted = false;
    
    mNextRequests.add(nextRequest);
​
    // Wait for additional requests
    // batchSize一般都为1,通过分析日志得到的,目前暂时没有搞清楚,需要确认
    const size_t batchSize = nextRequest.captureRequest->mBatchSize;
​
    // for循环的判断条件是for (size_t i = 1; i < batchSize; i++),i 的初始值为1,而batchSize也等于1,所以for循环是不会进入的
    for (size_t i = 1; i < batchSize; i++) {
        NextRequest additionalRequest;
        additionalRequest.captureRequest = waitForNextRequestLocked();
        if (additionalRequest.captureRequest == nullptr) {
            break;
        }
​
        additionalRequest.halRequest = camera3_capture_request_t();
        additionalRequest.submitted = false;
        mNextRequests.add(additionalRequest);
    }
​
    // 到目前为止,mNextRequests只添加了一个nextRequest,它的size就是1
    if (mNextRequests.size() < batchSize) {
        ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
                mNextRequests.size(), batchSize);
        cleanUpFailedRequests(/*sendRequestError*/true);
    }
​
    return;
}

首先断言成员变量mNextRequests中的元素为空,从这个逻辑我们也可以想到,每一帧处理完成后,肯定会把它清空,它的作用非常明确,就是将下一帧需要处理的Request添加进来,每一帧处理完成后直接清空,下一帧再继续添加。然后定义一个局部变量nextRequest,它就是要添加到mNextRequests当中的目标,调用waitForNextRequestLocked方法来给它的captureRequest成员变量赋值,halRequest成员变量是通过camera3_capture_request_t结构体构造的,但是它当中的所有参数都没有赋值,所以在这里它还只是个空壳子。submitted表示是否提交处理了,在这里肯定是false了,那么它什么时候为true呢?很明确,分界线就是我们最后将该Request提交给HAL进程进行处理,处理了之后,它才会为true。batchSize一般都为1,这是我加日志明确看过的,但是它所表示的具体的意思,暂时还没搞清楚。另外,这里请大家一定要看清楚,for循环的判断条件是for (size_t i = 1; i < batchSize; i++),i 的初始值为1,而batchSize也等于1,所以for循环是不会进入的,也就是说经过这里的处理,mNextRequests只添加了一个nextRequest,它的size就是1;

// Used to prepare a batch of requests.
struct NextRequest {
    sp<CaptureRequest>              captureRequest;
    camera3_capture_request_t       halRequest;
    Vector<camera3_stream_buffer_t> outputBuffers;
    bool                            submitted;
};

NextRequest结构体,在Camera3Device.h中定义;

我们继续来看它所调用的waitForNextRequestLocked方法,源码如下:

sp<Camera3Device::CaptureRequest>
        Camera3Device::RequestThread::waitForNextRequestLocked() {
    status_t res;
    sp<CaptureRequest> nextRequest;
​
    // 拍照请求的优先级高于预览请求
    while (mRequestQueue.empty()) {
        // mRepeatingRequests不为空
        if (!mRepeatingRequests.empty()) {
            // Always atomically enqueue all requests in a repeating request
            // list. Guarantees a complete in-sequence set of captures to
            // application.
            // 从预览队列中取头节点赋值给局部变量nextRequest
            // mRepeatingRequests不做擦除处理,区别于mRequestQueue.erase(firstRequest)
            // 这个就是thread轮训的最重要的点
            const RequestList &requests = mRepeatingRequests;
            RequestList::const_iterator firstRequest =
                    requests.begin();
            nextRequest = *firstRequest;
            mRequestQueue.insert(mRequestQueue.end(),
                    ++firstRequest,
                    requests.end());
            // No need to wait any longer
​
            // 给mRepeatingLastFrameNumber预览帧变量赋值
            mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
​
            break;
        }
​
        res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
​
        if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
                exitPending()) {
            Mutex::Autolock pl(mPauseLock);
            if (mPaused == false) {
                ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
                mPaused = true;
                if (mNotifyPipelineDrain) {
                    mInterface->signalPipelineDrain(mStreamIdsToBeDrained);
                    mNotifyPipelineDrain = false;
                    mStreamIdsToBeDrained.clear();
                }
                // Let the tracker know
                sp<StatusTracker> statusTracker = mStatusTracker.promote();
                if (statusTracker != 0) {
                    statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
                }
                sp<Camera3Device> parent = mParent.promote();
                if (parent != nullptr) {
                    parent->mRequestBufferSM.onRequestThreadPaused();
                }
            }
            // Stop waiting for now and let thread management happen
            return NULL;
        }
    }
​
    // mRequestQueue不为空,跳过while,直接从mRequestQueue获取request
    if (nextRequest == NULL) {
        // Don't have a repeating request already in hand, so queue
        // must have an entry now.
        RequestList::iterator firstRequest =
                mRequestQueue.begin();
        nextRequest = *firstRequest;
        mRequestQueue.erase(firstRequest);
        if (mRequestQueue.empty() && !nextRequest->mRepeating) {
            sp<NotificationListener> listener = mListener.promote();
            if (listener != NULL) {
                listener->notifyRequestQueueEmpty();
            }
        }
    }
​
    // In case we've been unpaused by setPaused clearing mDoPause, need to
    // update internal pause state (capture/setRepeatingRequest unpause
    // directly).
    Mutex::Autolock pl(mPauseLock);
    if (mPaused) {
        ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
        sp<StatusTracker> statusTracker = mStatusTracker.promote();
        if (statusTracker != 0) {
            statusTracker->markComponentActive(mStatusId);
        }
    }
    mPaused = false;
​
    // Check if we've reconfigured since last time, and reset the preview
    // request if so. Can't use 'NULL request == repeat' across configure calls.
    if (mReconfigured) {
        mPrevRequest.clear();
        mReconfigured = false;
    }
​
    // 这一块的逻辑,有可能是从mRequestQueue获取的request,也有可能是从mRepeatingRequests获取的
    if (nextRequest != NULL) {
        nextRequest->mResultExtras.frameNumber = mFrameNumber++;
        nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
        nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
​
        // Since RequestThread::clear() removes buffers from the input stream,
        // get the right buffer here before unlocking mRequestLock
        if (nextRequest->mInputStream != NULL) {
            res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
            if (res != OK) {
                // Can't get input buffer from gralloc queue - this could be due to
                // disconnected queue or other producer misbehavior, so not a fatal
                // error
                ALOGE("%s: Can't get input buffer, skipping request:"
                        " %s (%d)", __FUNCTION__, strerror(-res), res);
​
                sp<NotificationListener> listener = mListener.promote();
                if (listener != NULL) {
                    listener->notifyError(
                            hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
                            nextRequest->mResultExtras);
                }
                return NULL;
            }
        }
    }
​
    return nextRequest;
}

方法一开始的while循环可以很直接的看到,先从mRequestQueue队列取数据,那么意思很明白,拍照请求的优先级肯定是高于预览请求的,比如当前RequestThread的拍照队列和预览队列都有一个Request,此时threadloop循环要取一帧进行处理,在这里的while进行判断时,拍照队列不为空,则while循环直接跳过,if (nextRequest == NULL)判断为true,就直接从拍照队列中取数据了。好,我们结合当前预览的场景来分析一下,当前拍照队列为请求为空,而if (!mRepeatingRequests.empty())判断成立,因为我们在前面是通过setRepeatingRequest调用下来的,在那里已经把当时封装好的Request插入到预览队列中了。然后从预览队列中取头节点赋值给局部变量nextRequest,接着为什么将其插入到拍照队列中?这步逻辑看来看去都没搞清楚是什么意思。最后给mRepeatingLastFrameNumber预览帧变量赋值,此时局部变量nextRequest不为空,该方法结尾处if (nextRequest != NULL)判断为true,if判断中第一句就是给帧号赋值,可以看到mFrameNumber++,先赋值后自增,这就是前面我们所说的帧号递增的出处了,这个帧号大家一定要非常重视,从CameraServer到CameraHalServer,一个帧号对应一个结果,也就是说我发一个请求给你,你就必须回复一个结果给我,我才能根据这个结果进行相应的预览或者拍照后处理,所以这个变量非常重要,它是对标两个进程之间请求的一个核心变量。剩下的还有一些其他参数的赋值,填充完成后将nextRequest返回;

那么它准备好了NextRequest,再往上回到waitForNextRequestBatch方法当中,下一帧的请求Request也就添加到成员变量mNextRequests当中了。继续往上,回到threadLoop方法当中,当时size等于1,接下来执行prepareHalRequests方法,上一行的注释写的也非常清楚了,“Prepare a batch of HAL requests and output buffers”,准备下一批的HAL请求和输出的Buffer;

4.2 prepareHalRequests()

status_t Camera3Device::RequestThread::prepareHalRequests() {
    ATRACE_CALL();
​
    bool batchedRequest = mNextRequests[0].captureRequest->mBatchSize > 1;
    for (size_t i = 0; i < mNextRequests.size(); i++) {
        
        auto& nextRequest = mNextRequests.editItemAt(i);
        // 获取NextRequest结构体中的所有属性
        sp<CaptureRequest> captureRequest = nextRequest.captureRequest;
        camera3_capture_request_t* halRequest = &nextRequest.halRequest;
        // outputBuffers是一个保存stream buffer的容器
        Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
​
        // Prepare a request to HAL
        // halRequest的构建 -- start
        halRequest->frame_number = captureRequest->mResultExtras.frameNumber;
​
        // Insert any queued triggers (before metadata is locked)
        status_t res = insertTriggers(captureRequest);
        if (res < 0) {
            SET_ERR("RequestThread: Unable to insert triggers "
                    "(capture request %d, HAL device: %s (%d)",
                    halRequest->frame_number, strerror(-res), res);
            return INVALID_OPERATION;
        }
​
        int triggerCount = res;
        bool triggersMixedIn = (triggerCount > 0 || mPrevTriggers > 0);
        mPrevTriggers = triggerCount;
​
        bool rotateAndCropChanged = overrideAutoRotateAndCrop(captureRequest);
​
        // If the request is the same as last, or we had triggers last time
        bool newRequest =
                (mPrevRequest != captureRequest || triggersMixedIn || rotateAndCropChanged) &&
                // Request settings are all the same within one batch, so only treat the first
                // request in a batch as new
                !(batchedRequest && i > 0);
        if (newRequest) {
            std::set<std::string> cameraIdsWithZoom;
            /**
             * HAL workaround:
             * Insert a dummy trigger ID if a trigger is set but no trigger ID is
             */
            res = addDummyTriggerIds(captureRequest);
            if (res != OK) {
                SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
                        "(capture request %d, HAL device: %s (%d)",
                        halRequest->frame_number, strerror(-res), res);
                return INVALID_OPERATION;
            }
​
            {
                // Correct metadata regions for distortion correction if enabled
                sp<Camera3Device> parent = mParent.promote();
                if (parent != nullptr) {
                    List<PhysicalCameraSettings>::iterator it;
                    for (it = captureRequest->mSettingsList.begin();
                            it != captureRequest->mSettingsList.end(); it++) {
                        if (parent->mDistortionMappers.find(it->cameraId) ==
                                parent->mDistortionMappers.end()) {
                            continue;
                        }
                        res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
                            &(it->metadata));
                        if (res != OK) {
                            SET_ERR("RequestThread: Unable to correct capture requests "
                                    "for lens distortion for request %d: %s (%d)",
                                    halRequest->frame_number, strerror(-res), res);
                            return INVALID_OPERATION;
                        }
                    }
​
                    for (it = captureRequest->mSettingsList.begin();
                            it != captureRequest->mSettingsList.end(); it++) {
                        if (parent->mZoomRatioMappers.find(it->cameraId) ==
                                parent->mZoomRatioMappers.end()) {
                            continue;
                        }
​
                        camera_metadata_entry_t e = it->metadata.find(ANDROID_CONTROL_ZOOM_RATIO);
                        if (e.count > 0 && e.data.f[0] != 1.0f) {
                            cameraIdsWithZoom.insert(it->cameraId);
                        }
​
                        res = parent->mZoomRatioMappers[it->cameraId].updateCaptureRequest(
                            &(it->metadata));
                        if (res != OK) {
                            SET_ERR("RequestThread: Unable to correct capture requests "
                                    "for zoom ratio for request %d: %s (%d)",
                                    halRequest->frame_number, strerror(-res), res);
                            return INVALID_OPERATION;
                        }
                    }
                    if (captureRequest->mRotateAndCropAuto) {
                        for (it = captureRequest->mSettingsList.begin();
                                it != captureRequest->mSettingsList.end(); it++) {
                            auto mapper = parent->mRotateAndCropMappers.find(it->cameraId);
                            if (mapper != parent->mRotateAndCropMappers.end()) {
                                res = mapper->second.updateCaptureRequest(&(it->metadata));
                                if (res != OK) {
                                    SET_ERR("RequestThread: Unable to correct capture requests "
                                            "for rotate-and-crop for request %d: %s (%d)",
                                            halRequest->frame_number, strerror(-res), res);
                                    return INVALID_OPERATION;
                                }
                            }
                        }
                    }
                }
            }
​
            /**
             * The request should be presorted so accesses in HAL
             *   are O(logn). Sidenote, sorting a sorted metadata is nop.
             */
            captureRequest->mSettingsList.begin()->metadata.sort();
            halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
            mPrevRequest = captureRequest;
            mPrevCameraIdsWithZoom = cameraIdsWithZoom;
            ALOGVV("%s: Request settings are NEW", __FUNCTION__);
​
            IF_ALOGV() {
                camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
                find_camera_metadata_ro_entry(
                        halRequest->settings,
                        ANDROID_CONTROL_AF_TRIGGER,
                        &e
                );
                if (e.count > 0) {
                    ALOGV("%s: Request (frame num %d) had AF trigger 0x%x",
                          __FUNCTION__,
                          halRequest->frame_number,
                          e.data.u8[0]);
                }
            }
        } else {
            // leave request.settings NULL to indicate 'reuse latest given'
            ALOGVV("%s: Request settings are REUSED",
                   __FUNCTION__);
        }
​
        if (captureRequest->mSettingsList.size() > 1) {
            halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
            halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
            if (newRequest) {
                halRequest->physcam_settings =
                    new const camera_metadata* [halRequest->num_physcam_settings];
            } else {
                halRequest->physcam_settings = nullptr;
            }
            auto it = ++captureRequest->mSettingsList.begin();
            size_t i = 0;
            for (; it != captureRequest->mSettingsList.end(); it++, i++) {
                halRequest->physcam_id[i] = it->cameraId.c_str();
                if (newRequest) {
                    it->metadata.sort();
                    halRequest->physcam_settings[i] = it->metadata.getAndLock();
                }
            }
        }
​
        uint32_t totalNumBuffers = 0;
​
        // Fill in buffers
        if (captureRequest->mInputStream != NULL) {
            halRequest->input_buffer = &captureRequest->mInputBuffer;
            totalNumBuffers += 1;
        } else {
            halRequest->input_buffer = NULL;
        }
​
        // 构造一个camera3_stream_buffer的对象,并将其放入outputBuffers的容器中
        // 插在序号0的后面,插入个数为captureRequest->mOutputStreams.size(),一般为1个
        outputBuffers->insertAt(camera3_stream_buffer_t(), 0,
                captureRequest->mOutputStreams.size());
        // halRequest->output_buffers 指向的是上一步插入buffer的地址,应该是camera3_stream_buffer对象的地址
        halRequest->output_buffers = outputBuffers->array();
        std::set<String8> requestedPhysicalCameras;
​
        sp<Camera3Device> parent = mParent.promote();
        if (parent == NULL) {
            // Should not happen, and nowhere to send errors to, so just log it
            CLOGE("RequestThread: Parent is gone");
            return INVALID_OPERATION;
        }
        nsecs_t waitDuration = kBaseGetBufferWait + parent->getExpectedInFlightDuration();
​
        SurfaceMap uniqueSurfaceIdMap;
        for (size_t j = 0; j < captureRequest->mOutputStreams.size(); j++) {
            sp<Camera3OutputStreamInterface> outputStream =
                    captureRequest->mOutputStreams.editItemAt(j);
            int streamId = outputStream->getId();
​
            // Prepare video buffers for high speed recording on the first video request.
            if (mPrepareVideoStream && outputStream->isVideoStream()) {
                // Only try to prepare video stream on the first video request.
                mPrepareVideoStream = false;
​
                res = outputStream->startPrepare(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX,
                        false /*blockRequest*/);
                while (res == NOT_ENOUGH_DATA) {
                    res = outputStream->prepareNextBuffer();
                }
                if (res != OK) {
                    ALOGW("%s: Preparing video buffers for high speed failed: %s (%d)",
                        __FUNCTION__, strerror(-res), res);
                    outputStream->cancelPrepare();
                }
            }
​
            std::vector<size_t> uniqueSurfaceIds;
            res = outputStream->getUniqueSurfaceIds(
                    captureRequest->mOutputSurfaces[streamId],
                    &uniqueSurfaceIds);
            // INVALID_OPERATION is normal output for streams not supporting surfaceIds
            if (res != OK && res != INVALID_OPERATION) {
                ALOGE("%s: failed to query stream %d unique surface IDs",
                        __FUNCTION__, streamId);
                return res;
            }
            if (res == OK) {
                uniqueSurfaceIdMap.insert({streamId, std::move(uniqueSurfaceIds)});
            }
​
            if (mUseHalBufManager) {
                if (outputStream->isAbandoned()) {
                    ALOGV("%s: stream %d is abandoned, skipping request", __FUNCTION__, streamId);
                    return TIMED_OUT;
                }
                // HAL will request buffer through requestStreamBuffer API
                camera3_stream_buffer_t& buffer = outputBuffers->editItemAt(j);
                buffer.stream = outputStream->asHalStream();
                buffer.buffer = nullptr;
                buffer.status = CAMERA3_BUFFER_STATUS_OK;
                buffer.acquire_fence = -1;
                buffer.release_fence = -1;
            } else {
                // outputStream的类型为Camera3OutputStream
                res = outputStream->getBuffer(&outputBuffers->editItemAt(j),
                        waitDuration,
                        captureRequest->mOutputSurfaces[streamId]);
                if (res != OK) {
                    // Can't get output buffer from gralloc queue - this could be due to
                    // abandoned queue or other consumer misbehavior, so not a fatal
                    // error
                    ALOGV("RequestThread: Can't get output buffer, skipping request:"
                            " %s (%d)", strerror(-res), res);
​
                    return TIMED_OUT;
                }
            }
​
            {
                sp<Camera3Device> parent = mParent.promote();
                if (parent != nullptr) {
                    const String8& streamCameraId = outputStream->getPhysicalCameraId();
                    for (const auto& settings : captureRequest->mSettingsList) {
                        if ((streamCameraId.isEmpty() &&
                                parent->getId() == settings.cameraId.c_str()) ||
                                streamCameraId == settings.cameraId.c_str()) {
                            outputStream->fireBufferRequestForFrameNumber(
                                    captureRequest->mResultExtras.frameNumber,
                                    settings.metadata);
                        }
                    }
                }
            }
​
            String8 physicalCameraId = outputStream->getPhysicalCameraId();
​
            if (!physicalCameraId.isEmpty()) {
                // Physical stream isn't supported for input request.
                if (halRequest->input_buffer) {
                    CLOGE("Physical stream is not supported for input request");
                    return INVALID_OPERATION;
                }
                requestedPhysicalCameras.insert(physicalCameraId);
            }
            halRequest->num_output_buffers++;
        }
        totalNumBuffers += halRequest->num_output_buffers;
​
        // Log request in the in-flight queue
        // If this request list is for constrained high speed recording (not
        // preview), and the current request is not the last one in the batch,
        // do not send callback to the app.
        bool hasCallback = true;
        if (batchedRequest && i != mNextRequests.size()-1) {
            hasCallback = false;
        }
        bool isStillCapture = false;
        bool isZslCapture = false;
        if (!mNextRequests[0].captureRequest->mSettingsList.begin()->metadata.isEmpty()) {
            camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
            find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_CAPTURE_INTENT, &e);
            if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE)) {
                isStillCapture = true;
                ATRACE_ASYNC_BEGIN("still capture", mNextRequests[i].halRequest.frame_number);
            }
​
            find_camera_metadata_ro_entry(halRequest->settings, ANDROID_CONTROL_ENABLE_ZSL, &e);
            if ((e.count > 0) && (e.data.u8[0] == ANDROID_CONTROL_ENABLE_ZSL_TRUE)) {
                isZslCapture = true;
            }
        }
        res = parent->registerInFlight(halRequest->frame_number,
                totalNumBuffers, captureRequest->mResultExtras,
                /*hasInput*/halRequest->input_buffer != NULL,
                hasCallback,
                calculateMaxExpectedDuration(halRequest->settings),
                requestedPhysicalCameras, isStillCapture, isZslCapture,
                captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
                (mUseHalBufManager) ? uniqueSurfaceIdMap :
                                      SurfaceMap{});
        ALOGVV("%s: registered in flight requestId = %" PRId32 ", frameNumber = %" PRId64
               ", burstId = %" PRId32 ".",
                __FUNCTION__,
                captureRequest->mResultExtras.requestId, captureRequest->mResultExtras.frameNumber,
                captureRequest->mResultExtras.burstId);
        if (res != OK) {
            SET_ERR("RequestThread: Unable to register new in-flight request:"
                    " %s (%d)", strerror(-res), res);
            return INVALID_OPERATION;
        }
    }
​
    return OK;
}

分析该方法前,我们一定要清楚,该方法中完成了一个非常重要的目的,就是output buffer的准备,HAL所有的工作都是围绕输出的Buffer来操作的,所以看完这个方法,我们必须搞清楚,output buffer是如何准备的,准备到哪里去了。整个方法就一个for循环,对入参的每个Request进行处理,接下来的逻辑都是在给成员变量halRequest的子变量进行赋值,一步一步的完成halRequest的构建,输出Buffer就是成员变量outputBuffers了,它的准备就是调用outputStream->getBuffer(&outputBuffers->editItemAt(j), captureRequest->mOutputSurfaces[j])实现的。这里我们假定outputStream的类型为Camera3OutputStream(还有其他类型的Stream,比如Camera3SharedOutputStream);

4.3 sendRequestsBatch()

将准备好的Request发往HAL进程去处理,该方法的源码如下:

bool Camera3Device::RequestThread::sendRequestsBatch() {
    ATRACE_CALL();
    status_t res;
    size_t batchSize = mNextRequests.size();
    std::vector<camera3_capture_request_t*> requests(batchSize);
    uint32_t numRequestProcessed = 0;
    for (size_t i = 0; i < batchSize; i++) {
        requests[i] = &mNextRequests.editItemAt(i).halRequest;
        ATRACE_ASYNC_BEGIN("frame capture", mNextRequests[i].halRequest.frame_number);
    }
​
    // 将准备好的Request发往HAL进程去处理
    res = mInterface->processBatchCaptureRequests(requests, &numRequestProcessed);
​
    bool triggerRemoveFailed = false;
    NextRequest& triggerFailedRequest = mNextRequests.editItemAt(0);
    for (size_t i = 0; i < numRequestProcessed; i++) {
        NextRequest& nextRequest = mNextRequests.editItemAt(i);
        // 请求处理完成之后,submitted被赋值为true
        nextRequest.submitted = true;
​
        updateNextRequest(nextRequest);
​
        if (!triggerRemoveFailed) {
            // Remove any previously queued triggers (after unlock)
            status_t removeTriggerRes = removeTriggers(mPrevRequest);
            if (removeTriggerRes != OK) {
                triggerRemoveFailed = true;
                triggerFailedRequest = nextRequest;
            }
        }
    }
​
    if (triggerRemoveFailed) {
        SET_ERR("RequestThread: Unable to remove triggers "
              "(capture request %d, HAL device: %s (%d)",
              triggerFailedRequest.halRequest.frame_number, strerror(-res), res);
        cleanUpFailedRequests(/*sendRequestError*/ false);
        return false;
    }
​
    if (res != OK) {
        // Should only get a failure here for malformed requests or device-level
        // errors, so consider all errors fatal.  Bad metadata failures should
        // come through notify.
        SET_ERR("RequestThread: Unable to submit capture request %d to HAL device: %s (%d)",
                mNextRequests[numRequestProcessed].halRequest.frame_number,
                strerror(-res), res);
        cleanUpFailedRequests(/*sendRequestError*/ false);
        return false;
    }
    return true;
}

所有的request都已经准备好了,所以就调用mInterface->processBatchCaptureRequests(requests, &numRequestProcessed)来处理请求了,mInterface的类型为HalInterface,这里也就是分水领了,从这句代码往后,当前的Request就被处理了,所以nextRequest.submitted也就应该被赋值为true了。我们继续来看一下processBatchCaptureRequests的逻辑,源码如下:

status_t Camera3Device::HalInterface::processBatchCaptureRequests(
        std::vector<camera3_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
    ATRACE_NAME("CameraHal::processBatchCaptureRequests");
    if (!valid()) return INVALID_OPERATION;
​
    sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
    auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
    if (castResult_3_4.isOk()) {
        hidlSession_3_4 = castResult_3_4;
    }
​
    hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
    hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
    size_t batchSize = requests.size();
    if (hidlSession_3_4 != nullptr) {
        captureRequests_3_4.resize(batchSize);
    } else {
        captureRequests.resize(batchSize);
    }
    std::vector<native_handle_t*> handlesCreated;
    std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
​
    status_t res = OK;
    for (size_t i = 0; i < batchSize; i++) {
        if (hidlSession_3_4 != nullptr) {
            res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
                    /*out*/&handlesCreated, /*out*/&inflightBuffers);
        } else {
            // Android O的逻辑,没有if-else判断
            //for (size_t i = 0; i < batchSize; i++) {
            //    wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
            //}
            res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
                    /*out*/&handlesCreated, /*out*/&inflightBuffers);
        }
        if (res != OK) {
            mBufferRecords.popInflightBuffers(inflightBuffers);
            cleanupNativeHandles(&handlesCreated);
            return res;
        }
    }
​
    std::vector<device::V3_2::BufferCache> cachesToRemove;
    {
        std::lock_guard<std::mutex> lock(mFreedBuffersLock);
        for (auto& pair : mFreedBuffers) {
            // The stream might have been removed since onBufferFreed
            if (mBufferRecords.isStreamCached(pair.first)) {
                cachesToRemove.push_back({pair.first, pair.second});
            }
        }
        mFreedBuffers.clear();
    }
​
    common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
    *numRequestProcessed = 0;
​
    // Write metadata to FMQ.
    for (size_t i = 0; i < batchSize; i++) {
        camera3_capture_request_t* request = requests[i];
        device::V3_2::CaptureRequest* captureRequest;
        if (hidlSession_3_4 != nullptr) {
            captureRequest = &captureRequests_3_4[i].v3_2;
        } else {
            captureRequest = &captureRequests[i];
        }
​
        if (request->settings != nullptr) {
            size_t settingsSize = get_camera_metadata_size(request->settings);
            if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
                    reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
                captureRequest->settings.resize(0);
                captureRequest->fmqSettingsSize = settingsSize;
            } else {
                if (mRequestMetadataQueue != nullptr) {
                    ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
                }
                captureRequest->settings.setToExternal(
                        reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
                        get_camera_metadata_size(request->settings));
                captureRequest->fmqSettingsSize = 0u;
            }
        } else {
            // A null request settings maps to a size-0 CameraMetadata
            captureRequest->settings.resize(0);
            captureRequest->fmqSettingsSize = 0u;
        }
​
        if (hidlSession_3_4 != nullptr) {
            captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
            for (size_t j = 0; j < request->num_physcam_settings; j++) {
                if (request->physcam_settings != nullptr) {
                    size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
                    if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
                                reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
                                settingsSize)) {
                        captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
                        captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
                            settingsSize;
                    } else {
                        if (mRequestMetadataQueue != nullptr) {
                            ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
                        }
                        captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
                                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
                                        request->physcam_settings[j])),
                                get_camera_metadata_size(request->physcam_settings[j]));
                        captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
                    }
                } else {
                    captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
                    captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
                }
                captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
                    request->physcam_id[j];
            }
        }
    }
​
    hardware::details::return_status err;
    auto resultCallback =
        [&status, &numRequestProcessed] (auto s, uint32_t n) {
                status = s;
                *numRequestProcessed = n;
        };
    if (hidlSession_3_4 != nullptr) {
        err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
                                                         resultCallback);
    } else {
        err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
                                                  resultCallback);
    }
    if (!err.isOk()) {
        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
        status = common::V1_0::Status::CAMERA_DISCONNECTED;
    }
​
    if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
        ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
                __FUNCTION__, *numRequestProcessed, batchSize);
        status = common::V1_0::Status::INTERNAL_ERROR;
    }
​
    res = CameraProviderManager::mapToStatusT(status);
    if (res == OK) {
        if (mHidlSession->isRemote()) {
            // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
            // sent to camera HAL processes)
            cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
        } else {
            // In passthrough mode the FDs are now owned by HAL
            cleanupNativeHandles(&handlesCreated);
        }
    } else {
        mBufferRecords.popInflightBuffers(inflightBuffers);
        cleanupNativeHandles(&handlesCreated);
    }
    return res;
}

这里先调用wrapAsHidlRequest对每个Request进一步包装,我们来看一下它的实现,源码如下:

status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera3_capture_request_t* request,
        /*out*/device::V3_2::CaptureRequest* captureRequest,
        /*out*/std::vector<native_handle_t*>* handlesCreated,
        /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
    ATRACE_CALL();
    if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
        ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
                "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
        return BAD_VALUE;
    }
​
    // 帧号的赋值
    captureRequest->frameNumber = request->frame_number;
​
    captureRequest->fmqSettingsSize = 0;
​
    {
        if (request->input_buffer != nullptr) {
            int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
            buffer_handle_t buf = *(request->input_buffer->buffer);
            auto pair = getBufferId(buf, streamId);
            bool isNewBuffer = pair.first;
            uint64_t bufferId = pair.second;
            captureRequest->inputBuffer.streamId = streamId;
            captureRequest->inputBuffer.bufferId = bufferId;
            captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
            captureRequest->inputBuffer.status = BufferStatus::OK;
            native_handle_t *acquireFence = nullptr;
            if (request->input_buffer->acquire_fence != -1) {
                acquireFence = native_handle_create(1,0);
                acquireFence->data[0] = request->input_buffer->acquire_fence;
                handlesCreated->push_back(acquireFence);
            }
            captureRequest->inputBuffer.acquireFence = acquireFence;
            captureRequest->inputBuffer.releaseFence = nullptr;
​
            mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
                    request->input_buffer->buffer);
            inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
        } else {
            captureRequest->inputBuffer.streamId = -1;
            captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
        }
​
        captureRequest->outputBuffers.resize(request->num_output_buffers);
        for (size_t i = 0; i < request->num_output_buffers; i++) {
            // 将上面已经分析过的Surface中取出的buffer拿出来
            const camera3_stream_buffer_t *src = request->output_buffers + i;
            StreamBuffer &dst = captureRequest->outputBuffers[i];
            int32_t streamId = Camera3Stream::cast(src->stream)->getId();
            if (src->buffer != nullptr) {
                buffer_handle_t buf = *(src->buffer);
                auto pair = getBufferId(buf, streamId);
                bool isNewBuffer = pair.first;
                dst.bufferId = pair.second;
                // 将src->buffer赋值给dst,即将Surface中的buffer赋值给dst
                dst.buffer = isNewBuffer ? buf : nullptr;
                native_handle_t *acquireFence = nullptr;
                if (src->acquire_fence != -1) {
                    acquireFence = native_handle_create(1,0);
                    acquireFence->data[0] = src->acquire_fence;
                    handlesCreated->push_back(acquireFence);
                }
                dst.acquireFence = acquireFence;
            } else if (mUseHalBufManager) {
                // HAL buffer management path
                dst.bufferId = BUFFER_ID_NO_BUFFER;
                dst.buffer = nullptr;
                dst.acquireFence = nullptr;
            } else {
                ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
                return BAD_VALUE;
            }
            dst.streamId = streamId;
            dst.status = BufferStatus::OK;
            dst.releaseFence = nullptr;
​
            // Output buffers are empty when using HAL buffer manager
            if (!mUseHalBufManager) {
                // 调用pushInflightBufferLocked以帧号(captureRequest->frameNumber)、streamId、src->buffer、src->acquire_fence为参数将buffer保存在成员变量mInflightBufferMap中
                mBufferRecords.pushInflightBuffer(
                        captureRequest->frameNumber, streamId, src->buffer);
                inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
            }
        }
    }
    return OK;
}

可以看到,captureRequest->frameNumber = request->frame_number帧号的赋值,第一位,说明非常重要!!下面就是对buffer处理了,在output buffer中,通过const camera3_stream_buffer_t *src = request->output_buffers + i 将上面我们已经分析过的Surface中取出的buffer拿出来,然后调用 dst.buffer = isNewBuffer ? buf : nullptr 将它操作赋值给dst,我在这里打日志观察过,申请的几个buffer一直是复用的,isNewBuffer肯定是true,要不然输出buffer就为空了,而复用的就是分配了几个buffer,然后这几个buffer一直不断的轮转,比如1、2、3、4、5、6,然后又1、2、3、4、5、6一直往复循环的,大家也可以自己加日志研究一下这块的逻辑,最后调用pushInflightBufferLocked以帧号(captureRequest->frameNumber)、streamId、src->buffer、src->acquire_fence为参数将buffer保存在成员变量mInflightBufferMap中,后续HAL层对buffer填充完毕后,这里就可以直接从mInflightBufferMap当中取出来了;

wrapAsHidlRequest()方法执行完成之后,紧接着调用mHidlSession->processCaptureRequest()把Request发到HAL进程当中,这是通过HIDL来实现的,其实最根本的还是Binder框架。

processBatchCaptureRequests()方法就执行完了,即sendRequestsBatch()执行完毕;

5 mNextRequests.clear()

一帧请求处理完成,最后调用mNextRequests.clear()清空数据,成功返回true,继续下一次循环;