基于Android Camera2 close流程分析

基于Android P分析

close时序图:

1 Application.closeCamera()

该段逻辑来源于google提供的Camera demo中,应用层在调用closeCamera()方法:

scss 复制代码
@Override
public void onPause() {
    closeCamera();
    stopBackgroundThread();
    super.onPause();
}
csharp 复制代码
private void closeCamera() {
    try {
        mCameraOpenCloseLock.acquire();
        if (null != mCaptureSession) {
            mCaptureSession.close();
            mCaptureSession = null;
        }
        if (null != mCameraDevice) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
        if (null != mImageReader) {
            mImageReader.close();
            mImageReader = null;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
    } finally {
        mCameraOpenCloseLock.release();
    }
}
csharp 复制代码
/**
 * Stops the background thread and its {@link Handler}.
 */
private void stopBackgroundThread() {
    mBackgroundThread.quitSafely();
    try {
        mBackgroundThread.join();
        mBackgroundThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

其中mCameraOpenCloseLock类型为Semaphore;Google demo中使用了Semaphore防止在相机未关闭前就退出了App,因为这样会导致无法正常关闭相机,释放资源,相机服务是系统级别的,App如果一直持有其引用就无法被gc清理,造成泄露,同时也防止并发状态下多个应用频繁启动关闭相机;

可以看出,一共分为4个过程:

  1. CameraCaptureSessionImpl.close();
  2. CameraDevice.close();
  3. ImageReader.close();
  4. stopBackgroundThread();

依次分析;

2 CameraCaptureSessionImpl.close

scss 复制代码
@Override
public void close() {
    synchronized (mDeviceImpl.mInterfaceLock) {
        if (mClosed) {
            if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
            return;
        }
​
        if (DEBUG) Log.v(TAG, mIdString + "close - first time");
​
        mClosed = true;
​
        /*
         * Flush out any repeating request. Since camera is closed, no new requests
         * can be queued, and eventually the entire request queue will be drained.
         *
         * If the camera device was already closed, short circuit and do nothing; since
         * no more internal device callbacks will fire anyway.
         *
         * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
         * the camera. Once that's done, fire #onClosed.
         */
        try {
            mDeviceImpl.stopRepeating();
        } catch (IllegalStateException e) {
            // OK: Camera device may already be closed, nothing else to do
​
            // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
            // or just suppress the ISE only and rely onClosed.
            // Also skip any of the draining work if this is already closed.
​
            // Short-circuit; queue callback immediately and return
            mStateCallback.onClosed(this);
            return;
        } catch (CameraAccessException e) {
            // OK: close does not throw checked exceptions.
            Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
​
            // TODO: call onError instead of onClosed if this happens
        }
​
        // If no sequences are pending, fire #onClosed immediately
        mSequenceDrainer.beginDrain();
    }
    // createCaptureSessionInternal()方法中传入的InputConfiguration类型参数为null,所以在createCaptureSession的时候,mInput变量没有被赋值,所以为null
    if (mInput != null) {
        mInput.release();
    }
}

其核心为mDeviceImpl.stopRepeating(),查看源码:

scss 复制代码
public void stopRepeating() throws CameraAccessException {
​
    synchronized(mInterfaceLock) {
        checkIfCameraClosedOrInError();
        if (mRepeatingRequestId != REQUEST_ID_NONE) {
​
            int requestId = mRepeatingRequestId;
            mRepeatingRequestId = REQUEST_ID_NONE;
​
            long lastFrameNumber;
            try {
                lastFrameNumber = mRemoteDevice.cancelRequest(requestId);
            } catch (IllegalArgumentException e) {
                if (DEBUG) {
                    Log.v(TAG, "Repeating request was already stopped for request " + requestId);
                }
                // Repeating request was already stopped. Nothing more to do.
                return;
            }
​
            checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
        }
    }
}

其核心为mRemoteDevice.cancelRequest(requestId),查看源码:

php 复制代码
binder::Status CameraDeviceClient::cancelRequest(
        int requestId,
        /*out*/
        int64_t* lastFrameNumber) {
    ATRACE_CALL();
    ALOGV("%s, requestId = %d", __FUNCTION__, requestId);
​
    status_t err;
    binder::Status res;
​
    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");
    }
​
    Mutex::Autolock idLock(mStreamingRequestIdLock);
    if (mStreamingRequestId != requestId) {
        String8 msg = String8::format("Camera %s: Canceling request ID %d doesn't match "
                "current request ID %d", mCameraIdStr.string(), requestId, mStreamingRequestId);
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
    }
​
    err = mDevice->clearStreamingRequest(lastFrameNumber);
​
    if (err == OK) {
        ALOGV("%s: Camera %s: Successfully cleared streaming request",
                __FUNCTION__, mCameraIdStr.string());
        mStreamingRequestId = REQUEST_ID_NONE;
    } else {
        res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                "Camera %s: Error clearing streaming request: %s (%d)",
                mCameraIdStr.string(), strerror(-err), err);
    }
​
    return res;
}

其核心为mDevice->clearStreamingRequest(lastFrameNumber),查看源码:

c 复制代码
status_t Camera3Device::clearStreamingRequest(int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);
​
    switch (mStatus) {
        case STATUS_ERROR:
            CLOGE("Device has encountered a serious error");
            return INVALID_OPERATION;
        case STATUS_UNINITIALIZED:
            CLOGE("Device not initialized");
            return INVALID_OPERATION;
        case STATUS_UNCONFIGURED:
        case STATUS_CONFIGURED:
        case STATUS_ACTIVE:
            // OK
            break;
        default:
            SET_ERR_L("Unexpected status: %d", mStatus);
            return INVALID_OPERATION;
    }
    ALOGV("Camera %s: Clearing repeating request", mId.string());
​
    return mRequestThread->clearRepeatingRequests(lastFrameNumber);
}

