OpenHarmony——CameraService服务启动流程分析 原创 精华

深开鸿
发布于 2022-8-5 15:13
浏览
1收藏

作者:罗健

1. 相机组件简介

相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等

CameraService服务作为相机组件的重要一环,对上为app层提供IPC接口,对下完成CameraDevice设备创建以及会话管理等。

1.1 相机组件的代码在openharmony中的位置

相机组件的代码位于【foundation/multimedia/camera_standard】目录下

代码结构如下

├── bundle.json
├── figures
├── frameworks							camera frameworks部分,支持js和native转换
│   ├── js
│   └── native
├── hisysevent.yaml
├── interfaces							CameraService接口
│   ├── inner_api
│   └── kits
├── LICENSE
├── OAT.xml
├── README.md
├── README_zh.md
├── sa_profile							CameraService进程加载配置文件
│   ├── 3008.xml
│   └── BUILD.gn
└── services							CameraService启动相关
    ├── camera_service
    └── etc

1.2 CameraService在系统中的位置

相机服务整体架构如下:

OpenHarmony——CameraService服务启动流程分析-鸿蒙开发者社区

可以看到在整个相机组件中,把相机功能抽象为CaptureSession(管理生命周期、参数配置、输入管理、输出管理)、CameraInput(设备查询、设备控制、设备监听)和CameraOutput(元数据输出、流输出和状态控制)。

而CameraService就是将这些功能如何由camera app传达给camera host服务的中间人,以及Camera Host服务反馈的消息转发给Camera app。

所以下面的文章主要来看看CameraService实现了哪些接口,以及CameraService的启动流程

2. CameraService Native实现IPC通信需要实现的主要重要接口

2.1 icamera_service接口

实现ICameraService接口,继承于IRemoteBroker,定义描述符、业务函数和消息码

接口函数代码如下

【foundation\multimedia\camera_standard\services\camera_service\binder\base\include\icamera_service.h】

class ICameraService : public IRemoteBroker {
public:
    virtual int32
    virtual int32_t CreatePhotoOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                                      sptr<IStreamCapture> &photoOutput) = 0;

    virtual int32_t CreatePreviewOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                                        sptr<IStreamRepeat> &previewOutput) = 0;

    virtual int32_t CreateCustomPreviewOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                                              int32_t width, int32_t he_t CreateCameraDevice(std::string cameraId, sptr<ICameraDeviceService>& device) = 0;

    virtual int32_t SetCallback(sptr<ICameraServiceCallback>& callback) = 0;

    virtual int32_t GetCameras(std::vector<std::string> &cameraIds,
        std::vector<std::shared_ptr<Camera::CameraMetadata>> &cameraAbilityList) = 0;

    virtual int32_t CreateCaptureSession(sptr<ICaptureSession> &session) = 0;
ight, sptr<IStreamRepeat> &previewOutput) = 0;

    virtual int32_t CreateVideoOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                                      sptr<IStreamRepeat> &videoOutput) = 0;

    virtual int32_t SetListenerObject(const sptr<IRemoteObject> &object) = 0;

    DECLARE_INTERFACE_DESCRIPTOR(u"ICameraService");
};
} // namespace CameraStandard
}

2.2 hcamera_service_stub接口

实现服务提供端HCameraServiceStub接口,继承于IRemoteStub(Native),实现接口类中未实现方法外,还需要实现OnRemoteRequest方法

接口函数代码:

【foundation\multimedia\camera_standard\services\camera_service\binder\server\include\hcamera_service_stub.h】

class HCameraServiceStub : public IRemoteStub<ICameraService> {
public:
    HCameraServiceStub();
    ~HCameraServiceStub();
    int OnRemoteRequest(uint32_t code, MessageParcel &data,
                        MessageParcel &reply, MessageOption &option) override;

private:
    int HandleGetCameras(MessageParcel& reply);
    int HandleCreateCameraDevice(MessageParcel &data, MessageParcel &reply);
    int HandleSetCallback(MessageParcel &data);
    int HandleCreateCaptureSession(MessageParcel &reply);
    int HandleCreatePhotoOutput(MessageParcel &data, MessageParcel &reply);
    int HandleCreatePreviewOutput(MessageParcel &data, MessageParcel &reply);
    int HandleCreatePreviewOutputCustomSize(MessageParcel &data, MessageParcel &reply);
    int HandleCreateVideoOutput(MessageParcel &data, MessageParcel &reply);
    int DestroyStubForPid(pid_t pid);
    void ClientDied(pid_t pid);
    int SetListenerObject(const sptr<IRemoteObject> &object) override;
    int SetListenerObject(MessageParcel &data, MessageParcel &reply);

    std::map<pid_t, sptr<CameraDeathRecipient>> deathRecipientMap_;
    std::map<pid_t, sptr<IStandardCameraListener>> cameraListenerMap_;
};
} // namespace CameraStandard
} 

2.3 hcamera_service_proxy接口

实现服务请求段接口HCameraServiceProxy,继承IRemoteProxy(Native),封装业务函数,调用SendRequest将请求发送到Stub

接口函数代码:

【foundation\multimedia\camera_standard\services\camera_service\binder\client\include\hcamera_service_proxy.h】

class HCameraServiceProxy : public IRemoteProxy<ICameraService> {
public:
    explicit HCameraServiceProxy(const sptr<IRemoteObject> &impl);

    virtual ~HCameraServiceProxy() = default;

    int32_t CreateCameraDevice(std::string cameraId, sptr<ICameraDeviceService>& device) override;

    int32_t SetCallback(sptr<ICameraServiceCallback>& callback) override;

    int32_t GetCameras(std::vector<std::string> &cameraIds,
        std::vector<std::shared_ptr<Camera::CameraMetadata>> &cameraAbilityList) override;

