负责的项目中遇到一些三方和其他的场景使用camera导致问题,并且没有及时释放camera device致使手机camera应用一直无法使用的严重问题,针对这类问题进行了一系列的分析与追踪,最后算是定位到了问题且提供了一些解决方案,但整个追溯解决的过程却不得不引人深思,万一以后出现这样的情况,该如何能在底层做到高效且完美的处理。
1.异常log分析追溯:
首先对DreamCamera2 apk调用流程进行分析,15:08:35 open fail报错,进而对异常前后的CameraService、HAL层相关log进行分析,定位原因为有camera device被占用,需要check其他apk或者包对Camera Device的使用情况。
2. Camera CameraService层查看其他包对camera device的调用
查看相关log发现,15:06:34 com.sprd.validationtools调用camera device阶段已经发生了异常,异常之前的俩次调用分别为15:06:03、15:06:31,俩次都是调用的camera id 1,即为前摄,15:06:03没有disconnect相关的动作,15:06:31 执行openCamera 3s后即发生了openCamera fail的异常报错,之后对camera device的调用会一直报too many other clients connecting的异常。
15:06:34反馈的camera connect erro问题是针对15:06:31 openCamera error状态的一个反馈回调。
3. 对15:06:03 openCamera之后的异常流程进行分析
Camera open之后通过API 1调用startPreview开启预览,时间点为 15:06:03.085
15:06:07 Camera2Client出现sync with HAL异常报错
15:06:08 出现cmr_prev 帧error的报错
15:06:16 events.log里面 com.sprd.validationtools出现anr异常,异常持续时间10s,与帧error时间吻合,之后直接destory掉FrontCameraTestActivity。
4.对15:06:31 时间段再次打开camera的流程以及异常点进行解析。
15:06:31.514 手动选择打开FrontCameraTestActivity
15:06:34.587打印open fail异常,FrontCameraTestActivity没法调用startPreview。
2.异常总结
问题点:异常点为15:06:03 openCamera 之后的3s时间后发生了帧error导致预览帧上不来,进而引发anr destory掉整个activity。(帧error后续分析定位为硬件频率干扰导致)
难点:此问题是由帧error导致的,但是让人头疼的点是帧erro之后触发了ANR的处理机制,并不是Camera的异常处理机制,这就导致CameraDevice的状态并不能clear、reset到之前的原始状态,对于Camera HAL来说,会认为有一个client一直在与他connecting状态中,导致后续camera device的使用都connect fail。
解决误区:解决方案初期是在Camera apk里面去处理openCallback返回openFail状态时去重新触发openCamera操作以及configureSession配流操作。其实此时一定的思维定式让我们陷入了一个贼大的误区里面。
通过不段的追踪代码,在CameraService里面找到了误区的答案,Camera APP与Camera HAL建立Client、Server联系时,可是需要你的packageName、clientPid、clientUid的,结合这个问题分析,异常是com.sprd.validationtools调用camera open阶段出现了异常,而我们却选择在com.android.camera2里面处理异常,现在来看简直有点可笑,不仅仅是不能在不同的package里面去解决异常,在同一个package里面被destory掉了,再create之后去处理异常都会在camera的层层connect问题下变的不被识别与认可,因为它所对应的pid发生了改变。
这也是为什么出现camera apk里面重新reopen Camera之后可以恢复预览,但是切换其他模式或者再次openCamera还是会有异常报错的原因。
后续方案:这个问题目前是定位到帧error由硬件的频率干扰导致后,由硬件部门拿出了规避方案。但是对于Camera Team工程师而言,这个问题需要我们在监控camera device的状态同时,要建立监控预览帧的机制,一旦一定时间内帧error没有发生更新,我们必须要采取规范的camera device destory流程进行release操作,否则会引发一系列后续的大问题。
当然有一个非常重要的点是:这不仅仅是针对camera apk建立帧error监控机制,对于任何其他调用camera device的package来说,都需要这样的机制,否则出现这种问题,后续其他的package里面都会因为packagesname、pis、uid不相符没办法处理掉这个流程。
3.技术总结
1.这个问题涉及到不同的packages调用camera Devices的问题,分析思路不能局限在camera app层相关的接口上,甚至Framework层走的都是不一样的camera API,只能在CameraService、HAL层去整体的check全部的camera调用异常的流程与状态。
2.针对不同的apk使用camera device异常但没及时处理问题,需要在底层找到更好的接口能达到类似reset all devic的接口。(就像很多不同的apk调用音频pcm device的问题,open了但是一直不做close操作,导致后面其他想用到音频device设备的apk一直处于busy状态)
4.总结
其实这个问题细思极恐,不管是手机还是平板甚至IOT项目,都会遇到很多不同的使用到camera device的场景、应用、apk等,对于底层来说,只有前后摄固定的sensor供这么多的应用使用,某个应用万一设计不合理,确实出现了用着用着我崩了,导致camera device没法close掉的操作,或者出现了让camera device一直是占用状态操作,真的很让人头秃。
同样的,音频device也会经常遇到这样的问题,对整个手机而言,不同应用抢占有限的device,整个的open、close时序把控起来真的很难完美,只能砥砺前行,选择不断遇到问题、解决问题咯!!!