Camera Service

摘要:
左边是cameraserver进程中的动作,右边则是provider进程中的动作,它们之间通过ICameraProvider联系在了一起,而这个东西与HIDL相关,我们可以不用关心它的实现方式。此处初始化的最终目的是连接上CameraProvider。provider一侧,最终主体是CameraProvider。需要注意的是,此时CameraProvider还未实例化与初始化。第7行:创建默认为直通模式的CameraProvider服务实现。1intmain()2{3ALOGI;4//ThecameraHALmaycommunicatetoothervendorcomponentsvia5///dev/vndbinder6android::ProcessState::initWithDriver;7returndefaultPassthroughServiceImplementation;8}LegacySupport.h文件路径:systemlibhidlransportincludehidl该函数做了这些事:第5行:配置RPC线程池。第6行:将Interface以入参legacy/0为名注册到相应的管理服务中。

Camera Service第1张

上面这张图比较清楚的表现了camera provider进程在camera架构中位置,作为承上启下的部分,和cameraserver进程和底层的驱动交互,camera provider进程非常重要,camera HAL层几乎全部运行在camera provider进程中完成。

首先看下camera provider所在源码中的位置:hardware/interfaces/camera/provider/

Camera Service第2张

可以看出来在hardware/interfaces/camera/provider/2.4/default/ 下面有几个rc文件,Android初始化就是执行这些rc文件,这里执行的是android.hardware.camera.provider@2.4-service.rc文件,看看其中的执行代码。

1 service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
2 classhal
3 user cameraserver
4 group audio camera input drmrpc
5 ioprio rt 4
6 capabilities SYS_NICE
7 writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks

第一行就看到了启动一个 /vendor/bin/hw/android.hardware.camera.provider@2.4-service进程。

Cameraserver 执行文件对应的源码为:frameworksavcameracameraservermain_cameraserver.cpp

1     service cameraserver /system/bin/cameraserver
2     classmain
3 user cameraserver
4 group audio camera input drmrpc
5     ioprio rt 4
6     writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
7     rlimit rtprio 10 10

接下来看具体的流程:

cameraserver 与 provider 这两个进程启动、初始化的调用逻辑
@å¾. 主è¦è°ç¨æ­¥éª¤æ»è§

总体逻辑顺序:

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
文件位置:hardwareinterfacescameraprovider2.4default

看代码:

第 6 行:与 /dev/vndbinder 进行某种关联,注释表明 Camera HAL 可能会通过它与其它 vendor 组件进行通信。
第 7 行:创建默认为直通模式(passthrough)的 CameraProvider 服务实现。

1     intmain()
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
文件路径:systemlibhidl ransportincludehidl

该函数做了这些事:第 5 行:配置 RPC 线程池(当前设置最大线程为 6)。
第 6 行:将 Interface(即 CameraProvider)以入参 legacy/0 为名注册到相应的管理服务中。
第 12 行:连接到线程池。

1     template<class Interface>
2 __attribute__((warn_unused_result))
3     status_t defaultPassthroughServiceImplementation(std::stringname,
4                                                 size_t maxThreads = 1) {
5         configureRpcThreadpool(maxThreads, true);
6         status_t result = registerPassthroughServiceImplementation<Interface>(name);
7      
8         if (result !=OK) {
9             returnresult;
10 }
11      
12 joinRpcThreadpool();
13         return 0;
14     }

registerPassthroughServiceImplementation 的模板在LegacySupport.h 接下来就是hidl 相关的实现

1     template<class Interface>
2 __attribute__((warn_unused_result))
3 status_t registerPassthroughServiceImplementation(
4         std::string name = "default") {
5         sp<Interface> service = Interface::getService(name, true /*getStub */); //从当前进程空间中拿到IComposer接口类对象
6          
7         if (service ==nullptr) {
8         ALOGE("Could not get passthrough implementation for %s/%s.",
9 Interface::descriptor, name.c_str());
10         returnEXIT_FAILURE;
11 }
12          
13         LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
14 Interface::descriptor, name.c_str());
15          
16         status_t status = service->registerAsService(name);//将IComposer注册到hwservicemanager中
17          
18         if (status ==OK) {
19         ALOGI("Registration complete for %s/%s.",
20 Interface::descriptor, name.c_str());
21         } else{
22         ALOGE("Could not register service %s/%s (%d).",
23 Interface::descriptor, name.c_str(), status);
24 }
25          
26         returnstatus;
27     }

