小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[Android O] Camera 服務啟動流程簡析

 開花結果 2022-05-31 發(fā)布于北京


在 Android O 中,系統(tǒng)啟動時,就會啟動 CameraProvider 服務。它將 Camera HAL 從 cameraserver 進程中分離出來,作為一個獨立進程 android.hardware.camera.provider@2.4-service 來控制 HAL。
這兩個進程之間通過 HIDL 機制進行通信。

這樣的改動源自于 Android O 版本加入的 Treble 機制,它的主要功能(如下圖所示)是將 service 與 HAL 隔離,以方便 HAL 部分進行獨立升級。這其實和 APP 與 Framework 之間的 Binder 機制類似,通過引入一個進程間通信機制而針對不同層級進行解耦(從 Local call 變成了 Remote call)。

Alt text

(這個圖是部門里的大佬給的…)

如此一來 Camera 服務的啟動流程就變得有些復雜了,但是最核心的部分其實沒變,最終都要從動態(tài)庫中獲取連接 HAL 的結構,并保存下來以備未來對 Camera 設備進行操作。

這幾天跟了一下代碼流程,大概總結了一下 cameraserver 與 provider 這兩個進程啟動、初始化的調用邏輯,如下圖。

@圖. 主要調用步驟總覽
總體邏輯順序:

provider 進程啟動,注冊;
cameraserver 進程啟動,注冊,初始化;
cameraserver 獲取遠端 provider(此時實例化 CameraProvider 并初始化)。
上圖中,實線箭頭是調用關系。左邊是 cameraserver 進程中的動作,右邊則是 provider 進程中的動作,它們之間通過 ICameraProvider 聯(lián)系在了一起,而這個東西與 HIDL 相關,我們可以不用關心它的實現(xiàn)方式。

由圖可見:

cameraserver 一側,Cameraservice 類依舊是主體。它通過 CameraProviderManager 來管理對 CameraProvider 的操作。此處初始化的最終目的是連接上 CameraProvider。
provider 一側,最終主體是 CameraProvider。初始化最終目的是得到一個 mModule,通過它可以直接與 HAL 接口定義層進行交互。
至此,我們就能對 Android O 上的 Camera 服務啟動流程有一個大致的了解。但由于我個人功力尚淺,目前只能理解到這個地步,還無法輕易抽象出更容易理解的框架,所以圖片中的流程還是比較凌亂的,可能需要對照相應代碼才能理解。

下面是我分析代碼時的一些筆記,有需要可以對照上圖中的流程看看。

CameraProvider 的啟動與注冊
這個服務進程的啟動很簡單,主要動作是注冊該 CameraProvider,以便 CameraServer 啟動時能找到它。需要注意的是,此時 CameraProvider 還未實例化與初始化。

Service.cpp 文件位置:hardware\interfaces\camera\provider\2.4\default,看代碼:

第 6 行:與 /dev/vndbinder 進行某種關聯(lián),注釋表明 Camera HAL 可能會通過它與其它 vendor 組件進行通信。
第 7 行:創(chuàng)建默認為直通模式(passthrough)的 CameraProvider 服務實現(xiàn)。

 LegacySupport.h

文件路徑:system\libhidl\transport\include\hidl

該函數做了這些事:第 5 行:配置 RPC 線程池(當前設置最大線程為 6)。
第 6 行:將 Interface(即 CameraProvider)以入參 legacy/0 為名注冊到相應的管理服務中。
第 12 行:連接到線程池。

 https://blog.csdn.net/liujun3512159/article/details/122527997?spm=1001.2014.3001.5501

CameraService 的啟動與初始化
一般來說應該是 Provider 服務先啟動,然后 Cameraserver 再啟動,并 ”連接“ 到 Provider。
前面已經分析了 Provider 的啟動,現(xiàn)在就來看看 Cameraserver 的啟動流程。

main_cameraserver.cpp
文件位置:frameworks\av\camera\cameraserver關于線程池配置的部分就忽略吧,主要關注第 11 行,在該進程中實例化了 CameraService。
實例化只有簡單的一行代碼,但實例化的過程并不那么簡單。這個 instantiate() 接口并不是定義在 CameraService 類中的,而是定義在 BinderService 類里(而 CameraService 繼承了它)。在此處,它的作用是創(chuàng)建一個 CameraService(通過 new 的方式),并將其加入到 ServiceManager 中(注意,在這一過程中,CameraService 被強指針引用了)。

CameraService.cpp    文件位置:frameworks\av\services\camera\libcameraservice

由于首次被強指針引用時,就會調用 onFirstRef() 函數執(zhí)行初始化之類的業(yè)務邏輯,所以現(xiàn)在就看看 CameraService 在此處實現(xiàn)了什么邏輯。onFirstRef
根據 12~ 17 行可以知道,初始化的主要邏輯實現(xiàn)應該在 enumerateProviders() 函數中。
而最后在 19 行調用一個 ping 函數,可能是在嘗試連接到服務代理吧,不管它。

enumerateProviders

函數內容略多,所以只截取需要重點關注的部分。

