RK3288 android 6.0 卡死在开机logo画面问题处理

Description

烧录固件后,会概率性出现卡死在开机画面无法启动的问题,但是烧录新固件后会恢复正常。对比不同机型,发现只有带摄像头功能的机型会有这个问题。

Root cause

经过大量测试和排查,发现卡死问题源自一个文件, /data/camera/media_profiles.xml , 这是一个空文件,删除后系统就正常启动了。

通过使用 logcat 结合系统源码发现,该文件是摄像头配置文件,如果为空会导致系统循环检测该文件,并尝试从中获取摄像头配置,但是由于文件为空,导致一直获取失败,最后陷入死循环。

$ cd /data/camera
$ ls
media_profiles.xml

经过排查源码,发现系统在检查到有摄像头接入后,会将默认配置文件 /etc/media_profiles_default.xml 拷贝至 /data/camera/media_profiles_tmp.xml, 然后根据实际情况修改该tmp文件,并最终写入到 /data/camera/media_profiles.xml 文件中。相关函数 ProduceNewXml如下:

// hardware/rockchip/camera/CameraHal/CameraHal_board_xml_parse.cpp
int camera_board_profiles::ProduceNewXml(camera_board_profiles* profiles)
{
     char temp_dst_file[50];
     char dst_file[50];
     char default_file[50];
     int err=0;
     int res=0;

     //CheckSensorSupportDV
     AddConnectSensorToVector(profiles);
     size_t nCamNum =profiles->mDevideConnectVector.size();

     //verrify media_xml_device is supported by board xml
     for(int i=0; (i<profiles->xml_device_count && i<2); i++)
     {
         res |= ConnectDevHaveDev(profiles, (profiles->mXmlDevInfo + i));
     }

     if(res == RK_RET_SUCCESS && profiles->xml_device_count==(int)nCamNum){
         return RK_RET_SUCCESS;
     }

     int fileexit = access(RK_DST_MEDIA_PROFILES_XML_PATH, 0);
     ALOGD("judge the media profile xml fileexit = %d\n", fileexit);
     //if((int)nCamNum>=1){
     if((int)nCamNum>=1 && fileexit == -1){
         LOG1("enter produce new xml\n");
         //new xml file name
         strlcpy(default_file, RK_DEFAULT_MEDIA_PROFILES_XML_PATH, sizeof(default_file));
         strlcpy(dst_file, RK_DST_MEDIA_PROFILES_XML_PATH, sizeof(dst_file));
         strlcpy(temp_dst_file, RK_TMP_MEDIA_PROFILES_XML_PATH, sizeof(temp_dst_file));

         for(int i=0; i<(int)nCamNum; i++){
             CheckSensorSupportDV(profiles->mDevideConnectVector[i]);
         }

         //write name to xml
         err = WriteDevNameTOXML(profiles, default_file, temp_dst_file);
         if(err){
             ALOGE("write dev name to xml failed\n");
             goto end;
         }

         //modify xml
         err = ModifyMediaProfileXML( profiles, temp_dst_file, dst_file);
         if(err){
             ALOGE("modify xml failed\n");
             goto end;
         }

         LOG1("exit produce new xml\n");
         }

 end:
     return err;

}

其中使用了宏定义变量,定义如下:

//  hardware/rockchip/camera/CameraHal/CameraHal_board_xml_parse.h
#define RK_DEFAULT_MEDIA_PROFILES_XML_PATH "/etc/media_profiles_default.xml"
#if defined(ANDROID_5_X)
#define RK_DST_MEDIA_PROFILES_XML_PATH "/data/camera/media_profiles.xml"
#define RK_TMP_MEDIA_PROFILES_XML_PATH "/data/camera/media_profiles_tmp.xml"
#else
#define RK_DST_MEDIA_PROFILES_XML_PATH "/data/media_profiles.xml"
#define RK_TMP_MEDIA_PROFILES_XML_PATH "/data/media_profiles_tmp.xml"
#endif

至于为何会出现该空文件,有可能是在写入过程中掉电导致的,但是目前没有重现。

reproduce

手动重现的方法比较简单,就是新建一个空文件 data/camera/media_profiles.xml, 新建后无论什么机型都会卡死在logo界面,这个bug应该是系统原生就有的。