执行到这一步的时候,mStatus的状态为STATUS_ACTIVE,正常运行的情况下,mStatus的状态值为STATUS_ACTIVE,所以就会紧接着执行mRequestThread->clearRepeatingRequests,该方法源码分析:

arduino 复制代码
status_t Camera3Device::RequestThread::clearRepeatingRequests(/*out*/int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock l(mRequestLock);
    return clearRepeatingRequestsLocked(lastFrameNumber);
}
​
status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
    // 清空mRepeatingRequests请求队列
    mRepeatingRequests.clear();
    if (lastFrameNumber != NULL) {
        *lastFrameNumber = mRepeatingLastFrameNumber;
    }
    mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
    return OK;
}

上述逻辑过程中,将mRepeatingRequests请求队列清空之后,就直接会影响到正在轮询的RequestThread线程;

arduino 复制代码
bool Camera3Device::RequestThread::threadLoop() {
    ATRACE_CALL();
    status_t res;
​
    // Handle paused state.
    if (waitIfPaused()) {
        return true;
    }
​
    // Wait for the next batch of requests.
    waitForNextRequestBatch();
    if (mNextRequests.size() == 0) {
        return true;
    }
    ............
​
    // Unset as current request
    {
        Mutex::Autolock l(mRequestLock);
        mNextRequests.clear();
    }
​
    return submitRequestSuccess;
}

在threadloop中,会处理完一帧数据之后,mNextRequests就会执行clear()方法进行清空;

需要关注一下waitForNextRequestBatch()方法,在threadloop中会轮询waitForNextRequestBatch()方法,查看这个方法:

ini 复制代码
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);
​
    assert(mNextRequests.empty());
​
    NextRequest nextRequest;
    nextRequest.captureRequest = waitForNextRequestLocked();
    if (nextRequest.captureRequest == nullptr) {
        return;
    }
    
    nextRequest.halRequest = camera3_capture_request_t();
    nextRequest.submitted = false;
    mNextRequests.add(nextRequest);
    ............
​
    return;
}

而在waitForNextRequestBatch()方法中,首通过waitForNextRequestLocked()方法新创建一个nextRequest,然后将新建的nextRequest添加到mNextRequests中;

查看waitForNextRequestLocked()方法:

ini 复制代码
sp<Camera3Device::CaptureRequest>
        Camera3Device::RequestThread::waitForNextRequestLocked() {
    status_t res;
    sp<CaptureRequest> nextRequest;
​
    while (mRequestQueue.empty()) {
        if (!mRepeatingRequests.empty()) {
            // Always atomically enqueue all requests in a repeating request
            // list. Guarantees a complete in-sequence set of captures to
            // application.
            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 = 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;
                // Let the tracker know
                sp<StatusTracker> statusTracker = mStatusTracker.promote();
                if (statusTracker != 0) {
                    statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
                }
            }
            // Stop waiting for now and let thread management happen
            return NULL;
        }
    }
    ............
