在关闭camera时耗时近6s。
日志分析
日志中存在如下异常:
03-04 16:58:14.180 9976 25944 E Camera3-Device: Camera 101: waitUntilDrainedLocked: Error waiting for HAL to drain: Connection timed out (-110)
03-04 16:58:14.231 9976 25944 D CameraTraces: Process trace saved. Use dumpsys media.camera to view.
03-04 16:58:14.232 9976 25944 E CameraDeviceClient: detachDevice: waitUntilDrained failed with code 0xffffff92
03-04 16:58:14.232 9976 25944 I Camera3-Device: disconnectImpl: E deviceId:101
03-04 16:58:14.232 9976 25944 E Camera3-Device: Camera 101: disconnectImpl: Shutting down in an error state
查看systrace发现flush和close调用都很快。waitUntilDrained耗时5s。上级调用为disconnect。

2. waitUntilDrained耗时分析
通过错误日志查询耗时函数

2.1 代码逻辑梳理
从总的调用disconnect开始梳理,整体调用存在2个条件等待。
App调用关闭等待条件1:App binder -> Camera2ClientBase<TClientBase>::disconnect -> CameraDeviceClient::detachDevice -> Camera3Device::waitUntilStateThenRelock -> mStatusChanged.waitRelative
满足条件1的调用逻辑: StatusTracker::threadLoop -> Camera3Device::notifyStatus-> Camera3Device::internalUpdateStatusLocked -> mStatusChanged.broadcast()
第二条逻辑等待条件满足的调用:StatusTracker::markComponentIdle(mPendingChangeSignal.signal())-> StatusTracker::threadLoop

通过上面逻辑发现要满足条件需要在执行processCaptureResult时mInFlightMap为0才会触发通知。
2.2 梳理的代码相关日志分析
正常日志:

异常日志:

通过对比日志发现异常时mInFlightMap不为0。说明异常出现在camera hal的pipeline中。
3. camera provider pipeline分析
分析camera hal的pipeline最直接方式就是在processOneCaptureRequest和processCaptureResult中将帧编号打印出来。

通过分析日志发现在返回第0帧时cameraserver未调用onInflightEntryRemovedLocked函数,说明返回数据存在问题。在第一次打印mInFlightMap时请求了3帧返回了2帧,此时mInFlightMap的大小应为1。在camera hal日志中发现请求第0帧数据时出现了错误,但是pipeline未处理该错误,最后给cameraserver返回了一帧错误数据。导致关闭相机时cameraserver一直等待超时。