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

前言
去年正式進入框架組的時候,啥也不會,瞎jb分析了一通 Android N 上面的 Camera 相關流程。其實基本上都是跟着別人的分析日誌看代碼,而後按照本身的理解記了些筆記而已。android

不過當時感受受益不淺,而且後來在項目開發、維護的時候,不少相關的內容都派上了用場。架構

從正式進入項目到如今大概有 10 個月了吧,其中大概有一半時間在 Android N 上填坑,另外一半就是填 Android O 上的坑了(雖然這些坑基本上都是本身人挖的)。如今終於感受本身對 Android Camera 這塊的架構也有必定的認識了。框架

然而,公司業務要往 HAL3 上遷移了,又要從新開始學習 Camera 流程了…… 
不過如今的我已經有必定的能力,能夠本身跟蹤流程去分析了。趁此機會,我就從比較簡單的 Camera 服務啓動流程開始,鍛鍊鍛鍊分析代碼、抽象出主幹思想的功力吧。ide

Camera 服務啓動流程概覽
在 Android O 中,系統啓動時,就會啓動 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)。 
 
(這個圖是部門裏的大佬給的…)學習

如此一來 Camera 服務的啓動流程就變得有些複雜了,可是最核心的部分其實沒變,最終都要從動態庫中獲取鏈接 HAL 的結構,並保存下來以備將來對 Camera 設備進行操做。 
這幾天跟了一下代碼流程,大概總結了一下 cameraserver 與 provider 這兩個進程啓動、初始化的調用邏輯,以下圖。 測試


整體邏輯順序:this

provider 進程啓動,註冊;
cameraserver 進程啓動,註冊,初始化;
cameraserver 獲取遠端 provider(此時實例化 CameraProvider 並初始化)。
上圖中,實線箭頭是調用關係。左邊是 cameraserver 進程中的動做,右邊則是 provider 進程中的動做,它們之間經過 ICameraProvider 聯繫在了一塊兒,而這個東西與 HIDL 相關,咱們能夠不用關心它的實現方式。線程

由圖可見:翻譯

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 進行某種關聯,註釋代表 Camera HAL 可能會經過它與其它 vendor 組件進行通訊。
第 7 行:建立默認爲直通模式(passthrough)的 CameraProvider 服務實現。
1    int main()
2    {
3       ALOGI("Camera provider Service is starting.");
4        // The camera HAL may communicate to other vendor components via
5        // /dev/vndbinder
6       android::ProcessState::initWithDriver("/dev/vndbinder");
7       return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/ 6);
8    }

LegacySupport.h
文件路徑:system\libhidl\transport\include\hidl

該函數作了這些事:

第 5 行:配置 RPC 線程池(當前設置最大線程爲 6)。
第 6 行:將 Interface(即 CameraProvider)以入參 legacy/0 爲名註冊到相應的管理服務中。
第 12 行:鏈接到線程池。
1    template<class Interface>
2    __attribute__((warn_unused_result))
3    status_t defaultPassthroughServiceImplementation(std::string name,
4                                                size_t maxThreads = 1) {
5       configureRpcThreadpool(maxThreads, true);
6        status_t result = registerPassthroughServiceImplementation<Interface>(name);

7

 8       if (result != OK) {
 9           return result;
 10      }

11

 12       joinRpcThreadpool();
 13      return 0;
14    }

CameraService 的啓動與初始化
通常來講應該是 Provider 服務先啓動,而後 Cameraserver 再啓動,並 」鏈接「 到 Provider。 
前面已經分析了 Provider 的啓動,如今就來看看 Cameraserver 的啓動流程。

main_cameraserver.cpp
文件位置:frameworks\av\camera\cameraserver

關於線程池配置的部分就忽略吧,主要關注第 11 行,在該進程中實例化了 CameraService。
實例化只有簡單的一行代碼,但實例化的過程並不那麼簡單。這個 instantiate() 接口並非定義在 CameraService 類中的,而是定義在 BinderService 類裏(而 CameraService 繼承了它)。在此處,它的做用是建立一個 CameraService(經過 new 的方式),並將其加入到 ServiceManager 中(注意,在這一過程當中,CameraService 被強指針引用了)。
1    int main(int argc __unused, char** argv __unused)
2    {
3        signal(SIGPIPE, SIG_IGN);

4

5        // Set 3 threads for HIDL calls
6        hardware::configureRpcThreadpool(3, /*willjoin*/ false);

7

8        sp<ProcessState> proc(ProcessState::self());
9        sp<IServiceManager> sm = defaultServiceManager();
10        ALOGI("ServiceManager: %p", sm.get());
11        CameraService::instantiate();
12       ProcessState::self()->startThreadPool();
13        IPCThreadState::self()->joinThreadPool();
14    }

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