​
    return nextRequest;
}

在该方法中,首先会对mRequestQueue进行empty判断,在预览情况下,该mRequestQueue为空,因为这个请求队列一般只会存放capture的请求,即使因为从mRepeatingRequests中获取的request会再次添加到mRequestQueue中,也会在下一次轮询时,将mRequestQueue中的request erase掉,最终,mRequestQueue和mRepeatingRequests都为空,等待50ms(kRequestTimeout)之后,进入到if ((mRequestQueue.empty() && mRepeatingRequests.empty()) || exitPending())判断分支中,然后直接返回null;

ini 复制代码
NextRequest nextRequest;
nextRequest.captureRequest = waitForNextRequestLocked();
if (nextRequest.captureRequest == nullptr) {
    return;
}
nextRequest.halRequest = camera3_capture_request_t();
nextRequest.submitted = false;
mNextRequests.add(nextRequest);

即执行nextRequest.captureRequest = waitForNextRequestLocked()逻辑之后,nextRequest.captureRequest为null,因为captureRequest为null,所以进入if判断分支,所以直接return,所以不会执行mNextRequests.add(nextRequest)逻辑,所以当前mNextRequests为empty;

kotlin 复制代码
// Wait for the next batch of requests.
waitForNextRequestBatch();
if (mNextRequests.size() == 0) {
    return true;
}

所以在RequestThread::threadLoop()中执行waitForNextRequestBatch()方法,mNextRequests没有发生变化,所以mNextRequests.size() == 0为true,直接return true,然后又开始下一次的空轮询。

因为在threadLoop()中,只有return false的时候,才可以退出循环;

3 CameraDeviceImpl.close()

java 复制代码
@Override
public void close() {
    synchronized (mInterfaceLock) {
        if (mClosing.getAndSet(true)) {
            return;
        }
​
        if (mRemoteDevice != null) {
            mRemoteDevice.disconnect();
            // 解绑Binder
            mRemoteDevice.unlinkToDeath(this, /*flags*/0);
        }
​
        // Only want to fire the onClosed callback once;
        // either a normal close where the remote device is valid
        // or a close after a startup error (no remote device but in error state)
        if (mRemoteDevice != null || mInError) {
            mDeviceExecutor.execute(mCallOnClosed);
        }
​
        mRemoteDevice = null;
    }
}

核心逻辑:mRemoteDevice.disconnect(),在CameraDeviceClient中没有找到对应的disconnect()方法,那就再向上(父类)寻找,在Camera2ClientBase中找到了对应的方法:

php 复制代码
template <typename TClientBase>
binder::Status Camera2ClientBase<TClientBase>::disconnect() {
    ATRACE_CALL();
    Mutex::Autolock icl(mBinderSerializationLock);
​
    binder::Status res = binder::Status::ok();
    // Allow both client and the media server to disconnect at all times
    int callingPid = getCallingPid();
    if (callingPid != TClientBase::mClientPid &&
        callingPid != TClientBase::mServicePid) return res;
​
    ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
​
    detachDevice();
​
    CameraService::BasicClient::disconnect();
​
    ALOGV("Camera %s: Shut down complete complete", TClientBase::mCameraIdStr.string());
​
    return res;
}

在该方法中的核心逻辑:

scss 复制代码
detachDevice();
​
CameraService::BasicClient::disconnect();

3.1 detachDevice()

scss 复制代码
template <typename TClientBase>
void Camera2ClientBase<TClientBase>::detachDevice() {
    if (mDevice == 0) return;
    mDevice->disconnect();
​
    mDevice.clear();
​
    ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.string());
}

共两个方法:mDevice->disconnect()和mDevice.clear()

mDevice->disconnect():

