Android Camera的一些調(diào)試技巧總結(jié)

把之前開發(fā)遇到的一些問題總結(jié)一下, 由于很多東西都是和具體平臺(高通/MKT)相關的, 本來有更多的內(nèi)容可以總結(jié), 但由于不在之前公司了,一些源碼和環(huán)境都沒了, 只能寫一下記得比較清楚的東西了.

dumpsys

dumpsys是Android系統(tǒng)中一個調(diào)試神器, 可以看內(nèi)存信息, 電池信息, 相機參數(shù)等等, 基本Android中每一個大的模塊, 都能通過dumpsys來查看. 調(diào)試Camera我們通常需要知道一些參數(shù)信息, 默認參數(shù), 實際設置參數(shù), 支持的參數(shù), 這些信息都可以通過dumpsys media.camera來查看, 具體用法如下:

//執(zhí)行這個adb命令會打印所有默認參數(shù)和當前使用參數(shù)
adb shell dumpsys media.camera
//查看某一項參數(shù),使用過濾命令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

其中參數(shù)后面帶values(比如上面picture-size-values)表示這個參數(shù)可設置的值,需要注意的是, 如果當前沒有打開Camera, 執(zhí)行命令也會有相應輸出, 此時輸出的值是默認值(打開camera不設置任何參數(shù)).
上面說的是針對HAL1的參數(shù), 如果是HAL3參數(shù), 輸出內(nèi)容就不一樣了,如下:

adb shell dumpsys media.camera 
// HAL3部分參數(shù)輸出
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參數(shù)格式和Android Camera API2是對應的,如果要看HAL3的相關參數(shù), 直接使用grep命令存在問題, 因為grep只會輸出有關鍵字的那一行,但HAL3參數(shù)的Key和Values一般都不在一行, 所以要把輸出保存到文件中,然后搜索關鍵字

adb shell dumpsys media.camera > camera.txt

No Display Mode

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

  1. 打開Camera
  2. 設置參數(shù)
  3. 設置預覽Surface
  4. 開啟預覽:startPreview()
  5. 拍照:takePicture()

但有些情況下, 我們希望不設置預覽Surface就能拍照(默認情況下不設置預覽進行拍照會Crash), 常見的應用場景是雙攝項目, 打開了兩個Camera,但副攝預覽不需要用戶看到, 這樣做也可以減少系統(tǒng)資源占用, 高通和MTK平臺都提供了不設置預覽也可以拍照的功能, 使用方法如下:

  • 高通平臺
    高通平臺可以在ZSL開啟的情況下, 通過設置參數(shù)Parameters.set("no-display-mode", "1");來達到不用設置Surface也能拍照的效果(參數(shù)必須在startPreview()之前設置).
  • MTK平臺
    MTK平臺要更簡單些, 保證ZSD開啟的情況下, 直接不用設置Surface, 進行startPreview()和takePicture()即可.

Camera內(nèi)存占用問題

我們都知道, Camera App和CameraService是兩個進程, App內(nèi)存占用大家一般用Android Studio就能看到, 但如果我們在HAL層加入了一些修改, 要看內(nèi)存占用, 這個時候就需要看CameraService的內(nèi)存占用了, CameraService調(diào)用HAL層接口, 所以HAL層內(nèi)存占用就體現(xiàn)在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
找到進程后, 查看內(nèi)存就簡單了,也是通過dumpsys來查看(meminfo后面也可以使用pid作為參數(shù)):

$ 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計劃,旨在規(guī)范HAL接口, 簡化Android的版本升級,其中一個重要改變就是, Framework層和HAL層也是通過Binder(此Binder和我們通常使用Binder不是同一個)通信, 因此HAL層內(nèi)存占用并不在CameraService中, 而是在名為android.hardware.camera.provider@xx(xx表示版本號)中,比如SDM450平臺就是android.hardware.camera.provider@2.4,我們找到這個進程也是通過 adb shell ps |grep -i camera, 然后通過pid(名字可能會重復)來查看內(nèi)存即可, 基本方法和上面一樣, 只是進程不是CameraService.

API和HAL版本