这里可以看一下 google 关于注册服务 registerAsService 的描述:https://source.android.google.cn/devices/architecture/hidl/services

HIDL 接口服务器(实现接口的对象)可注册为已命名的服务。注册的名称不需要与接口或软件包名称相关。如果没有指定名称,则使用名称“默认”;这应该用于不需要注册同一接口的两个实现的 HAL。例如,在每个接口中定义的服务注册的 C++ 调用是:

    status_t status = myFoo->registerAsService();
    status_t anotherStatus = anotherFoo->registerAsService("another_foo_service");  //if needed

HIDL 接口的版本包含在接口本身中。版本自动与服务注册关联,并可通过每个 HIDL 接口上的方法调用 (android::hardware::IInterface::getInterfaceVersion()) 进行检索。服务器对象不需要注册,并可通过 HIDL 方法参数传递到其他进程,相应的接收进程会向服务器发送 HIDL 方法调用。


CameraService 的启动与初始化

一般来说应该是 Provider 服务先启动,然后 Cameraserver 再启动,并 ”连接“ 到 Provider。
前面已经分析了 Provider 的启动,现在就来看看 Cameraserver 的启动流程。

Camera Service第4张

main_cameraserver.cpp
文件位置:frameworksavcameracameraserver

  • 关于线程池配置的部分就忽略吧,主要关注第 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
文件位置:frameworksavservicescameralibcameraservice

由于首次被强指针引用时,就会调用 onFirstRef() 函数执行初始化之类的业务逻辑,所以现在就看看 CameraService 在此处实现了什么逻辑。

onFirstRef

  • 根据 12~ 17 行可以知道,初始化的主要逻辑实现应该在 enumerateProviders() 函数中。
  • 而最后在 19 行调用一个 ping 函数,可能是在尝试连接到服务代理吧,不管它。
1     voidCameraService::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 = newCameraProviderManager();
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             returnres;
8 }
9     }

CameraProviderManager.cpp
文件位置:frameworksavservicescameralibcameraservicecommon

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             returnBAD_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             returnINVALID_OPERATION;
19 }
20          
21         //See if there's a passthrough HAL, but let's not complain if there's not
22         addProviderLocked(kLegacyProviderName, /*expected*/ false);
23          
24         returnOK;
25     }

上面是CameraProviderManager的初始化过程,CameraProviderManager就是管理camera Service与camera provider之间通信的工程管理类,两个参数,其中第二个参数就是远程代理类。这个参数已经是默认赋值了。不信可以看下CameraProviderManager::initialize的定义。

1     status_t initialize(wp<StatusListener>listener,
2     ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);

这是定义,默认值就是 ----> sHardwareServiceInteractionProxy,这个sHardwareServiceInteractionProxy是 ----> HardwareServiceInteractionProxy 的实例,可以看出在HardwareServiceInteractionProxy定义中,已经直接调用了ICameraProvider--->getService(...)了。

1     //Standard use case - call into the normal generated static methods which invoke
2     //the real hardware service manager
3     struct HardwareServiceInteractionProxy : publicServiceInteractionProxy {
4     virtual boolregisterForNotifications(
5         const std::string &serviceName,
6         const sp<hidl::manager::V1_0::IServiceNotification>
7         &notification) override{
8             returnhardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
9 serviceName, notification);
10 }
11         virtual sp<hardware::camera::provider::V2_4::ICameraProvider>getService(
12         const std::string &serviceName) override{
13             returnhardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
14 }
15     };

addProviderLocked
这个函数主要作用是将找到的这个 Provider 通过 ProviderInfo 记录下来并初始化。这儿就实现了camera service与camera provider的桥接了。

  • 第 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, boolexpected) {
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                 returnALREADY_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                 returnBAD_VALUE;
18             } else{
19                 returnOK;
20 }
21 }
22          
23         sp<ProviderInfo> providerInfo =
24         new ProviderInfo(newProvider, interface, this);
25         status_t res = providerInfo->initialize();
26         if (res !=OK) {
27             returnres;
28 }
29          
30 mProviders.push_back(providerInfo);
31          
32         returnOK;
33     }