scss 复制代码
status_t Camera3Device::disconnect() {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
​
    ALOGI("%s: E", __FUNCTION__);
​
    status_t res = OK;
    std::vector<wp<Camera3StreamInterface>> streams;
    nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
    {
        Mutex::Autolock l(mLock);
        if (mStatus == STATUS_UNINITIALIZED) return res;
​
        if (mStatus == STATUS_ACTIVE ||
                (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
            res = mRequestThread->clearRepeatingRequests();
            if (res != OK) {
                SET_ERR_L("Can't stop streaming");
                // Continue to close device even in case of error
            } else {
                res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
                if (res != OK) {
                    SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
                            maxExpectedDuration);
                    // Continue to close device even in case of error
                }
            }
        }
​
        if (mStatus == STATUS_ERROR) {
            CLOGE("Shutting down in an error state");
        }
​
        if (mStatusTracker != NULL) {
            mStatusTracker->requestExit();
        }
​
        if (mRequestThread != NULL) {
            mRequestThread->requestExit();
        }
​
        streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
        for (size_t i = 0; i < mOutputStreams.size(); i++) {
            streams.push_back(mOutputStreams[i]);
        }
        if (mInputStream != nullptr) {
            streams.push_back(mInputStream);
        }
    }
​
    // Joining done without holding mLock, otherwise deadlocks may ensue
    // as the threads try to access parent state
    if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
        // HAL may be in a bad state, so waiting for request thread
        // (which may be stuck in the HAL processCaptureRequest call)
        // could be dangerous.
        mRequestThread->join();
    }
​
    if (mStatusTracker != NULL) {
        mStatusTracker->join();
    }
​
    HalInterface* interface;
    {
        Mutex::Autolock l(mLock);
        mRequestThread.clear();
        mStatusTracker.clear();
        interface = mInterface.get();
    }
​
    // Call close without internal mutex held, as the HAL close may need to
    // wait on assorted callbacks,etc, to complete before it can return.
    interface->close();
​
    flushInflightRequests();
​
    {
        Mutex::Autolock l(mLock);
        mInterface->clear();
        mOutputStreams.clear();
        mInputStream.clear();
        mDeletedStreams.clear();
        mBufferManager.clear();
        internalUpdateStatusLocked(STATUS_UNINITIALIZED);
    }
​
    for (auto& weakStream : streams) {
        sp<Camera3StreamInterface> stream = weakStream.promote();
        if (stream != nullptr) {
            ALOGE("%s: Stream %d leaked! strong reference (%d)!",
                    __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
        }
    }
​
    ALOGI("%s: X", __FUNCTION__);
    return res;
}

在这个方法中,首先对mStatus状态值进行了判断,从整体的流程分析上可知,到目前位置,mStatus的状态值还没有发生变化,即目前的mStatus仍为STATUS_ACTIVE,所以会进入if判断;

紧接着执行RequestThread->clearRepeatingRequests()方法,即还是用于清空mRepeatingRequests请求队列;

clear完成之后,通过返回值判断,为OK时执行waitUntilStateThenRelock()方法:

arduino 复制代码
status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
    status_t res = OK;
​
    size_t startIndex = 0;
    if (mStatusWaiters == 0) {
        // Clear the list of recent statuses if there are no existing threads waiting on updates to
        // this status list
        mRecentStatusUpdates.clear();
    } else {
        // If other threads are waiting on updates to this status list, set the position of the
        // first element that this list will check rather than clearing the list.
        startIndex = mRecentStatusUpdates.size();
    }
​
    mStatusWaiters++;
​
    bool stateSeen = false;
    do {
        if (active == (mStatus == STATUS_ACTIVE)) {
            // Desired state is current
            break;
        }
​
        res = mStatusChanged.waitRelative(mLock, timeout);
        if (res != OK) break;
​
        // This is impossible, but if not, could result in subtle deadlocks and invalid state
        // transitions.
        LOG_ALWAYS_FATAL_IF(startIndex > mRecentStatusUpdates.size(),
                "%s: Skipping status updates in Camera3Device, may result in deadlock.",
                __FUNCTION__);
​
        // Encountered desired state since we began waiting
        for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
            if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
                stateSeen = true;
                break;
            }
        }
    } while (!stateSeen);
​
    mStatusWaiters--;
​
    return res;
}

这个方法主要是用于更新mRecentStatusUpdates;

scss 复制代码
        if (mStatus == STATUS_ERROR) {
            CLOGE("Shutting down in an error state");
        }
​
        if (mStatusTracker != NULL) {
            mStatusTracker->requestExit();
        }
​
        if (mRequestThread != NULL) {
            mRequestThread->requestExit();
        }

