当前位置: 首页 > news >正文

三方相机问题分析六:【没用相机,诡异的手电筒不可使用】下拉状态栏,手电筒置灰,无法打开,提提示相机正在使用

【关注我,后续持续新增专题博文,谢谢!!!】

上一篇我们讲了

        这一篇我们开始讲 三方相机问题分析六:【没用相机,诡异的手电筒不可使用】下拉状态栏,点击手电筒,手电筒置灰,无法打开,提提示相机正在使用9348353

目录

一、问题背景

二、:问题分析过程

    2.1:基于原理分析

    2.2 :systemui分析手电筒状态

    2.3 :camera framework分析手电筒回调

    2.4 :继续查看谁在使用手电筒

    2.5 :尝试直接打开手电筒看看会不会调用connect call

    2.6 :camx hal接力分析

    2.7 :相机未打开过,camx flash驱动代码未执行,为什么会回调?why?

    2.8 :查看KMD CAM-FLASH驱动

    2.9 :分析CAM_ACQUIRE_DEV被执行的地方。

    2.10 :全局搜索ReserveTorchForCamera

    2.11 :分析该接口

    2.12 :基于新需求分析猜测,验证场景

    2.13 :解决方案


一、问题背景

【操作步骤】【Operation steps】下拉状态栏,点击手电筒
【实际结果】【Actual results】手电筒置灰,无法打开,提示相机正在使用
【期望结果】【Expected results】手电筒可以正常使用

【出现次数/测试次数】【Occurrence Times/Test Times】偶现,

开发本地无法复现

二、:问题分析过程

    2.1:基于原理分析

  1. 手电筒和相机都是使用的闪光灯驱动。
  2. 手电筒不可使用,要么是闪光灯驱动工作导致闪光灯被占用、要么是systemui上层代码逻辑存在问题。
  3. 而无三方app在使用闪光灯,当前问题便变得扑朔迷离了,优先上层systemui来分析。

     

    2.2 :systemui分析手电筒状态

        由于问题出现在15:47:36左右,systemui搜索onTorchModeUnavailable 关键字,分析到如下日志:

行 123877: 06-13 15:47:36.802 10170 21962 W MIADSFlashLightEventMonitor: onTorchModeUnavailable!

行 123880: 06-13 15:47:36.802  2945  2945 D ScreenOffTorchHelper: onTorchModeUnavailable cameraId is 0

行 123882: 06-13 15:47:36.802  2945  2945 D ScreenOffTorchHelper: onTorchModeUnavailable cameraId is 3

行 123886: 06-13 15:47:36.803  2945  4143 D TorchManagerService: onTorchModeUnavailable, start to setRIOClientInfo.

行 123927: 06-13 15:47:36.805  2945  4143 D TorchManagerService: onTorchModeUnavailable, start to setRIOClientInfo.

行 123977: 06-13 15:47:36.812  4354  4471 I SystemUi--QuickSettings: FlashlightController-->onTorchModeUnavailable cameraId=0

而这个状态是camera framework层回调状态发生变化了,需要查看手电筒回调函数是否有变化,因此需要camera framework组协助。 

    2.3 :camera framework分析手电筒回调

camera framework组接力分析,搜索onTorchStatusChangedLocked关键字,分析到如下日志:

	行 112260: 06-13 15:47:15.802  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1行 112263: 06-13 15:47:15.804  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=3, newStatus=1行 118905: 06-13 15:47:25.168  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 118986: 06-13 15:47:25.196  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 119951: 06-13 15:47:26.108  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120223: 06-13 15:47:26.905  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120320: 06-13 15:47:27.256  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120487: 06-13 15:47:27.973  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1行 123803: 06-13 15:47:36.791  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=0行 123825: 06-13 15:47:36.795  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=3, newStatus=0

发现手电筒状态一直在变化,且最终status为0,也就是手电筒不可使用状态。然而java层的相机相关回调函数,一般都是有底层camera HAL来触发回调的,说明并非systemui上层逻辑问题,而是闪光灯驱动工作导致闪光灯被占用。需要camera hal组来接力分析。

    2.4 :继续查看谁在使用手电筒

