Android CameraService啓動流程

在android系統啓動的過程中,CameraProvider服務啓動之後,接着將會啓動CameraService服務,它將負責與CameraClient進行通信,滿足應用需求。

下面以Android P進行相應的學習分析。

CameraService 啓動

  • android/frameworks/av/camera/cameraserver/cameraserver.rc

    service cameraserver /system/bin/cameraserver
        class main
        user cameraserver
        group audio camera input drmrpc
        ioprio rt 4
        writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
    

在android啓動的過程中,init進程調用該腳本啓動 CameraService 服務。根據該目錄下的 Android.mk 可以知道,其實就是運行該目錄下 main_cameraserver.cpp 編譯的可執行文件。

main_cameraserver.cpp

文件路徑:android/frameworks/av/camera/cameraserver

main_cameraserver.cpp 內容如下:

int main(int argc __unused, char** argv __unused)
{
    signal(SIGPIPE, SIG_IGN);

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

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

從內容可以看到,很多都是一些線程池的配置,主要是CameraService::instantiate() 。instantiate() 接口並不是定義在CameraService類中,而是定義在 BinderService 類(而CameraService繼承它,instantiate() 定義在android/frameworks/native/libs/binder/include/binder/BinderService.h)。在此處,它的作用是創建一個 CameraService(通過 new 的方式),並將其加入到 ServiceManager 中(注意,在這一過程中,CameraService 被強指針引用了)。注意這裏的ServiceName,這裏是CameraService.getServiceName(),返回的是 “media.camera”。後續應用將會通過這個ServiceName獲取CameraService的代理。

爲什麼會被強指針引用?

查看 IServiceManager::addService() 的聲明如下:

[android/frameworks/native/libs/binder/include/binder/IServiceManager.h]
	/**
     * Register a service.
     */
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated = false,
                                int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;

最終是 new CameraService() 賦值給 service 參數,而該參數是強指針引用,所以,將會調用 CameraService::onFirstRef() 函數。

CameraService.cpp

文件路徑:android/frameworks/av/services/camera/libcameraservice

在 CameraService::onFirstRef() 函數中,主要是調用 enumerateProviders() 函數獲取CameraProvider信息。

status_t CameraService::enumerateProviders() {
    status_t res;

    std::vector<std::string> deviceIds;
    {
        Mutex::Autolock l(mServiceLock);

        if (nullptr == mCameraProviderManager.get()) {
            mCameraProviderManager = new CameraProviderManager();
            /* 創建一個 CameraProviderManager 對象之後調用 initialize(),
             * 其實就是將CameraService設置爲 CameraProviderManager 的監聽者
             */
            res = mCameraProviderManager->initialize(this);
            if (res != OK) {
                ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
                        __FUNCTION__, strerror(-res), res);
                return res;
            }
        }

        ...

        deviceIds = mCameraProviderManager->getCameraDeviceIds();
    }


    for (auto& cameraId : deviceIds) {
        String8 id8 = String8(cameraId.c_str());
        onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
    }

    return OK;
}
CameraProviderManager.cpp

文件路徑:android/frameworks/av/services/camera/libcameraservice/common

    /**
     * Initialize the manager and give it a status listener; optionally accepts a service
     * interaction proxy.
     *
     * The default proxy communicates via the hardware service manager; alternate proxies can be
     * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
     */
    status_t initialize(wp<StatusListener> listener,
            ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);

CameraProviderManager::initialize() 主要完成以下操作:

  • 用於初始化管理器,並給它設置一個狀態監聽(即 CameraService 實例)。選擇性地接受一個與服務交互的代理。
  • 默認的代理通過 Hardware 服務管理器進行通信。備用的代理可以用來進行測試。代理的生命週期必須要超過管理器的生命週期。
  • 注意到在 enumerateProviders 中調用該接口時,只有一個入參,說明當前用的是默認代理。
  • 通過 mServiceProxy->registerForNotifications() 作出一個註冊的動作,註冊會觸發一個給所有已知 Provider 進行通知的動作。
  • 通過 CameraProviderManager::addProviderLocked() 獲得相應的 provider 代理信息(從實現來看,分別獲取 “legacy/0” 和 “external/0” 的代理信息)。
/* 調用參數:
 *     newProvider 參數分別是 "legacy/0" 和 "external/0"
 *     expected 參數爲 false
 */
