camera daemon启动过慢

本文探讨了Android设备在加密状态下启动相机遇到的问题。由于mm-camera-daemon进程延迟启动,导致camera HAL无法正常工作,最终造成相机连接失败。文章提供了一种解决方案,通过在底层代码中增加对加密状态的检查,确保在加密完成前不尝试启动相机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

发现在android 加密的情况下,mm-camera-daemon进程会在手动解锁以后才会启动,这就导致在cameraserver启动的时候无法匹配到对应的camera devices。进而导致后悔一直connect camera 失败,提示没有对应的camera.


android 8.0 系统启动的时候会启动涉及camera的进程有三个:

1、android.hardware.camera.provider@2.4-service

该进程的启动控制在:hardware/interfaces/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc

2、cameraserver

该进程的启动控制在:frameworks/av/camera/cameraserver/cameraserver.rc

3、mm-qcamera-daemon

该进程的启动控制在:device/qcom/XXXX/init_target.rc


android.hardware.camera.provider@2.4-service启动以后会通过hal层的interface接口获取底层的camera devices等信息,

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c

然而这个底层的camera probe 是在mm-camera-daemon中进行的。

但是在android 加密的情况下,mm-qcamera-daemon会等到手动解锁以后才会启动,导致mm-qcamera-daemon启动太慢,hal无法获得camera的驱动信息,进而认为没有camera,后续就会出现camera一直连接不上,报错:

03-20 14:40:07.880  2061  2193 I CameraService: CameraService::connect call (PID -1 "com.hmdglobal.camera2", camera ID 0) for HAL version 256 and Camera API version 1

03-20 14:40:07.881  2061  2193 E CameraService: CameraService::connect X (PID 13570) rejected (invalid camera ID 0)

即提示没有对应的camera。

解决方法是:

在mm_camera_interface.c中

get_num_of_cameras时候添加判断当前是否加密状态,若加密状态,则一直自循环,知道解锁后再去获取camera。


具体patch:
@@ -1772,6 +1772,38 @@ void sort_camera_info(int num_cam)
     return;
 }
 