首先將 CameraProviderManager 實例化(第 2 行),然后調用 initialize() 接口將其初始化(第 3 行),傳入的參數是 this 指針,指向當前 CameraService 實例的地址。

CameraProviderManager.cpp    文件位置:frameworks\av\services\camera\libcameraservice\common

initialize
在分析具體實現(xiàn)之前,可以先看看它在頭文件中的聲明:

用于初始化管理器,并給它設置一個狀態(tài)監(jiān)聽(即 CameraService 實例)。選擇性地接受一個與服務交互的代理。
默認的代理通過 Hardware 服務管理器進行通信。備用的代理可以用來進行測試。代理的生命周期必須要超過管理器的生命周期。

注意到在 enumerateProviders 中調用該接口時,只有一個入參,說明當前用的是默認代理。

接下來看看具體實現(xiàn)的邏輯:第 11~19 行:通過服務代理作出一個注冊動作。根據注釋,注冊會觸發(fā)一個給所有已知 Provider 進行通知的動作。

第 22 行:這是我們主要關注的函數。注釋翻譯過來是這樣,看看這是否為一個直通的 HAL,如果不是也沒關系。注意傳入的參數 kLegacyProviderName,在文件開頭有它的定義,即為字符串 legacy/0。 addProviderLocked

這個函數主要作用是將找到的這個 Provider 通過 ProviderInfo 記錄下來并初始化。第 2~8 行:檢查已知的 Provider 中是否已有名為 legacy/0 的。
第 10~21 行:根據 legacy/0 從服務代理處獲取 CameraProvider 接口,這里需要特別注意,因為此處真正地初始化了對應的 CameraProvider(怎么就在這初始化了?下一節(jié)繼續(xù)分析)。
第 23~28 行:通過 ProviderInfo 來保存當前 Provider 相關信息。
第 30 行:記錄當前 Provider。CameraProvider 的初始化

在 CameraService 的初始化過程中,CameraProvider 才開始進行初始化,只不過這個初始化是通過服務代理進行遠端調用而進行的。

在 CameraProviderManager::addProviderLocked 函數的實現(xiàn)邏輯中,調用了 ICameraProvider::getService 接口,該接口最終會調用到一個名為 HIDL_FETCH_ICameraProvider 的函數。見下面文章分析

Android Camera(一) Provider啟動流程 (androidP)(HIDL)_轉載和創(chuàng)作優(yōu)秀的博客-CSDN博客

CameraProvider.cpp
文件位置:hardware\interfaces\camera\provider\2.4\default

HIDL_FETCH_ICameraProvider
若傳入的參數是 legacy/0,則創(chuàng)建一個 CameraProvider 實例(構造函數中調用了它自身的初始化函數)并返回相應指針給函數調用者。

 new CameraProvider() 這個方法會執(zhí)行initialize

 initialize

整個函數實現(xiàn)比較冗長,只貼出我們需要關注的部分分析。第 1~7 行:需要注意 rawModule 這個指針指向的結構,通過 hw_get_module 函數獲取到它的實例(從相應的 Camera HAL 動態(tài)庫中加載得到)。實際上這個結構就是連接到 HAL 層的關鍵點,通過它就可以調用到 HAL 中的一些函數。
(關于 hw_get_module,我以前分析過 Android N 上相關的邏輯,在 O 上其實沒有很大改動,如果要詳細了解可以去看看那篇文章)
第 9~15 行:基于 rawModule 創(chuàng)建 CameraModule 實例并初始化。之后都是通過 mModule 來對 HAL 進行操作的。(其實 CameraModule 是對于 camera_module_t 的一層封裝,諸如 init、open 這樣的操作,實際上都是通過調用 camera_module_t 結構中函數指針指向的 HAL 層的具體實現(xiàn)函數來完成的)
執(zhí)行完這個函數,CameraProvider 也就隨之初始化完成了。

小結

在 Android O 之前,Service 與 HAL 的耦合比較嚴重,而現(xiàn)在 Google 通過 HIDL 這個進程通信機制將他們分隔成兩個進程,這使得 Service 與 HAL 之間的通路建立過程變得復雜了一些。
本文對 Android O 上,這兩個進程的啟動與初始化流程進行了簡單的分析??傮w來說是如下邏輯順序:

android.hardware.camera.provider@2.4-service 進程啟動,僅注冊 Provider;
cameraserver 進程啟動,實例化 CameraService,并注冊到 ServiceManager 中;
由于強指針首次引用,CameraService::onFirstRef() 被調用,相當于進行初始化;
在 CameraService 初始化過程中,通過 CameraProviderManager 來獲取已注冊的 Provider,并實例化、初始化 CameraProvider;
CameraProvider 初始化過程中,從動態(tài)庫中加載了 HAL 層的關鍵結構,并將其封裝到 CameraModule 中;
將獲取到的 CameraProvider 保存在 ProviderInfo 中,以便后續(xù)的使用。
這其實就相當于 Android N 之前,整個 cameraserver 的啟動流程。殊途同歸,最后都是通過 CameraModule 及其內部的 camera_module_t 連接到 Camera HAL。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多