Camera由于其復雜的特點, Android在發(fā)展過程中, Camera API也進行了更新, 在Android 5.0上, Google推出了Camera2 API, 同樣HAL版本中API1和API2對應的版本是HAL1和HAL3. 但由于一些原因, HAL3和API2普及并不理想, 到目前為止, 中低端手機基本都是API1+HAL1, 對于開發(fā)者來說,我們可能想知道一個App用的API和HAL的版本,這個時候可以通過過濾Log方式來實現(xiàn)(高通和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版本一般有三個結(jié)果: 256, 768, default.
256代表使用HAL1, 768為HAL3, default一般表示調(diào)用的是沒有特別指定版本, 根據(jù)平臺配置來決定,這種情況如果想知道到底使用的哪個版本, 需要看平臺代碼或者一些Log.

注:如果平臺只支持HAL1, App通過API2去調(diào)用Camera的話, Framework層會將API2的調(diào)用轉(zhuǎn)為用API1去調(diào)用, 也就是說雖然App使用的API2, 單對于CameraService來說使用的還是API1.

高通平臺副攝可見

做過雙攝項目的一般都知道, 副攝(一般id為2)對上層App是不可見的, 但我們在開發(fā)過程用需要對副攝進行一些測試, 因此是需要能打開副攝的,高通平臺隱藏副攝是在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<String> 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這個屬性中,則可以打開副攝, 否則不行.因此打開副攝有兩種方法:

  1. 設置camera.aux.packagelist這個屬性, 把要打開的App包名添加進去
  2. 刪除這部分限制Camera個數(shù)的代碼(不推薦)

SnapdragonCamera高級設置

高通平臺調(diào)試Camera一般用的就是SnapdragonCamera這個App, 這個App默認的設置參數(shù)比較有限, 有些我們想調(diào)節(jié)的參數(shù)沒有, 比如anti-banding, 其實高通埋了個彩蛋在設置中的, 只要瘋狂點擊設置菜單中的Reduce Red Eye(減少紅眼)選項, 然后重新進入設置菜單, 就能看到額外的設置選項了, 內(nèi)容非常多, 比較有用, 控制這個額外菜單選項(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會發(fā)起一次對底層Camera信息的查詢, 這個操作主要是確定Camera的個數(shù)和Camera基本信息的, 也就是說如果在HAL層及以下, 修改了Camera個數(shù), 需要重啟手機才會生效.
另外由于CameraService開機啟動, 如果HAL層修改東西存在問題, 可能會導致手機無法開機, 但據(jù)我所知, 高通平臺Android 7.1.1及以后的版本, CameraService無法啟動應該是不會影響整個系統(tǒng)的啟動.

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子艰匙,更是在濱河造成了極大的恐慌,老刑警劉巖障本,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異响鹃,居然都是意外死亡驾霜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門买置,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粪糙,“玉大人,你說我怎么就攤上這事忿项∪馗裕” “怎么了城舞?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寞酿。 經(jīng)常有香客問我家夺,道長,這世上最難降的妖魔是什么熟嫩? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任秦踪,我火速辦了婚禮,結(jié)果婚禮上掸茅,老公的妹妹穿的比我還像新娘。我一直安慰自己柠逞,他們只是感情好昧狮,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著板壮,像睡著了一般逗鸣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绰精,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天撒璧,我揣著相機與錄音,去河邊找鬼笨使。 笑死卿樱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的硫椰。 我是一名探鬼主播繁调,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼靶草!你這毒婦竟也來了蹄胰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤奕翔,失蹤者是張志新(化名)和其女友劉穎裕寨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體派继,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡宾袜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了互艾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片试和。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纫普,靈堂內(nèi)的尸體忽然破棺而出阅悍,到底是詐尸還是另有隱情好渠,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布节视,位于F島的核電站拳锚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寻行。R本人自食惡果不足惜霍掺,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拌蜘。 院中可真熱鬧杆烁,春花似錦、人聲如沸简卧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽举娩。三九已至析校,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铜涉,已是汗流浹背智玻。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芙代,地道東北人吊奢。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像链蕊,于是被迫代替她去往敵國和親事甜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容