+
+/*===========================================================================
+ * FUNCTION : checkEncryptionCompleted
+ *
+ * DESCRIPTION: check data encryption completed or not
+ *
+ * PARAMETERS :
+ *
+ * RETURN : status of encryption process
+ *==========================================================================*/
+bool checkEncryptionCompleted()            //添加判断函数,判断当前是否加密状态
+{
+ char property[PROPERTY_VALUE_MAX];
+ bool is_EncryptionDone = false;
+ property_get("ro.crypto.state", property, "unencrypted");
+ if (!strcmp(property, "encrypted")) {
+ property_get("ro.crypto.type", property, "block");
+ if (!strcmp(property, "block")) {
+ property_get("vold.decrypt", property, "");
+ if (!strcmp(property, "trigger_restart_framework")) {
+ is_EncryptionDone = true;
+ }
+ }
+ } else if (!strcmp(property, "unsupported")) {
+ is_EncryptionDone = true;
+ LOGE(" Encryption not enabled , skip this");
+ }
+ return is_EncryptionDone;
+}
 /*===========================================================================
  * FUNCTION   : get_num_of_cameras
  *
@@ -1874,16 +1905,18 @@ uint8_t get_num_of_cameras()
 
     cfg.cfgtype = CFG_SINIT_PROBE_WAIT_DONE;
     cfg.cfg.setting = NULL;
+
+ while (1) {                    //添加循环判断,该循环10s执行一次
+ if(checkEncryptionCompleted()){
+ LOGD("Data Encryption completed, start Camera Daemon");
+ break;
         }
+ LOGD(" Camera Daemon not started yet , Waiting for encryption to complete");
+ }
+
+ if (ioctl(sd_fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg) < 0)
     close(sd_fd);
     dev_fd = -1;




class photographWindow(QMainWindow): def __init__(self): #继承父类 super().__init__() self.ui = Ui_photographWindow() #显示画面 self.ui.setupUi(self) self.show() self.captured_image = None #初始化值 没问题 self.camera_active = False self.ui.capture_btn.clicked.connect(self.capture_image) # 给按钮设置槽函数 拍照 #槽函数如果没有正确连接也会导致画面崩溃无法显示 #self.ui.save_btn.clicked.connect(self.save_to_database) # 保存 self.ui.retry_btn.clicked.connect(self.retry_capture) self.start_camera() #启动摄像头的方法 def start_camera(self): """初始化并启动摄像头""" self.cap = cv2.VideoCapture(0) #打开摄像头,(0)表示电脑默认摄像头 if not self.cap.isOpened(): #检测摄像头是否打开 QMessageBox.warning(self, "错误", "找不到摄像头!") #摄像头画面那个label,不启动就不会往下运行 return self.camera_active = True #起标记作用 #28行设置了默认值self.camera_active = False,改为True则摄像头开始运转 self.timer = QtCore.QTimer(self) #创建定时器 self.timer.timeout.connect(self.update_frame) #定时器触发时调用,用于定时刷新画面 self.timer.start(30) # 30ms刷新一次,控制画面刷新率 def update_frame(self): #展示在左侧画面 """更新摄像头预览画面""" if not self.camera_active: #如果摄像头未激活就直接返回 return ret, frame = self.cap.read() #从摄像头读取一帧画面 if ret: #ret为true表示读取成功 # 转换OpenCV BGR格式为Qt RGB格式 frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) #获取画面尺寸和字节数,用于创建QImage h, w, ch = frame.shape #这两步是把转换OpenCV BGR格式为Qt RGB格式 bytes_per_line = ch * w q_img = QtGui.QImage(frame.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888) #再转化为QPixmap形式,QT标签显示图片需要QPixmap形 pixmap = QtGui.QPixmap.fromImage(q_img) self.ui.label_P_tack_photos.setPixmap(pixmap.scaled( #把画面设置到ui上 self.ui.label_P_tack_photos.width(), #读取label的大小,按大小缩放画面,注意更换label的名称 self.ui.label_P_tack_photos.height(), QtCore.Qt.KeepAspectRatio #保持画面比例,避免拉伸变形 )) def capture_image(self): #点击拍照后的逻辑 """捕获当前帧作为照片""" if not self.camera_active: return ret, frame = self.cap.read() #读取一阵画面并显示 if ret: self.captured_image = frame #把画面保存到frame变量当中 # 在预览窗口显示捕获的图像 self.display_preview_image(frame) #引用变量,引用方法 # 更新状态和按钮 self.ui.label_P_statusbar.setText("状态: 照片已捕获! 请预览并决定是否保存") self.ui.save_btn.setEnabled(True) #启用保存和重拍按钮 self.ui.retry_btn.setEnabled(True) self.ui.capture_btn.setEnabled(False) def display_preview_image(self, image): #在预览区显示图像 """在预览区域显示图像""" # 转换图像格式 frame = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) h, w, ch = frame.shape bytes_per_line = ch * w q_img = QtGui.QImage(frame.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888) # 创建并设置预览图 preview_pixmap = QtGui.QPixmap.fromImage(q_img) #同样是转化格式并展示 preview_pixmap = preview_pixmap.scaled( self.ui.label_preview.width(), self.ui.label_preview.height(), QtCore.Qt.KeepAspectRatio ) self.ui.label_preview.setPixmap(preview_pixmap) def retry_capture(self): """重新拍摄照片""" # self.ui.label_preview.clear() #清空标签 self.ui.label_preview.setText("预览区域") #重新设置提示 self.ui.save_btn.setEnabled(False) self.ui.retry_btn.setEnabled(False) self.ui.capture_btn.setEnabled(True) self.ui.label_P_statusbar.setText("状态: 准备拍摄新照片") self.captured_image = None 为什么打开窗口加载慢
07-10
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值