执行完上述方法之后,紧接着根据判断mStatus状态,变更mStatusTracker和mRequestThread的线程状态;

scss 复制代码
    if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
        // HAL may be in a bad state, so waiting for request thread
        // (which may be stuck in the HAL processCaptureRequest call)
        // could be dangerous.
        mRequestThread->join();
    }
​
    if (mStatusTracker != NULL) {
        mStatusTracker->join();
    }

在变更mStatusTracker和mRequestThread的线程状态时,需要等待线程状态执行完成之后,该方法才可以继续执行,否则会和后续的逻辑出现冲突;

ini 复制代码
HalInterface* interface;
{
    Mutex::Autolock l(mLock);
    mRequestThread.clear();
    mStatusTracker.clear();
    interface = mInterface.get();
}

等待mStatusTracker和mRequestThread线程状态更新完成之后,执行对应的clear方法以及获取hal层代理:

主要关注一下RequestThread::clear():

scss 复制代码
status_t Camera3Device::RequestThread::clear(
        /*out*/int64_t *lastFrameNumber) {
    ATRACE_CALL();
    Mutex::Autolock l(mRequestLock);
    ALOGV("RequestThread::%s:", __FUNCTION__);
​
    mRepeatingRequests.clear();
​
    // Send errors for all requests pending in the request queue, including
    // pending repeating requests
    sp<NotificationListener> listener = mListener.promote();
    if (listener != NULL) {
        for (RequestList::iterator it = mRequestQueue.begin();
                 it != mRequestQueue.end(); ++it) {
            // Abort the input buffers for reprocess requests.
            if ((*it)->mInputStream != NULL) {
                camera3_stream_buffer_t inputBuffer;
                status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
                        /*respectHalLimit*/ false);
                if (res != OK) {
                    ALOGW("%s: %d: couldn't get input buffer while clearing the request "
                            "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
                } else {
                    res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
                    if (res != OK) {
                        ALOGE("%s: %d: couldn't return input buffer while clearing the request "
                                "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
                    }
                }
            }
            // Set the frame number this request would have had, if it
            // had been submitted; this frame number will not be reused.
            // The requestId and burstId fields were set when the request was
            // submitted originally (in convertMetadataListToRequestListLocked)
            (*it)->mResultExtras.frameNumber = mFrameNumber++;
            listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
                    (*it)->mResultExtras);
        }
    }
    mRequestQueue.clear();
​
    Mutex::Autolock al(mTriggerMutex);
    mTriggerMap.clear();
    if (lastFrameNumber != NULL) {
        *lastFrameNumber = mRepeatingLastFrameNumber;
    }
    mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
    return OK;
}

在clear()方法中,首先对mRepeatingRequests进行clear操作,然后归还InputStream持有的buffer,然后再清空mRequestQueue请求队列;

scss 复制代码
    interface->close();
​
    flushInflightRequests();
​
    {
        Mutex::Autolock l(mLock);
        mInterface->clear();
        mOutputStreams.clear();
        mInputStream.clear();
        mDeletedStreams.clear();
        mBufferManager.clear();
        internalUpdateStatusLocked(STATUS_UNINITIALIZED);
    }

执行完请求队列的clear操作之后,就执行interface->close()方法,用于关闭hal层camera device。

然后接着执行代理、streams以及manager的清空操作用于释放资源;

最后执行internalUpdateStatusLocked(STATUS_UNINITIALIZED)方法,将mStatus的状态值修改为STATUS_UNINITIALIZED;

3.2 CameraService::BasicClient::disconnect()

scss 复制代码
binder::Status CameraService::BasicClient::disconnect() {
    binder::Status res = Status::ok();
    if (mDisconnected) {
        return res;
    }
    mDisconnected = true;
​
    sCameraService->removeByClient(this);
    sCameraService->logDisconnected(mCameraIdStr, mClientPid,
            String8(mClientPackageName));
​
    sp<IBinder> remote = getRemote();
    if (remote != nullptr) {
        remote->unlinkToDeath(sCameraService);
    }
​
    finishCameraOps();
    // Notify flashlight that a camera device is closed.
    sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
    ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.string(),
            mClientPid);
​
    // client shouldn't be able to call into us anymore
    mClientPid = 0;
​
    return res;
}

在这个方法中,其实主要是解绑binder代理和Application与CameraServer之间关系解除的操作;

