基于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个过程:
- CameraCaptureSessionImpl.close();
- CameraDevice.close();
- ImageReader.close();
- 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:
csharpsetOnImageAvailableListener(null, null);
-
释放Surface:
scssif (mSurface != null) mSurface.release();
-
释放Image;
arduinofor (Image image : mAcquiredImages) { image.close(); }
-
清空Image集合;
iniprivate List<Image> mAcquiredImages = new CopyOnWriteArrayList<>(); mAcquiredImages.clear();
-
nativeClose();
scssnativeClose();
至此,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的流程就基本上结束;