【定制Android系统】Android O Camera(1)——简单梳理 Camera1 的 setParameters 通路.1

需求:最近在做一个 Camera 相关的项目,最简单粗暴的一个目的就是使用 C++ 开发。也就是说,作为 System/Framework 层,我们需要把 Android 的 Camera 系统封装出一套 C++ 接口,以供 SDK/Application 调用,使得 SDK/Application 可以直接使用 C++ 开发,以便更高效地加入 AI 相关的算法。
那么,打开 Camera,设置相关参数,就是必不可少的接口。网上关于 Camera 的 Open 流程有较多的参考。这里就不赘述了。只写一下,最近在看的,关于 Camera 的参数,是如何从 Android Runtime 层设置到 硬件的 Camera 设备上的。

封装出自己的 Camera 参数 get/set 接口

一般应用直接调用 Camera.java 相关的接口,即可实现 Camera 的各种功能。当需要使用 C++ 进行 Android Camera 开发时,就需要我们从 Camera 的架构中找到一个切入点,把相关的代码封装出来。参考Camera 基本架构这篇文章中的架构图:
这里写图片描述
我们应该模仿 Android Runtime,调用 Camera.cpp 中的相关函数,实现功能,并封装出接口。

而对于 Camera 的相关参数,例如,分辨率、帧率、数据格式等,则通过 Camera.cpp 中的两个方法 String8 Camera::getParameters() conststatus_t Camera::setParameters(const String8& params)

class CameraParameters

这里需要借助另一个类 CameraParameters
这个类好比一个名片,或者一本手册。里面记录了一个 Camera 应有的所有参数的 key/value 对。
该类的最主要的一个方法是构造函数 CameraParameters(const String8 &params) { unflatten(params); }。它可以配合 Camera.cpp 中的 getParameters() 使用,构建一个 CameraParameters 类对象。
另两个最主要的方法就是构造函数中的 void unflatten(const String8 &params) 以及 String8 flatten() const
flatten 方法主要是把 CameraParameters 类记载着的 key/value 对变成符合要求的 String8 字符串。 而 unflatten 则是把符合要求的 String8 字符串转换成 CameraParameters 类中的各个 key/value 对。

所以,一般来说,获取、设置摄像头参数一般可以写成如下形式(以获取、设置分辨率为例):

sp <Camera> mCamera = Camera::open(....) 
CameraParameters* cp = new CameraParameters(mCamera->getParameters());
int w, h;
cp->getPreviewSize(w, h);
w = 1920;
h = 1080;
cp->setPreviewSize(w, h);
mCamera->setParameters(cp->flatten());

也就是拿这本手册从实体设备上获取所有参数并且记录下来,通过手册的相关方法修改参数的某些具体的值,然后再把这本手册化身为字符串通过设备设置进去。

如果添加一个自定义的参数该如何

如果只是使用普通 Camera,完成一些简单的参数设置、获取功能的话,如果项目又很紧张,估计也就看到此为止了。估计以后出了 Bug 会继续深究一些。
但是项目里面有些需求,需要设置一些普通 Camera 没有的参数,也就是自定义的 Camera 的自定义的参数。那该怎么做呢?
最简单粗暴的想法就是直接在 CameraParameters 中添加相应的 key/value 对,然后利用既有的通路让它直达 HAL 层。但是,这种想法充满了不确定性。不知道这条既有的通路上,这些键值对是怎样一步一步走下去的。为了弄清楚这个问题。于是开始了梳理方法 setParameters 的过程。

从 Camera.cpp 到 CameraDevice.cpp

为了弄清楚 setParameters 的通路,我们首先要理清楚这一坨坨的 Camera 相关类的相互继承的关系。

Camera 相关类的继承关系

首先,我们可以看到,Camera 类的 setParameters这么写的:

// frameworks/av/camera/Camera.cpp

status_t Camera::setParameters(const String8& params)
{
    ALOGV("setParameters");
    sp <::android::hardware::ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    return c->setParameters(params);
}

也就是,把 Camera 类转成 ICamera 类然后调用 ICamera 类的 setParameters 方法的。而 ICamera 类是个接口类,没有任何实现。那么,是谁继承自 ICamera 类并且实现了 setParameters 方法呢?
我们先看 ICamera 类的头文件

// /frameworks/av/camera/include/camera/android/hardware/ICamera.h

namespace android {
namespace hardware {
class ICameraClient;

class ICamera: public android::IInterface
{
public:
    virtual status_t setParameters() const = 0;
};

class BnCamera: public android::BnInterface<ICamera>
{
public:
    virtual status_t    onTransact( ... );
};

} // namespace hardware
} // namespace android

我们记下 class BnCamera: public android::BnInterface<ICamera>再找 BnInterface 类的定义,看 IInterface头文件

class IInterface : public virtual RefBase
{
public:
        IInterface();
        static sp<IBinder>  asBinder(const IInterface*);
        static sp<IBinder>  asBinder(const sp<IInterface>&);
    ...
};

// ---------------------------------------------------------------------

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    ....
};

由此可见,class BnCamera: public android::BnInterface<ICamera> 相当于,class BnCamera : public ICamera?。
继续找,是谁继承了 BnCamera 类,然后我们就找到了 CameraService 类的头文件,它是这么写的:

// /frameworks/av/services/camera/libcameraservice/CameraService.h