rust 复制代码
status_t CameraService::BasicClient::finishCameraOps() {
    ATRACE_CALL();
​
    // Check if startCameraOps succeeded, and if so, finish the camera op
    if (mOpsActive) {
        // Notify app ops that the camera is available again
        mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
                mClientPackageName);
        mOpsActive = false;
​
        // This function is called when a client disconnects. This should
        // release the camera, but actually only if it was in a proper
        // functional state, i.e. with status NOT_AVAILABLE
        std::initializer_list<StatusInternal> rejected = {StatusInternal::PRESENT,
                StatusInternal::ENUMERATING, StatusInternal::NOT_PRESENT};
​
        // Transition to PRESENT if the camera is not in either of the rejected states
        sCameraService->updateStatus(StatusInternal::PRESENT,
                mCameraIdStr, rejected);
​
        int apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1;
        if (canCastToApiClient(API_2)) {
            apiLevel = hardware::ICameraServiceProxy::CAMERA_API_LEVEL_2;
        }
        // Transition device state to CLOSED
        sCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED,
                mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
    }
    // Always stop watching, even if no camera op is active
    if (mOpsCallback != NULL) {
        mAppOpsManager.stopWatchingMode(mOpsCallback);
    }
    mOpsCallback.clear();
​
    return OK;
}

处理Camera Application和CameraServer之间的关系;

至此CameraDeviceImpl.close()方法就执行结束了;

4 ImageReader.close()

scss 复制代码
@Override
public void close() {
    setOnImageAvailableListener(null, null);
    if (mSurface != null) mSurface.release();
​
    /**
     * Close all outstanding acquired images before closing the ImageReader. It is a good
     * practice to close all the images as soon as it is not used to reduce system instantaneous
     * memory pressure. CopyOnWrite list will use a copy of current list content. For the images
     * being closed by other thread (e.g., GC thread), doubling the close call is harmless. For
     * the image being acquired by other threads, mCloseLock is used to synchronize close and
     * acquire operations.
     */
    synchronized (mCloseLock) {
        mIsReaderValid = false;
        for (Image image : mAcquiredImages) {
            image.close();
        }
        mAcquiredImages.clear();
​
        nativeClose();
​
        if (mEstimatedNativeAllocBytes > 0) {
            VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes);
            mEstimatedNativeAllocBytes = 0;
        }
    }
}

在这个方法中,主要做了如下几件事:

  • 注销Listener:

    csharp 复制代码
    setOnImageAvailableListener(null, null);
  • 释放Surface:

    scss 复制代码
    if (mSurface != null) mSurface.release();
  • 释放Image;

    arduino 复制代码
    for (Image image : mAcquiredImages) {
        image.close();
    }
  • 清空Image集合;

    ini 复制代码
    private List<Image> mAcquiredImages = new CopyOnWriteArrayList<>();
    ​
    mAcquiredImages.clear();
  • nativeClose();

    scss 复制代码
    nativeClose();

至此,ImageReader这一块的逻辑也关闭了;

5 stopBackgroundThread()

csharp 复制代码
/**
 * Stops the background thread and its {@link Handler}.
 */
private void stopBackgroundThread() {
    mBackgroundThread.quitSafely();
    try {
        mBackgroundThread.join();
        mBackgroundThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

最后一步,将用于处理各种Handler回调的thread关闭;

至此,整个camea close的流程就基本上结束;

相关推荐
深海呐1 小时前
Android AlertDialog圆角背景不生效的问题
android
ljl_jiaLiang1 小时前
android10 系统定制:增加应用使用数据埋点,应用使用时长统计
android·系统定制
花花鱼1 小时前
android 删除系统原有的debug.keystore,系统运行的时候,重新生成新的debug.keystore,来完成App的运行。
android
canonical_entropy2 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
落落落sss2 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
沛沛老爹3 小时前
服务监控插件全览:提升微服务可观测性的利器
微服务·云原生·架构·datadog·influx·graphite
huaqianzkh4 小时前
了解华为云容器引擎(Cloud Container Engine)
云原生·架构·华为云
消失的旧时光-19435 小时前
kotlin的密封类
android·开发语言·kotlin
Kika写代码5 小时前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
刘某某.5 小时前
使用OpenFeign在不同微服务之间传递用户信息时失败
java·微服务·架构