当前位置: 首页 > 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.lryc.cn/news/619294.html

相关文章:

  • YOLOv1 到 YOLOv2 模型训练过程全解析
  • Java面试宝典:ZGC
  • 大模型能力评测方式很多?
  • 《Python学习之基础语法2:掌握程序流程控制的艺术》
  • RTCP详解
  • 【安卓,问题记录】ImageView 在布局顺序上位于 Button 上方,却出现图像内容被 Button 遮挡
  • [激光原理与应用-263]:理论 - 几何光学 - 光纤通信:以光为媒的现代通信基石
  • MySQL宝典
  • html原生js文件使用javascript-obfuscator插件进行加密处理
  • 《C++进阶之继承多态》【final + 继承与友元 + 继承与静态成员 + 继承模型 + 继承和组合】
  • HTML第三次作业
  • 腾讯位置商业授权微信小程序关键词输入提示
  • Flink DataStream 按分钟或日期统计数据量
  • 深度学习——03 神经网络(3)-网络优化方法
  • 基于Apache Flink的实时数据处理架构设计与高可用性实战经验分享
  • 搜索引擎核心机制解析
  • 美团搜索推荐统一Agent之性能优化与系统集成
  • 云计算-OpenStack 实战运维:从组件配置到故障排查(含 RAID、模板、存储管理,网络、存储、镜像、容器等)
  • Flink中的窗口
  • HTML5 Canvas实现数组时钟代码,适用于wordpress侧边栏显示
  • 方法论基础。
  • 设计秒杀系统从哪些方面考虑
  • 从零开始:用PyTorch实现线性回归模型
  • 比特币与区块链:去中心化的技术革命
  • VUE2连接USB打印机
  • Pytorch FSDP权重分片保存与合并
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day3
  • 【Qt开发】常用控件(三) -> geometry
  • 疏老师-python训练营-Day44预训练模型
  • php7 太空船运算符