闪光灯使用者要么是手电筒,要么是三方相机app,我们搜索connect call关键字,即可知道谁在使用闪光灯:

	行 96633: 06-13 15:47:11.516  2321 24904 I CameraService: CameraService::connect call (PID 21313 "com.camera", camera ID 0) and Camera API version 2行 112260: 06-13 15:47:15.802  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1行 112263: 06-13 15:47:15.804  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=3, newStatus=1行 118905: 06-13 15:47:25.168  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 118986: 06-13 15:47:25.196  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 119951: 06-13 15:47:26.108  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120223: 06-13 15:47:26.905  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120320: 06-13 15:47:27.256  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120487: 06-13 15:47:27.973  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1行 123803: 06-13 15:47:36.791  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=0行 123825: 06-13 15:47:36.795  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=3, newStatus=0行 123877: 06-13 15:47:36.802 10170 21962 W MIADSFlashLightEventMonitor: onTorchModeUnavailable!行 123880: 06-13 15:47:36.802  2945  2945 D ScreenOffTorchHelper: onTorchModeUnavailable cameraId is 0行 123882: 06-13 15:47:36.802  2945  2945 D ScreenOffTorchHelper: onTorchModeUnavailable cameraId is 3行 123886: 06-13 15:47:36.803  2945  4143 D TorchManagerService: onTorchModeUnavailable, start to setRIOClientInfo.行 123927: 06-13 15:47:36.805  2945  4143 D TorchManagerService: onTorchModeUnavailable, start to setRIOClientInfo.行 123977: 06-13 15:47:36.812  4354  4471 I SystemUi--QuickSettings: FlashlightController-->onTorchModeUnavailable cameraId=0

发现connect call有在15:47:11时间点有打开过相机,而出现问题的时间是15:47:36,隔了20分钟,所以不太可能是相机app打开相机导致的。由camera hal进一步确认hal流程。

    2.5 :尝试直接打开手电筒看看会不会调用connect call

单独打开手电筒,日志如下:

18844: 06-13 15:47:25.155  1702 22521 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1483 Initialize() Flash[0] [back_pmic_flash] Acquired, pipelineId:0, hCSL: 0x40200, hFlashDevice: 0x70101行 118899: 06-13 15:47:25.167  1702  3368 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=1 Operation=1 LEDs=2行 118900: 06-13 15:47:25.167  1702  3368 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1832 FirePMIC() Flash[0] Operation: Low: numberOfFlashs = 2 1:2 = 110 : 110, requestId= 1行 118905: 06-13 15:47:25.168  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 118981: 06-13 15:47:25.195  1702  3370 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=2 Operation=1 LEDs=2行 118982: 06-13 15:47:25.195  1702  3370 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1832 FirePMIC() Flash[0] Operation: Low: numberOfFlashs = 2 1:2 = 60 : 60, requestId= 2行 118986: 06-13 15:47:25.196  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 119948: 06-13 15:47:26.107  1702  3371 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=3 Operation=1 LEDs=2行 119949: 06-13 15:47:26.107  1702  3371 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1832 FirePMIC() Flash[0] Operation: Low: numberOfFlashs = 2 1:2 = 100 : 100, requestId= 3行 119951: 06-13 15:47:26.108  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120220: 06-13 15:47:26.904  1702  3368 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=4 Operation=1 LEDs=2行 120221: 06-13 15:47:26.904  1702  3368 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1832 FirePMIC() Flash[0] Operation: Low: numberOfFlashs = 2 1:2 = 125 : 125, requestId= 4行 120223: 06-13 15:47:26.905  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120317: 06-13 15:47:27.255  1702  3370 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=5 Operation=1 LEDs=2行 120318: 06-13 15:47:27.255  1702  3370 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1832 FirePMIC() Flash[0] Operation: Low: numberOfFlashs = 2 1:2 = 160 : 160, requestId= 5行 120320: 06-13 15:47:27.256  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=2行 120424: 06-13 15:47:27.953  1702  3371 V CamX    : [ VERB][UNKNOWN] camxflash.cpp:1761 FirePMIC() SENSOR_FLASH_DEBUG: Flash[0] Fire ReqId=6 Operation=0 LEDs=2行 120425: 06-13 15:47:27.953  1702  3371 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:1821 FirePMIC() Flash[0] Operation: OFF requestId= 6行 120469: 06-13 15:47:27.958  1702  3832 I CamX    : [CORE_CFG][SENSOR ] camxflash.cpp:166 Destroy() Flash[0] Release行 120487: 06-13 15:47:27.973  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1
  1. 并不会调用connect call
  2. 并不会调用camxhal3.cpp的接口
  3. camxflash.cpp会有闪光灯的调用过程和状态
  4. onTorchStatusChangedLocked也会调用

    2.6 :camx hal接力分析

