Android Camera的一些调试技巧总结

您所在的位置:网站首页 苹果相机调试参数设置 Android Camera的一些调试技巧总结

Android Camera的一些调试技巧总结

2024-05-21 05:28| 来源: 网络整理| 查看: 265

把之前开发遇到的一些问题总结一下, 由于很多东西都是和具体平台(高通/MKT)相关的, 本来有更多的内容可以总结, 但由于不在之前公司了,一些源码和环境都没了, 只能写一下记得比较清楚的东西了.

dumpsys

dumpsys是Android系统中一个调试神器, 可以看内存信息, 电池信息, 相机参数等等, 基本Android中每一个大的模块, 都能通过dumpsys来查看. 调试Camera我们通常需要知道一些参数信息, 默认参数, 实际设置参数, 支持的参数, 这些信息都可以通过dumpsys media.camera来查看, 具体用法如下:

//执行这个adb命令会打印所有默认参数和当前使用参数 adb shell dumpsys media.camera //查看某一项参数,使用过滤命令grep(linux), windows下可使用findstr来过滤 adb shell dumpsys media.camera |grep picture-size //输出 picture-size: 3264x2448 picture-size-values: 5520x4140,5984x3366,3840x2160,3264x2448,2048x1536,1920x1080,1280x720,640x480,480x320,320x240

其中参数后面带values(比如上面picture-size-values)表示这个参数可设置的值,需要注意的是, 如果当前没有打开Camera, 执行命令也会有相应输出, 此时输出的值是默认值(打开camera不设置任何参数). 上面说的是针对HAL1的参数, 如果是HAL3参数, 输出内容就不一样了,如下:

adb shell dumpsys media.camera // HAL3部分参数输出 android.control.aeLockAvailable (10024): byte[1] [TRUE ] android.control.awbLockAvailable (10025): byte[1] [TRUE ] android.control.availableModes (10026): byte[2] [1 2 ] android.shading.availableModes (100002): byte[2] [1 2 ] android.statistics.info.availableLensShadingMapModes (120007): byte[1] [0 ] android.sensor.info.preCorrectionActiveArraySize (f000a): int32[4]

可以看到, HAL1和HAL3差别很大, HAL3参数格式和Android Camera API2是对应的,如果要看HAL3的相关参数, 直接使用grep命令存在问题, 因为grep只会输出有关键字的那一行,但HAL3参数的Key和Values一般都不在一行, 所以要把输出保存到文件中,然后搜索关键字

adb shell dumpsys media.camera > camera.txt No Display Mode

通常情况下,正常使用Camera的流程是:

打开Camera 设置参数 设置预览Surface 开启预览:startPreview() 拍照:takePicture()

但有些情况下, 我们希望不设置预览Surface就能拍照(默认情况下不设置预览进行拍照会Crash), 常见的应用场景是双摄项目, 打开了两个Camera,但副摄预览不需要用户看到, 这样做也可以减少系统资源占用, 高通和MTK平台都提供了不设置预览也可以拍照的功能, 使用方法如下:

高通平台 高通平台可以在ZSL开启的情况下, 通过设置参数Parameters.set("no-display-mode", "1");来达到不用设置Surface也能拍照的效果(参数必须在startPreview()之前设置). MTK平台 MTK平台要更简单些, 保证ZSD开启的情况下, 直接不用设置Surface, 进行startPreview()和takePicture()即可. Camera内存占用问题

我们都知道, Camera App和CameraService是两个进程, App内存占用大家一般用Android Studio就能看到, 但如果我们在HAL层加入了一些修改, 要看内存占用, 这个时候就需要看CameraService的内存占用了, CameraService调用HAL层接口, 所以HAL层内存占用就体现在CameraService中, 要找到CameraService的进程, 可通过如下方法: Android 7.1及以下版本

adb shell ps |grep -i camera //高通Android 7.1.1, 输出如下: cameraserver 371 1 20456 2240 binder_thr a84b396c S /system/bin/cameraserver camera 401 1 73188 3404 poll_sched ab1a8a6c S /system/bin/mm-qcamera-daemon

可以看到和Camera相关的进程有两个, 一个是我们要找的CameraService,名称为cameraserver 另一个就高通的Camera守护进程qcamera-daemon 找到进程后, 查看内存就简单了,也是通过dumpsys来查看(meminfo后面也可以使用pid作为参数):

$ adb shell dumpsys meminfo cameraserver Applications Memory Usage (in Kilobytes): Uptime: 24402928 Realtime: 83208095 Pss Private Private Swap Heap Heap Heap Total Dirty Clean Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ ------ Native Heap 196 196 0 40 0 0 0 Dalvik Heap 0 0 0 0 0 0 0 Stack 32 32 0 64 Other dev 5 0 4 0 .so mmap 470 204 176 508 Other mmap 14 8 4 8 Unknown 88 88 0 88 TOTAL 805 528 184 708 0 0 0 App Summary Pss(KB) ------ Java Heap: 0 Native Heap: 196 Code: 380 Stack: 32 Graphics: 0 Private Other: 104 System: 93 TOTAL: 805 TOTAL SWAP (KB): 708