这里可以看一下 google 关于注册服务 getService 的描述:https://source.android.google.cn/devices/architecture/hidl/services

发现服务
客户端代码按名称和版本请求给定的接口,并对所需的 HAL 类调用 getService:

1     //C++
2     sp<V1_1::IFooService> service =V1_1::IFooService::getService();
3     sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service");
4     //Java
5     V1_1.IFooService service = V1_1.IFooService.getService(true /*retry */);
6     V1_1.IFooService alternateService = V1_1.IFooService.getService("another", true /*retry */);

每个版本的 HIDL 接口都会被视为单独的接口。因此,IFooService 版本 1.1 和 IFooService 版本 2.2 都可以注册为“foo_service”,在任一接口上调用 getService("foo_service") 都会获得相应接口的已注册服务。因此,在大多数情况下,注册或发现服务均无需提供名称参数(也就是说名称为“默认”)。

供应商接口对象还会影响所返回接口的传输方法。对于软件包 android.hardware.foo@1.0 中的接口 IFoo,IFoo::getService 返回的接口始终使用设备清单中针对 android.hardware.foo 声明的传输方法(如果相应条目存在的话);如果该传输方法不存在,则返回 nullptr。

在某些情况下,即使没有获得相关服务,也可能需要立即继续。例如,当客户端希望自行管理服务通知或者在需要获得所有 hwservice 并检索它们的诊断程序(如 atrace)中时,可能会发生这种情况。在这种情况下,可以使用其他 API,如 C++ 中的 tryGetService 或 Java 中的 getService("instance-name", false)。Java 中提供的旧版 API getService 也必须与服务通知一起使用。使用此 API 不会避免以下竞态条件:当客户端使用某个非重试 API 请求服务器后,该服务器对自身进行了注册。

CameraProviderManager中提供了一个ProviderInfo来保存Camera provider信息,方便管理camera service调用 camera provider,下面分析一下ProviderInfo是怎么样的?方便我们接下来从这个为切入掉分析camera provider里面代码。