搜索camxhal3.cpp关键字,发现相机在15:47:15.845就已经关闭,后面再也没有使用过相机。

06-13 15:47:15.845  1702  3832 E CamX    : [ALWAYS_ON   ] camxhal3.cpp:1249 close() HAL3Close end

而出现问题在15:47:36左右,搜索camxflash.cpp,并没有调用,此时有点懵了。

    2.7 :相机未打开过,camx flash驱动代码未执行,为什么会回调?why?

此时我们查看kernel KMD的flash驱动代码看看执行情况,这里才是真正是驱动代码。

    2.8 :查看KMD CAM-FLASH驱动

查看kernel dmesg日志:发现问题出现点,确认又执行CAM_ACQUIRE_DEV:

[31092.104338] CAM_INFO: CAM-FLASH: cam_flash_driver_cmd: 101 CAM_ACQUIRE_DEV for dev_hdl: 0x9e010b

哪到底被谁执行的?

    2.9 :分析CAM_ACQUIRE_DEV被执行的地方。

熟悉camx架构的话,会知道闪光灯流程在camxhal3.cpp open接口里:

  1. 申请使用是调用: HAL3Module::GetInstance()->ReserveTorchForCamera()
  2. 释放资源是使用: HAL3Module::GetInstance()->ReleaseTorchForCamera()

    2.10 :全局搜索ReserveTorchForCamera

发现只有两处使用ReserveTorchForCamera,除了camxhal3.cpp open接口,还有一个preconfig_open接口会调用,我们搜索日志发现:

	行 120487: 06-13 15:47:27.973  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=1行 123776: 06-13 15:47:36.781  1702  3831 E CamX    : [ALWAYS_ON   ] camxpreconfig.cpp:1963 Preconfig() preconfig,openTypes:0,camid:0,operation:0x8001行 123777: 06-13 15:47:36.781  1702  3831 E CamX    : [ALWAYS_ON   ] camxpreconfig.cpp:1183 preconfig_open() HAL3Open begin cameraId: 0 packagename:com..camera行 123803: 06-13 15:47:36.791  2321  4004 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newStatus=0行 123817: 06-13 15:47:36.793  1702  3831 E CamX    : [ALWAYS_ON   ] camxpreconfig.cpp:1283 preconfig_open() HAL3Open end行 123825: 06-13 15:47:36.795  2321 24904 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=3, newStatus=0

果然是因为preconfig_open被调用后,马上onTorchStatusChangedLocked就回调了,newStatus=0 变成了不可使用状态。

    2.11 :分析该接口

经过分析发现该接口是一个性能新需求,意外被开启后,导致此问题。这个需求会在点击桌面相机图标就会下发命令到camx并执行preconfig_open调用ReserveTorchForCamera占用闪光灯资源,并且在camera app oncreate之前就会调用,比opencamera api调用更早。然而点击相机图标就会调用相机,只可能是长按相机图标触发该接口,才不会打开相机。