因爲首次被強指針引用時,就會調用 onFirstRef() 函數執行初始化之類的業務邏輯,因此如今就看看 CameraService 在此處實現了什麼邏輯。

onFirstRef
根據 12~ 17 行能夠知道,初始化的主要邏輯實現應該在 enumerateProviders() 函數中。
而最後在 19 行調用一個 ping 函數,多是在嘗試鏈接到服務代理吧,無論它。
1    void CameraService::onFirstRef()
2    {
3        ALOGI("CameraService process starting");

4

5        BnCameraService::onFirstRef();

6

7        // Update battery life tracking if service is restarting
8        BatteryNotifier& notifier(BatteryNotifier::getInstance());
9        notifier.noteResetCamera();
10        notifier.noteResetFlashlight();

11

12        status_t res = INVALID_OPERATION;

13

14       res = enumerateProviders();
15        if (res == OK) {
16           mInitialized = true;
 17       }

18

 19   CameraService::pingCameraServiceProxy();
 20    }

enumerateProviders
函數內容略多,因此只截取須要重點關注的部分。
首先將 CameraProviderManager 實例化(第 2 行),而後調用 initialize() 接口將其初始化(第 3 行),傳入的參數是 this 指針,指向當前 CameraService 實例的地址。
1    if (nullptr == mCameraProviderManager.get()) {
2        mCameraProviderManager = new CameraProviderManager();
3        res = mCameraProviderManager->initialize(this);
4        if (res != OK) {
5            ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
6                    __FUNCTION__, strerror(-res), res);
7            return res;
8        }
9    }

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

initialize
在分析具體實現以前,能夠先看看它在頭文件中的聲明:

用於初始化管理器,並給它設置一個狀態監聽(即 CameraService 實例)。選擇性地接受一個與服務交互的代理。
默認的代理經過 Hardware 服務管理器進行通訊。備用的代理能夠用來進行測試。代理的生命週期必需要超過管理器的生命週期。
注意到在 enumerateProviders 中調用該接口時,只有一個入參,說明當前用的是默認代理。
   1     /**
    2     * Initialize the manager and give it a status listener; optionally accepts a service
    3     * interaction proxy.
    4     *
    5    * The default proxy communicates via the hardware service manager; alternate proxies can be
    6     * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
    7     */
    8     status_t initialize(wp<StatusListener> listener,
    9           ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);

接下來看看具體實現的邏輯:

第 11~19 行:經過服務代理做出一個註冊動做。根據註釋,註冊會觸發一個給全部已知 Provider 進行通知的動做。
第 22 行:這是咱們主要關注的函數。註釋翻譯過來是這樣,看看這是否爲一個直通的 HAL,若是不是也不要緊。注意傳入的參數 kLegacyProviderName,在文件開頭有它的定義,即爲字符串 legacy/0。
1    status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
2           ServiceInteractionProxy* proxy) {
3        std::lock_guard<std::mutex> lock(mInterfaceMutex);
4        if (proxy == nullptr) {
5            ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
6            return BAD_VALUE;
7        }
8        mListener = listener;
9       mServiceProxy = proxy;

10

11       // Registering will trigger notifications for all already-known providers
12        bool success = mServiceProxy->registerForNotifications(
13            /* instance name, empty means no filter */ "",
14            this);
15       if (!success) {
16           ALOGE("%s: Unable to register with hardware service manager for notifications "
17                    "about camera providers", __FUNCTION__);
18           return INVALID_OPERATION;
 19       }

20

21

 22       // See if there's a passthrough HAL, but let's not complain if there's not
 23       addProviderLocked(kLegacyProviderName, /*expected*/ false);

24

25    return OK;
}

addProviderLocked
這個函數主要做用是將找到的這個 Provider 經過 ProviderInfo 記錄下來並初始化。