Android 8.0及以上版本 在Android 8.0上, Google推出了一项Project Treble计划,旨在规范HAL接口, 简化Android的版本升级,其中一个重要改变就是, Framework层和HAL层也是通过Binder(此Binder和我们通常使用Binder不是同一个)通信, 因此HAL层内存占用并不在CameraService中, 而是在名为android.hardware.camera.provider@xx(xx表示版本号)中,比如SDM450平台就是[email protected],我们找到这个进程也是通过 adb shell ps |grep -i camera, 然后通过pid(名字可能会重复)来查看内存即可, 基本方法和上面一样, 只是进程不是CameraService.

API和HAL版本

Camera由于其复杂的特点, Android在发展过程中, Camera API也进行了更新, 在Android 5.0上, Google推出了Camera2 API, 同样HAL版本中API1和API2对应的版本是HAL1和HAL3. 但由于一些原因, HAL3和API2普及并不理想, 到目前为止, 中低端手机基本都是API1+HAL1, 对于开发者来说,我们可能想知道一个App用的API和HAL的版本,这个时候可以通过过滤Log方式来实现(高通和MTK都通用):

$ adb logcat |grep CameraService 04-07 14:07:43.174 371 4415 I CameraService: CameraService::connect call (PID -1 "com.smewise.camera2", camera ID 0) for HAL version default and Camera API version 1

可以看到Log打印的信息有App API的版本和HAL版本, API版本只有API1 和API2, HAL版本一般有三个结果: 256, 768, default. 256代表使用HAL1, 768为HAL3, default一般表示调用的是没有特别指定版本, 根据平台配置来决定,这种情况如果想知道到底使用的哪个版本, 需要看平台代码或者一些Log.

注:如果平台只支持HAL1, App通过API2去调用Camera的话, Framework层会将API2的调用转为用API1去调用, 也就是说虽然App使用的API2, 单对于CameraService来说使用的还是API1.

高通平台副摄可见

做过双摄项目的一般都知道, 副摄(一般id为2)对上层App是不可见的, 但我们在开发过程用需要对副摄进行一些测试, 因此是需要能打开副摄的,高通平台隐藏副摄是在Framework层做的处理, 代码如下: API1 代码: frameworks/base/core/java/android/hardware/Camera.java

public static int getNumberOfCameras() { boolean exposeAuxCamera = false; String packageName = ActivityThread.currentOpPackageName(); /* Force to expose only two cameras * if the package name does not falls in this bucket */ String packageList = SystemProperties.get("camera.aux.packagelist"); if (packageList.length() > 0) { TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(packageList); for (String str : splitter) { if (packageName.equals(str)) { exposeAuxCamera = true; break; } } } int numberOfCameras = _getNumberOfCameras(); if (exposeAuxCamera == false && (numberOfCameras > 2)) { numberOfCameras = 2; } return numberOfCameras; }

API2 代码: frameworks/base/core/java/android/hardware/camera2/CameraManager.java

private ArrayList getOrCreateDeviceIdListLocked() throws CameraAccessException { // 部分代码省略 try { numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL); /* Force to expose only two cameras * if the package name does not falls in this bucket */ boolean exposeAuxCamera = false; String packageName = ActivityThread.currentOpPackageName(); String packageList = SystemProperties.get("camera.aux.packagelist"); if (packageList.length() > 0) { TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); splitter.setString(packageList); for (String str : splitter) { if (packageName.equals(str)) { exposeAuxCamera = true; break; } } } if (exposeAuxCamera == false && (numCameras > 2)) { numCameras = 2; } //部分代码省略

可以看到,这段代码逻辑是如果App包名在camera.aux.packagelist这个属性中,则可以打开副摄, 否则不行.因此打开副摄有两种方法:

设置camera.aux.packagelist这个属性, 把要打开的App包名添加进去 删除这部分限制Camera个数的代码(不推荐) SnapdragonCamera高级设置

高通平台调试Camera一般用的就是SnapdragonCamera这个App, 这个App默认的设置参数比较有限, 有些我们想调节的参数没有, 比如anti-banding, 其实高通埋了个彩蛋在设置中的, 只要疯狂点击设置菜单中的Reduce Red Eye(减少红眼)选项, 然后重新进入设置菜单, 就能看到额外的设置选项了, 内容非常多, 比较有用, 控制这个额外菜单选项(DeveloperMenu)的代码如下: packages/apps/SnapdragonCamera/src/com/android/camera/PhotoMenu.java

public void onPreferenceClicked(ListPreference pref, int y) { if (!mActivity.isDeveloperMenuEnabled()) { if (pref.getKey().equals(CameraSettings.KEY_REDEYE_REDUCTION)) { privateCounter++; if (privateCounter >= DEVELOPER_MENU_TOUCH_COUNT) { mActivity.enableDeveloperMenu(); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(mActivity); prefs.edit().putBoolean(CameraSettings.KEY_DEVELOPER_MENU, true).apply(); RotateTextToast.makeText(mActivity, "Camera developer option is enabled now", Toast.LENGTH_SHORT).show(); } } else { privateCounter = 0; } } //其他代码省略 CameraService启动流程

CameraService是在开机的的时候启动的, 并且不管有没有App使用Camera, 进程会一直存在, 在开机时,CameraService会发起一次对底层Camera信息的查询, 这个操作主要是确定Camera的个数和Camera基本信息的, 也就是说如果在HAL层及以下, 修改了Camera个数, 需要重启手机才会生效. 另外由于CameraService开机启动, 如果HAL层修改东西存在问题, 可能会导致手机无法开机, 但据我所知, 高通平台Android 7.1.1及以后的版本, CameraService无法启动应该是不会影响整个系统的启动.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3