static int preconfig_open(void)
{// Reserve the Torch resource for camera.// If torch already switched on, then turn it off and reserve for camera.HAL3Module::GetInstance()->ReserveTorchForCamera(GetCHIAppCallbacks()->chi_remap_camera_id(cameraId, IdRemapTorch).first, cameraId);if (CamxResultSuccess != result){// If open fails, then release the Torch resource that we reserved.HAL3Module::GetInstance()->ReleaseTorchForCamera(GetCHIAppCallbacks()->chi_remap_camera_id(cameraId, IdRemapTorch).first, cameraId);}CAMX_LOG_CORE_CFG(CamxLogGroupHAL, "HalOp: End OPEN, logicalCameraId: %d, cameraId: %d",logicalCameraId, cameraId);
}

    2.12 :基于新需求分析猜测,验证场景

长按和短按桌面相机图标发现:

  1. 长按不会调用connect call,不会调用camx hal3接口,会调用preconfig_open,接着调用CAM_ACQUIRE_DEV。但并不会打开相机,会显示app info等菜单。此时去下拉systemui,会发现手电筒变得不可使用。
  2. 01-02 00:58:26.671  3422  3804 E CamX    : [ALWAYS_ON   ] camxpreconfig.cpp:1183 preconfig_open() HAL3Open begin cameraId: 0 packagename:com..camera
    01-02 00:58:26.675  3422  3804 I CamX    : [CORE_CFG][HAL    ] camxpreconfig.cpp:1219 preconfig_open() HalOp: Begin OPEN, logicalCameraId: 0, cameraId: 0
    01-02 00:58:26.677  3422  3804 I CamX    : [CORE_CFG][HAL    ] camxpreconfig.cpp:1279 preconfig_open() HalOp: End OPEN, logicalCameraId: 0, cameraId: 0
    01-02 00:58:26.677  3422  3804 E CamX    : [ALWAYS_ON   ] camxpreconfig.cpp:1283 preconfig_open() HAL3Open end
  3. 短按点击会调用connect call,会调用camx hal3接口,会调用preconfig_open,会同时调用CAM_ACQUIRE_DEV和CAM_START_DEV。此时去下拉systemui,会发现手电筒也变得不可使用。但这个场景是正常,毕竟相机已经打开,其他三方APP不可抢占。
  4. 所以长按这种情况下,相机没有使用,而手电筒变得不可使用,显示是严重bug。

    2.13 :解决方案

  1. preconfig_open新需求明显存在严重漏洞,长按桌面相机图标提前调用preconfig_open,可提升相机性能,但如果不打开相机时,将没有地方释放闪光灯资源,会长期持有,手电筒一直无法使用,且功耗一直增加。因此需要修改当前新需求。
  2. 新需求修改和验证时间周期长,也可以关闭此需求。
  3. 也可长按不触发preconfig_open,改成长按不触发,短按触发。
  4. 保留此需求,可设置长按相机图标,实现定时器,若超过5秒不打开相机,主动调用camera hal3 close接口关闭相机。方案如下:
  5. @@ -10,6 +10,10 @@
    +#include <stdio.h>
    +#include <signal.h>
    +#include <sys/time.h>
    +#include <unistd.h>+static INT32 preconfigTimeout = 5;
    +static INT32 preconfigDefCameraID = 0;+int call_close(
    +    struct hw_device_t* pHwDeviceAPI)
    +{
    +    return close(pHwDeviceAPI);
    +}
    +int call_flush(
    +    const struct camera3_device* pCamera3DeviceAPI)
    +{
    +    return flush(pCamera3DeviceAPI);
    +}
    +int preconfig_close(struct hw_device_t* pHwDeviceAPI)
    +{
    +    int resultOut = 0;
    +    resultOut = call_close(pHwDeviceAPI);
    +    return resultOut;
    +}
    +int preconfig_flush(const struct camera3_device * pCamera3DeviceAPI)
    +{
    +    int resultOut = 0;
    +    resultOut = call_flush(pCamera3DeviceAPI);
    +    return resultOut;
    +}
    +static struct itimerval timer;
    +static BOOL hal3Opend = FALSE;
    +extern void timer_handler(int signum);
    +void stop_timer(void)
    +{
    +    timer.it_value.tv_sec = 0;
    +    timer.it_value.tv_usec = 0;
    +    timer.it_interval.tv_sec = 0;
    +    timer.it_interval.tv_usec = 0;
    +
    +	setitimer(ITIMER_REAL, &timer, NULL);
    +}
    +
    +int start_timer(void)
    +{
    +    signal(SIGALRM, timer_handler);
    +
    +    timer.it_value.tv_sec = preconfigTimeout;
    +    timer.it_value.tv_usec = 0;
    +    timer.it_interval.tv_sec = 0;
    +    timer.it_interval.tv_usec = 0;
    +
    +    if (setitimer(ITIMER_REAL, &timer, NULL) == -1) {
    +        CAMX_LOG_ERROR(CamxLogGroupHAL, "start_timer fail");
    +        return 1;
    +    }
    +    return 0;
    +}
    +void timer_handler(int signum) {
    +    if((isPreopenDone() || isPreconfigDone()) && !hal3Opend)
    +    {
    +        CAMX_LOG_ALWAYS_ON(CamxLogGroupHAL, "Long press the camera icon, timeout to preconfig_close, Status = 0x%x",getGlobalStatus());
    +        if (0 != preconfig_flush(GetCameraDeviceAPI()))
    +        {
    +            CAMX_LOG_ALWAYS_ON(CamxLogGroupHAL, "preconfig cameraid error, do flush fail");
    +        }
    +        if (0 != preconfig_close(&(GetCameraDeviceAPI()->common)))
    +        {
    +            CAMX_LOG_ALWAYS_ON(CamxLogGroupHAL, "preconfig cameraid error, do close camera fail");
    +        }
    +        hal3Opend = FALSE;
    +    }
    +
    +    stop_timer();
    +}
    +@@ -1298,6 +1334,8 @@ static int preconfig_open(void)
    +    start_timer();
    +    hal3Opend = FALSE;@@ -2049,6 +2109,7 @@ :CamxResult OpenStart(   {
    +    hal3Opend = TRUE;

【关注我,后续持续新增专题博文,谢谢!!!】

下一篇讲解

http://www.dtcms.com/a/329906.html

相关文章:

  • RAG-Fusion 实战:检索召回率提升新方案
  • 数据分析小白训练营:基于python编程语言的Numpy库介绍(第三方库)(下篇)
  • 智能制造数字孪生最佳交付实践:打造数据融合×场景适配×持续迭代的数字孪生框架
  • 计算机二级 Web —— HTML 全面精讲(含真题实战)
  • 2020/12 JLPT听力原文 问题一 5番
  • Unity3d UGUI图片按钮只有非透明区域(透明阈值)可以点击功能实现(含源码)
  • OSG —— Windows11下Vs2017完美编译Osg3.6.5+osgQt(附:Osg+osgQt测试用例)
  • GLSL学习
  • IPO辅导四年半,马上消费何时“马到成功”?
  • 深度解析:DCF估值模型实战指南 ——以Kappa Pi Therapeutics为例的完整估值建模过程
  • 万字长文全解析:五种主流归一化方法深入讲解(BN/LN/IN/GN/WN)
  • html img标签设置默认图片,防止图片路径不存在导致图片不展示影响页面美观
  • 微服务单元测试组件
  • 二分|回溯
  • 了解 Linux 中的 /usr 目录以及 bin、sbin 和 lib 的演变
  • C++算法·递推递归
  • 基于.Net Framework4.5 Web API 引用Swagger
  • HCIP——OSPF综合实验
  • 药房智能盘库系统:基于CV与时间序列预测的库存革命
  • 蓝蜂网关在雄安新区物联网建设中的关键应用
  • Vue内置组件全解析:从入门到面试通关
  • 用 OPC UA C# WinForm 的单节点订阅方法
  • 【个人项目】跑者天地—测试用例
  • AI搜索的极限优化、新兴技术、硬件加速、特定行业解决方案
  • [QtADS]解析demo.pro
  • 利用 Makefile 高效启动 VIVADO 软件:深入解析与实践
  • 十,算法-动态规划
  • 深入理解 Cookie 与 Session —— Web 状态保持详解与实战
  • 目标检测公开数据集全解析:从经典到前沿
  • Linux软件编程3.(文件IO和目录IO)