cd /data/camera/
touch media_profiles.xml

files

相关文件如下:

# line 676 MediaProfiles::getInstance
frameworks/av/media/libmedia/MediaProfiles.cpp

hardware/rockchip/camera/CameraHal/*
hardware/rockchip/camera/CameraHal/CameraHal_board_xml_parse.h
hardware/rockchip/camera/CameraHal/CameraHal_MediaProfile.cpp

# int camera_board_profiles::LoadSensor(camera_board_profiles* profiles)
# 01-10 16:08:27.266   205   205 D CameraHal: read cam name from xml(/data/camera/media_profiles.xml)
hardware/rockchip/camera/CameraHal/CameraHal_board_xml_parse.cpp
$ cd /media/hdd1/wugt/rk3288-android6.0-sdk/out/target/product/rk3288  
$ grep -rn media_profiles.xml
Binary file obj/lib/camera.rk30board.so matches
Binary file obj/lib/libmedia.so matches
Binary file obj/PACKAGING/systemimage_intermediates/system.img matches
Binary file obj/SHARED_LIBRARIES/camera.rk30board_intermediates/LINKED/camera.rk30board.so matches
Binary file obj/SHARED_LIBRARIES/camera.rk30board_intermediates/PACKED/camera.rk30board.so matches
Binary file obj/SHARED_LIBRARIES/camera.rk30board_intermediates/CameraHal_board_xml_parse.o matches
Binary file obj/SHARED_LIBRARIES/camera.rk30board_intermediates/CameraHal_Module.o matches
Binary file obj/SHARED_LIBRARIES/libmedia_intermediates/LINKED/libmedia.so matches
Binary file obj/SHARED_LIBRARIES/libmedia_intermediates/PACKED/libmedia.so matches
Binary file obj/SHARED_LIBRARIES/libmedia_intermediates/MediaProfiles.o matches
Binary file system.img matches
Binary file system/lib/hw/camera.rk30board.so matches
Binary file system/lib/libmedia.so matches
Binary file symbols/system/lib/hw/camera.rk30board.so matches
Binary file symbols/system/lib/libmedia.so matches

logs

相关log如下:

130|root@rk3288:/ # logcat  |grep profile &
[1] 1070 1071
root@rk3288:/ # 01-07 11:08:57.330   205   205 E CameraHal: camera_get_number_of_cameras(695): board profiles cam num 7
01-07 11:08:57.330   205   205 D CameraHal: read cam name from xml(/data/camera/media_profiles.xml)
01-07 11:08:57.352   205   205 D CameraHal: camera_get_number_of_cameras(1146): meida_profiles_xml_control time (43839)us
01-07 11:08:59.981   171   171 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:08:59.982   171   171 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:01.087   543   543 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:01.088   543   543 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:06.287   558   558 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:06.287   558   558 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:11.466   584   584 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:11.466   584   584 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:15.695   610   610 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:15.695   610   610 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:20.920   636   636 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:20.920   636   636 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:26.222   671   671 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:26.222   671   671 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:31.403   696   696 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:31.403   696   696 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:35.640   725   725 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:35.640   725   725 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:40.841   748   748 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:40.841   748   748 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:46.009   770   770 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:09:46.009   770   770 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
01-07 11:09:51.775   797   797 E CameraHal: camera_get_number_of_cameras(695): board profiles cam num 7
01-07 11:09:51.775   797   797 D CameraHal: read cam name from xml(/data/camera/media_profiles.xml)
01-07 11:09:51.782   797   797 D CameraHal: camera_get_number_of_cameras(1146): meida_profiles_xml_control time (21590)us

root@rk3288:/ #
root@rk3288:/ #
root@rk3288:/ # cd /data/camera/
root@rk3288:/data/camera #
root@rk3288:/data/camera # 01-07 11:10:18.581   794   794 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:10:18.581   794   794 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
[   85.094068] init: couldn't write 0 to /dev/cpuset/foreground/tasks: No such file or directory
01-07 11:10:19.342  1079  1079 E CameraHal: camera_get_number_of_cameras(695): board profiles cam num 7
01-07 11:10:19.342  1079  1079 D CameraHal: read cam name from xml(/data/camera/media_profiles.xml)
01-07 11:10:19.350  1079  1079 D CameraHal: camera_get_number_of_cameras(1146): meida_profiles_xml_control time (21315)us

root@rk3288:/data/camera # 01-07 11:10:19.861  1077  1077 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:10:19.861  1077  1077 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml

root@rk3288:/data/camera #
root@rk3288:/data/camera # [   90.250059] init: couldn't write 0 to /dev/cpuset/foreground/tasks: No such file or directory
01-07 11:10:24.556  1207  1207 D CameraHal: camera_get_number_of_cameras(1146): meida_profiles_xml_control time (20242)us
01-07 11:10:25.081  1208  1208 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:10:25.081  1208  1208 D MediaProfiles: getInstance(713): Create instance from /data/camera/media_profiles.xml
root@rk3288:/data/camera #
root@rk3288:/data/camera #
root@rk3288:/data/camera # rm media_profiles.xml
root@rk3288:/data/camera # [   95.425765] init: couldn't write 0 to /dev/cpuset/foreground/tasks: No such file or directory
01-07 11:10:29.853  1343  1343 E CameraHal: camera_get_number_of_cameras(695): board profiles cam num 7
01-07 11:10:29.853  1343  1343 D CameraHal: read cam name from xml(/data/camera/media_profiles.xml)
01-07 11:10:29.860  1343  1343 D CameraHal: camera_get_number_of_cameras(1146): meida_profiles_xml_control time (22146)us
01-07 11:10:30.372  1344  1344 D MediaProfiles: CameraGroupFound(618): media_profiles_id: 0x0
01-07 11:10:30.372  1344  1344 E MediaProfiles: WARNING!!!! getInstance(689): cameraHal version(1.65.1) after(0.3.0x33),but don't have file(/data/camera/media_profiles.xml)
[  116.602227] healthd: battery l=100 v=0 t=42.4 h=2 st=2 chg=a 2022-01-07 03:10:50.769561638 UTC
[  116.814715] lowmemorykiller: lowmem_shrink: convert oom_adj to oom_score_adj:
[  116.814743] lowmemorykiller: oom_adj 0 => oom_score_adj 0
[  116.814754] lowmemorykiller: oom_adj 1 => oom_score_adj 58
[  116.814764] lowmemorykiller: oom_adj 2 => oom_score_adj 117
[  116.814773] lowmemorykiller: oom_adj 3 => oom_score_adj 176
[  116.814803] lowmemorykiller: oom_adj 9 => oom_score_adj 529
[  116.814813] lowmemorykiller: oom_adj 15 => oom_score_adj 1000

workaround

临时解决方案:在出现问题后通过 adb指令删除文件 /data/camera/media_profiles.xml, 或者使用默认配置文件覆盖它。

cd /data/camera
rm media_profiles.xml

# or

cp /etc/media_profiles_default.xml /data/camera/

solution

最终解决方案,就是在检查到 /data/camera/media_profiles.xml 后,查看文件大小,如果为空或者小于某个值,则认为该文件异常,将其删除。

diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index fe0126a..3258b71 100755
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -688,6 +688,17 @@ MediaProfiles::getInstance()
                             ALOGE("WARNING!!!! %s(%d): cameraHal version(%s) after(0.3.0x33),but don't have file(%s)",
                                      __FUNCTION__,__LINE__,camerahal_value,defaultXmlFile);
                         }
+                        else {
+                            fseek(fp, 0L, SEEK_END);
+                            int size = ftell(fp);
+
+                            if (size < 1000) {
+                                ALOGE("WARNING!!!! %s(%d): file(%s) size(%d) is too small, delete it",
+                                       __FUNCTION__,__LINE__,defaultXmlFile,size);
+                                fp = NULL;
+                                remove(defaultXmlFile);
+                            }
+                        }
                     } else {
                         if (fp == NULL)
                             ALOGD("THIS IS RIGHT: %s(%d): cameraHal version(%s) before(0.3.33),so don't have file(%s)",

删除后,系统能够正常启动,并且在下次启动后,会自动生成新文件。