本文已参加「新人创造礼」活动, 一同开启创造之路。

需求:最近在做一个 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系统】Android O Camera(1)——简单梳理 Camera1 的 setParameters 通路.1
咱们应该仿照 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() constflatten办法主要是把 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 发现。工作并没有这么简略。

预知后事怎么,且听下回分解。