IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 虚拟摄像头之六: 《详解 CameraService 都做了什么》之 CameraService 与 CameraProvider 通讯 -> 正文阅读

[移动开发]虚拟摄像头之六: 《详解 CameraService 都做了什么》之 CameraService 与 CameraProvider 通讯

前言

上一篇梳理了 CameraProvider 是独立服务、通过 v4l2 框架管理物理摄像头,本篇主要描述的是 CameraService 如何与 CameraProvider 通讯;
android 的 CameraService 是 Camera 子系统核心模块,Camera Api1 和 Api2 的接口、是如何与CameraService 通讯呢?笔者将分两篇来介绍。

CameraService 运行环境部署

首先看一下他的Android.mk 编译配置文件
@frameworks/av/camera/cameraserver/Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
  main_cameraserver.cpp

LOCAL_SHARED_LIBRARIES := \
  libcameraservice \
  liblog \
  libutils \
  libui \
  libgui \
  libbinder \
  libhidltransport \
  android.hardware.camera.common@1.0 \
  android.hardware.camera.provider@2.4 \
  android.hardware.camera.device@1.0 \
  android.hardware.camera.device@3.2

LOCAL_MODULE:= cameraserver

LOCAL_32_BIT_ONLY := true
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter
LOCAL_INIT_RC := cameraserver.rc
include $(BUILD_EXECUTABLE)

编译生成的是可执行文件,它依赖的库文件 libcameraservice 就是 CameraService 生成的库;
依赖的 libbinder 库就是与 libcamera_client.so 通讯使用的库文件;
依赖的 android.hardware.camera.provider@2.4 库是与 CameraProvider 通讯使用的库文件.

他的入口函数在哪里呢?

@frameworks/av/camera/cameraserver/main_cameraserver.cpp

#define LOG_TAG "cameraserver"
//#define LOG_NDEBUG 0
#include "CameraService.h"
#include <hidl/HidlTransportSupport.h>

using namespace android;

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();
}

什么时候启动这个服务的呢?

@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

此文件中定义了 cameraserver 服务名称,启动位置在 servicemanager.rc 文件中,笔者开发板文件路径:
@frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver                //> 启动声卡
    onrestart restart media
    onrestart restart surfaceflinger             
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver               //> 启动 cameraserver 服务
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

我们清楚知道 cameraserver 入口函数,以及系统什么时候开启这个服务。当服务启动时执行 CameraService::instantiate();方法是cameraserver 继承 BinderService 类的instantiate方法,他的定义如下: @frameworks/native/include/binder/BinderService.h

namespace android {
template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

    static void publishAndJoinThreadPool(bool allowIsolated = false) {
        publish(allowIsolated);
        joinThreadPool();
    }

    static void instantiate() { publish(); }

    static status_t shutdown() { return NO_ERROR; }

private:
    static void joinThreadPool() {
        sp<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        ps->giveThreadPoolName();
        IPCThreadState::self()->joinThreadPool();
    }
};

};

addService 方法申明如下:

virtual status_t            addService( const String16& name,
                                            const sp<IBinder>& service,
                                            bool allowIsolated = false) = 0;

在 main_cameraserver.cpp 中, 执行 CameraService::instantiate(); 调用是继承类BinderService的 instantiate() 函数,该函数调用 publish(); ==> sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);BinderService 提供了 Service 的创建和发布;

而 new SERVICE() 就是 new 一个 CameraService 对象、该对象返回值被 const sp& service 引用, CameraService构造函数内容如下:

CameraService::CameraService() :
        mEventLog(DEFAULT_EVENT_LOG_LENGTH),
        mNumberOfCameras(0), mNumberOfNormalCameras(0),
        mSoundRef(0), mInitialized(false) {
    ALOGI("CameraService started (pid=%d)", getpid());

    this->camera_device_status_change = android::camera_device_status_change;
    this->torch_mode_status_change = android::torch_mode_status_change;

    mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}

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

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");
    //> 1. 继承 BnCameraService 类
    BnCameraService::onFirstRef();

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

    status_t res = INVALID_OPERATION;
    //> 2. CameraProvider 服务
    res = enumerateProviders();
    if (res == OK) {
        mInitialized = true;
    }
    //> 3. 激活 media.camera.proxy 服务
    CameraService::pingCameraServiceProxy();
}

该方法中调用 res = enumerateProviders() 函数,此函数就是 CameraService 与 CameraProvider 通讯关联的入口函数。

CameraService 如何与 CameraProvider 通讯

在 CameraService::onFirstRef 中调用 enumerateProviders() ,代码内容如下:

status_t CameraService::enumerateProviders() {
    status_t res;
    Mutex::Autolock l(mServiceLock);

    if (nullptr == mCameraProviderManager.get()) {
        mCameraProviderManager = new CameraProviderManager();
        res = mCameraProviderManager->initialize(this);
        if (res != OK) {
            ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
                    __FUNCTION__, strerror(-res), res);
            return res;
        }
    }

    mNumberOfCameras = mCameraProviderManager->getCameraCount();
    mNumberOfNormalCameras =
            mCameraProviderManager->getAPI1CompatibleCameraCount();

    // Setup vendor tags before we call get_camera_info the first time
    // because HAL might need to setup static vendor keys in get_camera_info
    // TODO: maybe put this into CameraProviderManager::initialize()?
    mCameraProviderManager->setUpVendorTags();

    if (nullptr == mFlashlight.get()) {
        mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
    }

    res = mFlashlight->findFlashUnits();
    if (res != OK) {
        ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
    }

    for (auto& cameraId : mCameraProviderManager->getCameraDeviceIds()) {
        String8 id8 = String8(cameraId.c_str());
        bool cameraFound = false;
        {

            Mutex::Autolock lock(mCameraStatesLock);
            auto iter = mCameraStates.find(id8);
            if (iter != mCameraStates.end()) {
                cameraFound = true;
            }
        }

        if (!cameraFound) {
            hardware::camera::common::V1_0::CameraResourceCost cost;
            res = mCameraProviderManager->getResourceCost(cameraId, &cost);
            if (res != OK) {
                ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
                continue;
            }
            std::set<String8> conflicting;
            for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
                conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
            }

            {
                Mutex::Autolock lock(mCameraStatesLock);
                mCameraStates.emplace(id8,
                    std::make_shared<CameraState>(id8, cost.resourceCost, conflicting));
            }
        }

        onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);

        if (mFlashlight->hasFlashUnit(id8)) {
            mTorchStatusMap.add(id8, TorchModeStatus::AVAILABLE_OFF);
        }
    }

    return OK;
}

首先将 new CameraProviderManager() 实例化,然后调用 initialize() 接口将其初始化,传入的参数是 this 指针,指向当前 CameraService 实例的地址。 initialize 在分析具体实现之前,可以先看看它在头文件中的声明:

class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification {

    struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
        virtual bool registerForNotifications(
                const std::string &serviceName,
                const sp<hidl::manager::V1_0::IServiceNotification>
                &notification) override {
            return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
                    serviceName, notification);
        }

        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                const std::string &serviceName) override {
            return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
        }

    };

    static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;

/**
     * 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);
}

用于初始化管理器,并给它设置一个状态监听 (即 CameraService 实例), 选择性地接受一个与服务交互的代理。
默认的代理通过 Hardware 服务管理器进行通信,在创建 HardwareServiceInteractionProxy 代理时执行了hardware:📷:provider::V2_4::ICameraProvider::getService(serviceName);也就开启了 ICameraProvider 对象构建过程,实现 cameraServer 与 CameraProvider 之间关联。


const std::string kLegacyProviderName("legacy/0");

status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
        ServiceInteractionProxy* proxy) {
    std::lock_guard<std::mutex> lock(mInterfaceMutex);
    if (proxy == nullptr) {
        ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
        return BAD_VALUE;
    }
    mListener = listener;
    mServiceProxy = proxy;

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

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

    return OK;
}

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

status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    //> 检查已知的 Provider 中是否已有名为 legacy/0 的。
    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;
        }
    }

    //> 根据 legacy/0 从服务代理处获取 CameraProvider 接口,getService("legacy/0") 触发CameraProvider的响应接口
    //> 由上一篇《谁在调用 v4l2_camera_HAL 摄像头驱动》 中,我们知道该接口是CameraProvider构建函数,返回ICameraProvider对象。
    sp<provider::V2_4::ICameraProvider> interface;
    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;
        }
    }

    //> 通过 ProviderInfo 来保存当前 Provider 相关信息。
    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this);
    status_t res = providerInfo->initialize();
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo);

    return OK;
}

这个函数主要作用是将找到的这个 Provider 通过 ProviderInfo 记录下来并初始化,并再次执行通过接口代理 执行 getService(),这儿就实现了camera service与camera provider的桥接了;

CameraProviderManager中提供了一个ProviderInfo来保存Camera provider信息,方便管理camera service调用 camera provider,下面分析一下ProviderInfo是怎么样的?源码路径在 CameraProviderManager.h 文件中,是 CameraProviderManager 类的子类内容;

struct ProviderInfo :
            virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
            virtual public hardware::hidl_death_recipient
    {
        const std::string mProviderName;
        const sp<hardware::camera::provider::V2_4::ICameraProvider> mInterface;
        const metadata_vendor_id_t mProviderTagid;

        //> 构建函数中关联服务名称、ICameraProvider 和 CameraProviderManager 之间对应关系
        ProviderInfo(const std::string &providerName,
                sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
                CameraProviderManager *manager);
        ~ProviderInfo();

        status_t initialize();

        const std::string& getType() const;

        status_t addDevice(const std::string& name,
                hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
                /*out*/ std::string *parsedId = nullptr);

        status_t dump(int fd, const Vector<String16>& args) const;

        // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
        virtual hardware::Return<void> cameraDeviceStatusChange(
                const hardware::hidl_string& cameraDeviceName,
                hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
        virtual hardware::Return<void> torchModeStatusChange(
                const hardware::hidl_string& cameraDeviceName,
                hardware::camera::common::V1_0::TorchModeStatus newStatus) override;

        // hidl_death_recipient interface - this locks the parent mInterfaceMutex
        virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;

        // Basic device information, common to all camera devices
        struct DeviceInfo {
            const std::string mName;  // Full instance name
            const std::string mId;    // ID section of full name
            const hardware::hidl_version mVersion;
            const metadata_vendor_id_t mProviderTagid;

            const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;

            hardware::camera::common::V1_0::CameraDeviceStatus mStatus;

            bool hasFlashUnit() const { return mHasFlashUnit; }
            virtual status_t setTorchMode(bool enabled) = 0;
            virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
            virtual bool isAPI1Compatible() const = 0;
            virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
                (void) characteristics;
                return INVALID_OPERATION;
            }

            DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
                    const std::string &id, const hardware::hidl_version& version,
                    const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
                    mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
                    mResourceCost(resourceCost),
                    mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
                    mHasFlashUnit(false) {}
            virtual ~DeviceInfo();
        protected:
            bool mHasFlashUnit;

            template<class InterfaceT>
            static status_t setTorchMode(InterfaceT& interface, bool enabled);
        };