namespace android {

class CameraSercie :
    public BinderService<CameraService>,
    public virtual ::android::hardware::BnCameraService,
    public virtual IBinder::DeathRecipient,
    public camera_module_callbacks_t,
    public virtual CameraProviderManager::StatusListener
{
    friend class BinderService<CameraService>;
    friend class CameraClient;
public:
    class Client;
    class BasicClient;

    class BasicClient : public virtual RefBase 
    {
    public:
        .....

    class Client : public hardware::BnCamera, public BasicClient
    {
    public:
        typedef hardware::ICameraClient TCamCallbacks;

        // ICamera interface (see ICamera for details)
        virtual status_t setParameters(const String8& params) = 0;
    };

    class ClientEventListener {

    };

    class CameraStatus {
    public:

    }
};
}

CameraService 类的内部类 Client 继承自 BnCamera 类。
当我们继续向下找,就会发现,CameraClient 类继承自CameraService 类的内部类 Client。其头文件如下:

// /frameworks/av/services/camera/libcameraservice/api1/CameraClient.h
namespace android {

class CameraHardwareInterface;

class CameraClient : public CameraService::Client
{
public:
    // ICamera interface (see ICamera for details)
    virtual status_t setParameters(const String8& params);

    CameraClient(const sp<CameraService>& cameraService,
            const sp<hardware::ICameraClient>& cameraClient,
            int camraId,
            int cameraFacing,
            int clientPid,
            int clientUid,
            int servicePid,
            bool legacyMode = false);
private:
    sp<CameraHardwareInterface>     mHardware;   // cleared after disconnect()
    CameraParameters                mLatestSetParameters;
};

}

而它的源文件则定义了 setParameters 的具体实现

// /frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
status_t CameraClient::setParameters(const String8& params) {
    mLatestSetParameters = CameraParameters(params);
    CameraParameters p(params);
    return mHardware->setParameters(p);
}

mHardware 的声明,我们找到 CameraHardwareInterface 类。其头文件如下:

// /frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h

namespace android {

class CamerahardwareInterface :
    public virtual RefBase,
    public virtual hardware::camera::device::v1_0::ICameraDeviceCallback,
    public virtual hardware::camera::device::v1_0::ICameraDevicePreviewCallback {\
public:
    explicit CameraHardwareInterface(const char *name):
        mHidlDevice(nullptr),
        mName(name),
        mPreviewScalingMode(NOT_SET),
        mPreviewTransfrom(NOT_SET),
        mPreviewWidth(NOT_SET),
        mPreviewHeight(NOT_SET),
        mPreviewUsage(0),
        mPreviewSwapInterval(NOT_SET),
        mPreviewCrop{NOT_SET,NOT_SET,NOT_SET,NOT_SET}
    {
    }

    status_t setParameters(const CamreaParameters &params);

private:
    sp<hardware::camera::device::V1_0::ICameraDevice>   mHidlDevice;
};

}

其源文件中关于 setParameters 的具体实现如下:

// /frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp

status_t CameraHardwareInterface::setParameters(const CameraParameters &params)
{
    ALOGV("%s(%s)", __FUNCTION__, mName.string());
    if (CC_LIKELY(mHidlDevice != nullptr)) {
        return CameraProviderManager::mapToStatusT(
            mHidlDevice->setParameters(params.flatten().string()));
    }
    return INVALID_OPERATION;
}

很自然地,我们顺着找到了 CameraDevice_1_0.hCameraDevice.cpp。它们关于 setParameters 的相关代码如下:

hardware/interfaces/camera/device/1.0/default/CameraDevice_1_0.h

namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V1_0 {
namespace implementation {

using ::android::hardware::camera::device::V1_0::ICameraDevice

struct CameraDevice : public ICameraDevice {
    Return<Status> setParameters(const hidl_string& params) override;

private:
    struct CameraMemory : public camera_memory_t {
        MemoryId mId;
        CameraDevice* mDevice;
    };

    const std::string mCameraId;
    int mCameraIdInt;

    camera_device_t* mDevice = nullptr;
};


}  // namespace implementation
}  // namespace V1_0
}  // namespace device
}  // namespace camera
}  // namespace hardware
}  // namespace android



hardware/interfaces/camera/device/1.0/default/CameraDevice.cpp

#include "CameraDevice_1_0.h"

namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V1_0 {
namespace implementation {

Status CameraDevice::getHidlStatus(const int& status) {
    switch (status) {
        case 0: return Status::OK;
        case -ENOSYS  : return Status::OPERATION_NOT_SUPPORTED;
        case -EBUSY   : return Status::CAMERA_IN_USE;
        case -EUSERS  : return Status::MAX_CAMERAS_IN_USE;
        case -ENODEV  : return Status::INTERNAL_ERROR;
        case -EINVAL  : return Status::ILLEGAL_ARGUMENT;
        default:
            return Status::INTERNAL_ERROR;
    }
}

Return<Status> CameraDevice::open(const sp<ICameraDeviceCallback>& callback) {
    int rc = OK;
    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&
        info.device_version > CAMREA_DEVICE_API_VERSION_1_0) {
        // Open higher version camera device as HAL1.0 device.
        rc = mModule->openLegacy(mCameraId.c_str(),
                                CAMERA_DEVICE_API_VERSION_1_0,
                                (hw_device_t **)&mDevice);
    } else {
        rc = mModule->open(mCameraId.c_str(), (hw_device_t **)&mDevice);
    }
}

Return<Status> CameraDevice::setParameters(const hidl_string& params) {
    if (!mDevice) {
        return Status::OPERATION_NOT_SUPPORTED;
    }
    if (mDevice->ops->set_parameters) {
        return getHidlStatus(mDevice->ops->set_parameters(mDevice, params.c_str()));
    }
    return Status::ILLEGAL_ARGUMENT;
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace device
}  // namespace camera
}  // namespace hardware
}  // namespace android

由此看来,setParameters 好像从此进入 HAL 层,与真实设备直接交互了,然而通过打印 LOG 发现。事情并没有这么简单。

预知后事如何,且听下回分解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深海Enoch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值