第 2~8 行:檢查已知的 Provider 中是否已有名爲 legacy/0 的。
第 10~21 行:根據 legacy/0 從服務代理處獲取 CameraProvider 接口,這裏須要特別注意,由於此處真正地初始化了對應的 CameraProvider(怎麼就在這初始化了?下一節繼續分析)。
第 23~28 行:經過 ProviderInfo 來保存當前 Provider 相關信息。
第 30 行:記錄當前 Provider。
1    status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
2        for (const auto& providerInfo : mProviders) {
3            if (providerInfo->mProviderName == newProvider) {
4                ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
5                        newProvider.c_str());
6                return ALREADY_EXISTS;
7            }
8        }

9

10        sp<provider::V2_4::ICameraProvider> interface;
11        interface = mServiceProxy->getService(newProvider);

12

13        if (interface == nullptr) {
14            if (expected) {
15                ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
16                       newProvider.c_str());
 17               return BAD_VALUE;
 18           } else {
  19              return OK;
  20          }
  21  }

22

23

24        sp<ProviderInfo> providerInfo =
25                new ProviderInfo(newProvider, interface, this);
26        status_t res = providerInfo->initialize();
27       if (res != OK) {
28           return res;
29    }

30

 31       mProviders.push_back(providerInfo);

32

33    return OK;
}

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

在 CameraProviderManager::addProviderLocked 函數的實現邏輯中,調用了 ICameraProvider::getService 接口,該接口最終會調用到一個名爲 HIDL_FETCH_ICameraProvider 的函數。

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

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

1    ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
2        if (strcmp(name, kLegacyProviderName) != 0) {
3            return nullptr;
4        }
5        CameraProvider* provider = new CameraProvider();
6        if (provider == nullptr) {
7            ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
8           return nullptr;
9        }
10        if (provider->isInitFailed()) {
11           ALOGE("%s: camera provider init failed!", __FUNCTION__);
12           delete provider;
13            return nullptr;
14        }
15        return provider;
16    }

initialize
整個函數實現比較冗長,只貼出咱們須要關注的部分分析。

第 1~7 行:須要注意 rawModule 這個指針指向的結構,經過 hw_get_module 函數獲取到它的實例(從相應的 Camera HAL 動態庫中加載獲得)。實際上這個結構就是鏈接到 HAL 層的關鍵點,經過它就能夠調用到 HAL 中的一些函數。
(關於 hw_get_module,我之前分析過 Android N 上相關的邏輯,在 O 上其實沒有很大改動,若是要詳細瞭解能夠去看看那篇文章)
第 9~15 行:基於 rawModule 建立 CameraModule 實例並初始化。以後都是經過 mModule 來對 HAL 進行操做的。(其實 CameraModule 是對於 camera_module_t 的一層封裝,諸如 init、open 這樣的操做,實際上都是經過調用 camera_module_t 結構中函數指針指向的 HAL 層的具體實現函數來完成的)
執行完這個函數,CameraProvider 也就隨之初始化完成了。
1    camera_module_t *rawModule;
2    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
3            (const hw_module_t **)&rawModule);
4    if (err < 0) {
5        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
6        return true;
7    }

8

9    mModule = new CameraModule(rawModule);
10    err = mModule->init();
11    if (err != OK) {
12       ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
13        mModule.clear();
14        return true;
15    }
16    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());

小結
在 Android O 以前,Service 與 HAL 的耦合比較嚴重,而如今 Google 經過 HIDL 這個進程通訊機制將他們分隔成兩個進程,這使得 Service 與 HAL 之間的通路創建過程變得複雜了一些。 
本文對 Android O 上,這兩個進程的啓動與初始化流程進行了簡單的分析。整體來講是以下邏輯順序:

android.hardware.camera.provider@2.4-service 進程啓動,僅註冊 Provider; cameraserver 進程啓動,實例化 CameraService,並註冊到 ServiceManager 中; 因爲強指針首次引用,CameraService::onFirstRef() 被調用,至關於進行初始化; 在 CameraService 初始化過程當中,經過 CameraProviderManager 來獲取已註冊的 Provider,並實例化、初始化 CameraProvider; CameraProvider 初始化過程當中,從動態庫中加載了 HAL 層的關鍵結構,並將其封裝到 CameraModule 中; 將獲取到的 CameraProvider 保存在 ProviderInfo 中,以便後續的使用。 這其實就至關於 Android N 以前,整個 cameraserver 的啓動流程。異曲同工,最後都是經過 CameraModule 及其內部的 camera_module_t 鏈接到 Camera HAL。  

相關文章
相關標籤/搜索