1     structProviderInfo :
2     virtual publichardware::camera::provider::V2_4::ICameraProviderCallback,
3     virtual publichardware::hidl_death_recipient
4 {
5         const std::stringmProviderName;
6         const sp<hardware::camera::provider::V2_4::ICameraProvider>mInterface;
7          
8         ProviderInfo(const std::string &providerName,
9         sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
10         CameraProviderManager *manager);
11          
12          
13 status_t initialize();
14         status_t addDevice(const std::string&name,
15         hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
16 hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
17         /*out*/ std::string *parsedId =nullptr);
18          
19          
20         //ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
21         virtual hardware::Return<void>cameraDeviceStatusChange(
22         const hardware::hidl_string&cameraDeviceName,
23         hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
24         virtual hardware::Return<void>torchModeStatusChange(
25         const hardware::hidl_string&cameraDeviceName,
26         hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
27          
28          
29         //hidl_death_recipient interface - this locks the parent mInterfaceMutex
30         virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
31          
32          
33         //......
34     };

ProviderInfo继承了 hardware::camera::provider::V2_4::ICameraProviderCallback 与 hardware::hidl_death_recipient,其中ProviderInfo 第 2个参数就是camera service与cameraprovider通信的IPC接口,保证两层可以顺利通信。

ICameraProviderCallback 是 camera provider的 回调接口,也是可以IPC间通信的,hardware::hidl_death_recipient 是hal层的死亡回调接口,方便在底层死亡的时候通知上层。

initialize() ----> initialize 函数的主要作用是初始化camera provider,并且IPC调用到camera provider 获取camera device信息,然后调用 addDevice接口将获取的camera device保存在内存中。

addDevice ----> 将底层获取的camera device信息保存在camera service中,防止多次跨进程调用。

cameraDeviceStatusChange 与 torchModeStatusChange 都是 ICameraProviderCallback 的回调函数,当camera provider发生变化的时候需要通知上层这些变化。

serviceDied 是 hardware::hidl_death_recipient 的回调函数,当底层发生问题的时候会通知上层变化。

我们在camera service中就是使用 ProviderInfo 来和底层的camera provider通信,保存camera device顺利运行。


CameraProvider 的初始化

在 CameraService 的初始化过程中,CameraProvider 才开始进行初始化,只不过这个初始化是通过服务代理进行远端调用而进行的。

在 CameraProviderManager::addProviderLocked 函数的实现逻辑中,调用了 ICameraProvider::getService 接口,该接口最终会调用到一个名为 HIDL_FETCH_ICameraProvider 的函数。

CameraProvider.cpp
文件位置:hardwareinterfacescameraprovider2.4default

HIDL_FETCH_ICameraProvider
若传入的参数是 legacy/0,则创建一个 CameraProvider 实例(构造函数中调用了它自身的初始化函数)并返回相应指针给函数调用者。

1     ICameraProvider* HIDL_FETCH_ICameraProvider(const char*name) {
2         if (strcmp(name, kLegacyProviderName) != 0) {
3             returnnullptr;
4 }
5         CameraProvider* provider = newCameraProvider();
6         if (provider ==nullptr) {
7             ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
8             returnnullptr;
9 }
10         if (provider->isInitFailed()) {
11             ALOGE("%s: camera provider init failed!", __FUNCTION__);
12             deleteprovider;
13             returnnullptr;
14 }
15         returnprovider;
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 = newCameraModule(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());

期间使用了camera_module_t这个结构体。可以看下 CameraModule::init函数。

1     intCameraModule::init() {
2 ATRACE_CALL();
3         int res =OK;
4         if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
5             mModule->init !=NULL) {
6             ATRACE_BEGIN("camera_module->init");
7             res = mModule->init();
8 ATRACE_END();
9 }
10 mCameraInfoMap.setCapacity(getNumberOfCameras());
11         returnres;
12     }

这儿调用的mModule->init(); 这个mModule就是camera_module_t结构体对象

1     typedef structcamera_module {
2 hw_module_t common;
3         int (*get_number_of_cameras)(void);
4         int (*get_camera_info)(int camera_id, struct camera_info *info);
5         int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
6         void (*get_vendor_tag_ops)(vendor_tag_ops_t*ops);
7         int (*open_legacy)(const struct hw_module_t* module, const char*id,
8         uint32_t halVersion, struct hw_device_t**device);
9         int (*set_torch_mode)(const char* camera_id, boolenabled);
10         int (*init)();
11         void* reserved[5];
12     } camera_module_t;

结构体中有一些函数指针,我们现在需要搞清楚这些函数指针被映射到什么地方了? camx 和 mm-camera 是一样的实现 类似于:(关于qcom的code只是copy了其他博文上的code)

1     camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) ={
2         .common ={
3             .tag =HARDWARE_MODULE_TAG,
4             .module_api_version =CAMERA_MODULE_API_VERSION_2_2,
5             .hal_api_version =HARDWARE_HAL_API_VERSION,
6             .id =CAMERA_HARDWARE_MODULE_ID,
7             .name = "Default Camera HAL",
8             .author = "The Android Open Source Project",
9             .methods = &gCameraModuleMethods,
10             .dso =NULL,
11             .reserved = {0},
12 },
13         .get_number_of_cameras =get_number_of_cameras,
14         .get_camera_info =get_camera_info,
15         .set_callbacks =set_callbacks,
16         .get_vendor_tag_ops =get_vendor_tag_ops,
17         .open_legacy =NULL,
18         .set_torch_mode =NULL,
19         .init =NULL,
20         .reserved = {0},
21     };
1     static hw_module_t camera_common ={
2         .tag =HARDWARE_MODULE_TAG,
3         .module_api_version =CAMERA_MODULE_API_VERSION_2_4,
4         .hal_api_version =HARDWARE_HAL_API_VERSION,
5         .id =CAMERA_HARDWARE_MODULE_ID,
6         .name = "QCamera Module",
7         .author = "Qualcomm Innovation Center Inc",
8         .methods = &qcamera::QCamera2Factory::mModuleMethods,
9         .dso =NULL,
10         .reserved = {0}
11 };
12      
13     camera_module_t HAL_MODULE_INFO_SYM ={
14         .common =camera_common,
15         .get_number_of_cameras =qcamera::QCamera2Factory::get_number_of_cameras,
16         .get_camera_info =qcamera::QCamera2Factory::get_camera_info,
17         .set_callbacks =qcamera::QCamera2Factory::set_callbacks,
18         .get_vendor_tag_ops =qcamera::QCamera3VendorTags::get_vendor_tag_ops,
19         .open_legacy =NULL,
20         .set_torch_mode =qcamera::QCamera2Factory::set_torch_mode,
21         .init =NULL,
22         .reserved = {0}
23     };

小结

在 Android O 之前,Service 与 HAL 的耦合比较严重,而现在 Google 通过 HIDL 这个进程通信机制将他们分隔成两个进程,这使得 Service 与 HAL 之间的通路建立过程变得复杂了一些。
本文对 Android O 上,这两个进程的启动与初始化流程进行了简单的分析。总体来说是如下逻辑顺序:

  1. android.hardware.camera.provider@2.4-service 进程启动,仅注册 Provider;
  2. cameraserver 进程启动,实例化 CameraService,并注册到 ServiceManager 中;
  3. 由于强指针首次引用,CameraService::onFirstRef() 被调用,相当于进行初始化;
  4. 在 CameraService 初始化过程中,通过 CameraProviderManager 来获取已注册的 Provider,并实例化、初始化 CameraProvider;
  5. CameraProvider 初始化过程中,从动态库中加载了 HAL 层的关键结构,并将其封装到 CameraModule 中;
  6. 将获取到的 CameraProvider 保存在 ProviderInfo 中,以便后续的使用。

这其实就相当于 Android N 之前,整个 cameraserver 的启动流程。殊途同归,最后都是通过 CameraModule 及其内部的 camera_module_t 连接到 Camera HAL。

免责声明:文章转载自《Camera Service》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇将List&amp;lt;T&amp;gt;转化成 DataTable调整可空类型的转化错误sam格式详细说明下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CS231N 数据预处理(data proprecessing)

原文链接:https://blog.csdn.net/weixin_38646522/article/details/79534677 一些数据预处理的标准方法有均值化数据和归一化数据。 零中心化的意义在上面已经详细的讲述了,这里就不在细讲。 归一化数据的意义在于让所有的特征都在相同的值域之内,并且让这些特征有相同的贡献。对于图像处理,在大部分情况下会进...

C# 类类型

1、一旦定义了自定义构造函数,默认的构造函数就会被移除2、可以使用this设计构造函数链,将核心部分代码由主构造函数完成,其余的构造函数调用主构造函数就可以了3、静态构造函数适合初始化静态数据成员(这个初始化发生在编译时)4、防止创建类对象的方式: 定义静态类 将构造函数声明为私有的(private) 将类声明为抽象的(abstract) 5、OOP...

swiper 绑定点击事件 点击失效处理

1、 问题:react使用swiper3插件实现banner轮播,其中有个banner图有个click点击事件,而其他的是页面跳转。出现了一个问题: 就是向右滑动到该帧时的swiper,点击时未触发react的onClick方法。 参考文章地址:https://www.cnblogs.com/wuhairui/p/9343846.html 错误示范 组件初...

LWIP network interface 网卡 初始化 以 STM32 为例子 后面会有 用 2G 或者4G 模块 用 PPP拨号的 形式 虚拟出网卡 所以先以 这个为 前提

LWIP   network interface   网卡 初始化    以  STM32  为例子  后面会有 用  2G 或者4G 模块 用 PPP拨号的 形式  虚拟出网卡  所以先以 这个为  前提  LWIP   有 一个 结构体 是 描述 物理 接口 的  即  netif Struct, 大神朱工 对这个 有个 详细的 解释 :http://...

u-boot核心初始化

异常向量表:异常:因为内部或者外部的一些事件,导致处理器停下正在处理的工作,转而去处理这些发生的事件。ARM Architecture Reference Manual p54页。7种异常的类型:Reset异常:突然按下重启键。Undefined Instruction:未定义指令。()software interrup:软中断()Prefetch Abo...

Flask入门之触发器,事件,数据迁移

SQLAlchemy Core和SQLAlchemy ORM都具有各种各样的事件挂钩: 核心事件 - 这些在 Core Events中描述,并包括特定于连接池生命周期,SQL语句执行,事务生命周期以及模式创建和拆卸的事件挂钩。 ORM事件 - 这些在 ORM事件中描述,并且包括特定于类和属性检测,对象初始化钩子,变更钩子,会话状态,刷新和提交钩子,映射器初...