status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    for (const auto& providerInfo : mProviders) {
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
                    newProvider.c_str());
            return ALREADY_EXISTS;
        }
    }

    sp<provider::V2_4::ICameraProvider> interface;
    /* mServiceProxy 爲 sHardwareServiceInteractionProxy,根據同一目錄下的
     * CameraProviderManager.h 中 HardwareServiceInteractionProxy 定義可以
     * 知道,getService() 將會調用
     * hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName)
     * 在這裏,CameraService已經獲得 CameraProvider
     */
    interface = mServiceProxy->getService(newProvider);

    if (interface == nullptr) {
        if (expected) {
            ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
                    newProvider.c_str());
            return BAD_VALUE;
        } else {
            return OK;
        }
    }

    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this);
    /* 在獲得CameraProvider代理之後,將會根據 ICameraProvider 填充相應的 providerInfo */
    status_t res = providerInfo->initialize();
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo);

    return OK;
}

上述的 interface = mServiceProxy->getService(newProvider) 函數將會調用 hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName) 獲取CameraProvider 代理,該函數將會調用到

android/out/soong/.intermediates/hardware/interfaces/camera/provider/2.4/[email protected]_genc++/gen/android/hardware/camera/provider/2.4 目錄下的CameraProviderAll.cpp文件,而在該文件中,也是通過 getRawServiceInternal( getStub = false) 獲取CameraProvider 代理,注意,此處的 getRawServiceInternal() 調用參數爲 false,getRawServiceInternal() 函數在 CameraProvider 註冊爲服務的時候調用了,只是調用參數不一致,所以,這裏返回的將會是 CameraProvider 代理。

status_t CameraProviderManager::ProviderInfo::initialize() {
    
    ...

    // Get initial list of camera devices, if any
    std::vector<std::string> devices;
    /* 獲取 CameraProvider 中的camera設備信息,這裏獲取的就是
     * CameraProvider服務在啓動時通過HAL層的 getCameraInfo() 得到的信息
     */
    hardware::Return<void> ret = mInterface->getCameraIdList([&status, &devices](
            Status idStatus,
            const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
        status = idStatus;
        if (status == Status::OK) {
            for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
                devices.push_back(cameraDeviceNames[i]);
            }
        } });
    
    ...

    for (auto& device : devices) {
        std::string id;
        /* 將上述獲取得到的camera信息保存到 mDevices,
         * 至此,CameraService與CameraProvider聯繫起來。
         * device的值一般類似以下: [email protected]/legacy/0
         * 該device的值,是CameraProvider服務獲取device之後,添加到 mCameraDeviceNames,
         * 該變量的含義如下:@3. : 3 是與camera HAL的版本號相關,
         *                        只要不是 CAMERA_DEVICE_API_VERSION_1_0,都是3
         *                3.3 :第二個 3 是從系統屬性
         *                 ro.vendor.camera.wrapper.hal3TrebleMinorVersion 獲取的,沒有則是3
         *                legacy/0 : 則與 CameraProvider 服務相關
         */
        status_t res = addDevice(device,
                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);
        if (res != OK) {
            ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
                    __FUNCTION__, device.c_str(), strerror(-res), res);
            continue;
        }
    }

    ALOGI("Camera provider %s ready with %zu camera devices",
            mProviderName.c_str(), mDevices.size());

    mInitialized = true;
    return OK;
}

status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
        CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {

    ALOGI("Enumerating new camera device: %s", name.c_str());

    uint16_t major, minor;
    std::string type, id;

    status_t res = parseDeviceName(name, &major, &minor, &type, &id);
    
    ...

    /* 根據HAL版本,創建相應的 DeviceInfo */
    std::unique_ptr<DeviceInfo> deviceInfo;
    switch (major) {
        case 1:
            deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, mProviderTagid,
                    id, minor);
            break;
        case 3:
            deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
                    id, minor);
            break;
        default:
            ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
                    name.c_str(), major);
            return BAD_VALUE;
    }
    ...

    mDevices.push_back(std::move(deviceInfo));

    ...
    
    return OK;
}

最後

至此,CameraService與CameraProvider聯繫起來,可以通過CameraService操作影響到camera HAL層。下圖爲在跟蹤代碼過程中,記錄的UML圖。
CameraService

參考文章

在瞭解學習CameraService服務的過程中,參考了網上很多的優秀文章,感謝!

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

Android P之Camera HAL3流程分析(0)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章