    int32_t CreateCaptureSession(sptr<ICaptureSession>& session) override;

    int32_t CreatePhotoOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                              sptr<IStreamCapture>& photoOutput) override;

    int32_t CreatePreviewOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                                sptr<IStreamRepeat>& previewOutput) override;

    int32_t CreateCustomPreviewOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format, int32_t width,
                                      int32_t height, sptr<IStreamRepeat>& previewOutput) override;

    int32_t CreateVideoOutput(const sptr<OHOS::IBufferProducer> &producer, int32_t format,
                              sptr<IStreamRepeat>& videoOutput) override;
    int32_t SetListenerObject(const sptr<IRemoteObject> &object) override;

private:
    static inline BrokerDelegator<HCameraServiceProxy> delegator_;
};
} // namespace CameraStandard
} 

3. CameraService启动流程

3.1 CameraService启动入口

sa_main通过读取解析camera_service.xml, 把动态库libcamera_service.z.so加载到自身进程中来,从而将camera_service服务启动起
在系统起来的时候,通过下面的命令{/system/bin/sa_main", “/system/profile/camera_service.xml” }将camera_service拉去来

<info>
    <process>camera_service</process>
    <loadlibs>
        <libpath>libcamera_service.z.so</libpath>
    </loadlibs>
    <systemability>
       <name>3008</name>
       <libpath>libcamera_service.z.so</libpath>
       <run-on-create>true</run-on-create>
       <distributed>false</distributed>
       <dump-level>1</dump-level>
   </systemability>
</info>

OpenHarmony——CameraService服务启动流程分析-鸿蒙开发者社区

3.2 CameraService启动流程

由配置文件中path字段,配置的是去运行"/system/bin/sa_main"可执行程序,再通过sa_main里的DoStartSAProcess()根据/system/profile/camera_service.xml的描述,去加载libcamera_service.z.so,以此来切换到camera_server进程的上下文中运行

在DoStartSAProcess中完成SystemAbilityProfiles的初始化,然后调用ret = Run(saId)函数将服务拉起来

【foundation\distributedschedule\safwk\services\safwk\src\local_ability_manager.cpp】

bool LocalAbilityManager::Run(int32_t saId)
{
	...
    FindAndStartPhaseTasks();
	...
    return true;
}

在FindAndStartPhaseTasks中根据启动的类型,去启动每一段的任务,调用StartPhaseTasks

【foundation\distributedschedule\safwk\services\safwk\src\local_ability_manager.cpp】

void LocalAbilityManager::StartPhaseTasks(const std::list<SystemAbility*>& systemAbilityList)
{
    if (systemAbilityList.empty()) {
        return;
    }

    for (auto systemAbility : systemAbilityList) {
        if (systemAbility != nullptr) {
            HILOGD(TAG, "add phase task for SA:%{public}d", systemAbility->GetSystemAbilitId());
            std::lock_guard<std::mutex> autoLock(startPhaseLock_);
            ++startTaskNum_;
            auto task = std::bind(&LocalAbilityManager::StartSystemAbilityTask, this, systemAbility);
            pool_.AddTask(task);
        }
    }
...
}

通过bind函数去执行每一个SystemAbilityTask

【foundation\distributedschedule\safwk\services\safwk\src\local_ability_manager.cpp】

void LocalAbilityManager::StartSystemAbilityTask(SystemAbility* ability)
{
    if (ability != nullptr) {
        HILOGD(TAG, "StartSystemAbility is called for %{public}d", ability->GetSystemAbilitId());
        if (ability->GetDependSa().empty()) {
            ability->Start();
		}
...
}

进入start函数

【foundation\distributedschedule\safwk\services\safwk\src\system_ability.cpp】

void SystemAbility::Start()
{
	...
    OnStart();
	...
}

调用到实现服务的OnStart中

【foundation\multimedia\camera_standard\services\camera_service\src\hcamera_service.cpp】

void HCameraService::OnStart()
{
	...
    if (cameraHostManager_->Init() != CAMERA_OK) {
        MEDIA_ERR_LOG("HCameraService OnStart failed to init camera host manager.");
    }
    bool res = Publish(this);//调用父类的publish,即system_ability.cpp中的public
    if (res) {
        MEDIA_INFO_LOG("HCameraService OnStart res=%{public}d", res);
    }
...
}

调用cameraHostManager_->Init(),获取cameraHostProxy实例,完成相关的初始化,其实就是为了后面使用CameraHost做准备了

3.3 CameraService服务发布

后面调用Publish(this)将CameraService服务通过AddSystemAbility接口注册注册进SystemAbilityManager中

【foundation\distributedschedule\safwk\services\safwk\src\system_ability.cpp】

bool SystemAbility::Publish(sptr<IRemoteObject> systemAbility)
{
	...
    int32_t result = samgrProxy->AddSystemAbility(saId_, publishObj_, saExtra);
	...
}

至此CameraService服务就发布完成了

后面Camera Client就可以通过SystemAbilityManager的GetSystemAbility方法可获取到Camera_service的代理IRemoteObject,然后构造HCameraServiceProxy

4. 总结

1.相机组件的基本介绍以及CameraService在相机组件中的位置

2.介绍了CameraService的启动流程及服务的发布过程

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-8-11 17:02:14修改
5
收藏 1
回复
举报
3条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

楼主,图片好像挂掉了,方便补一下吗?

回复
2022-8-5 16:31:26
深开鸿
深开鸿 回复了 红叶亦知秋
楼主,图片好像挂掉了,方便补一下吗?

重新上传了

回复
2022-8-5 18:00:13
LoinDIci
LoinDIci

大佬能出一个camera设备驱动的教程吗

回复
2022-8-16 10:35:11
回复
    相关推荐