ProviderInfo继承了 hardware:📷:provider::V2_4::ICameraProviderCallback 与 hardware::hidl_death_recipient;
ICameraProviderCallback 是 cameraProvider的 回调接口,hardware::hidl_death_recipient 是hal层的死亡回调接口,方便在底层死亡的时候通知上层。
cameraDeviceStatusChange 与 torchModeStatusChange 都是 ICameraProviderCallback 的回调函数,当camera provider发生变化的时候需要通知上层这些变化。

status_t CameraProviderManager::ProviderInfo::initialize() {
    status_t res = parseProviderName(mProviderName, &mType, &mId);
    if (res != OK) {
        ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
        return BAD_VALUE;
    }
    ALOGI("Connecting to new camera provider: %s, isRemote? %d",
            mProviderName.c_str(), mInterface->isRemote());
    hardware::Return<Status> status = mInterface->setCallback(this);
    if (!status.isOk()) {
        ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), status.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to register callbacks with camera provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
    if (!linked.isOk()) {
        ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    } else if (!linked) {
        ALOGW("%s: Unable to link to provider '%s' death notifications",
                __FUNCTION__, mProviderName.c_str());
    }

    // Get initial list of camera devices, if any
    std::vector<std::string> devices;
    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]);
            }
        } });
    if (!ret.isOk()) {
        ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
                __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
        return DEAD_OBJECT;
    }
    if (status != Status::OK) {
        ALOGE("%s: Unable to query for camera devices from provider '%s'",
                __FUNCTION__, mProviderName.c_str());
        return mapToStatusT(status);
    }

    sp<StatusListener> listener = mManager->getStatusListener();
    for (auto& device : devices) {
        std::string id;
        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;
        }
    }

    for (auto& device : mDevices) {
        mUniqueCameraIds.insert(device->mId);
        if (device->isAPI1Compatible()) {
            mUniqueAPI1CompatibleCameraIds.insert(device->mId);
        }
    }
    mUniqueDeviceCount = mUniqueCameraIds.size();

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

    return OK;
}

initialize 函数的主要作用是初始化cameraProvider,并且IPC调用到cameraProvider 获取camera device信息,然后调用 addDevice接口将获取的camera device保存在cameraService中,防止多次跨进程调用。

至此、回答第一个问题 CameraService 如何与 CameraProvider 通讯,是通过 CameraProviderManager管理 cameraService 与 cameraProvider 间通信;

因第二个问题涉及到 Binder IPC 通讯相关内容较多、所以另外开启一篇续《详解 CameraService 都做了什么》之 CameraService 与 cameraclient 通讯 篇专门梳理分析此部分内容。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:17:25  更:2022-08-19 19:20:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:24:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码