上一篇梳理了 CameraProvider 是独立服务、通过 v4l2 框架管理物理摄像头,本篇主要描述的是 CameraService 如何与 CameraProvider 通讯;
android 的 CameraService 是 Camera 子系统核心模块,Camera Api1 和 Api2 的接口、是如何与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::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>
¬ification) 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 通讯 篇专门梳理分析此部分内容。