CameraService 的起点需要从 init.rc 说起。解析 init.rc 脚本是在 init.cpp 入口方法 main 中开始解析的。mediaserver 服务进程随即就会启动。
system/core/rootdir/init.rc
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
经过分析可知,mediaserver 执行程序位于 main_mediaserver.cpp 中。调用 CameraService 类 instantiate() 启动了相机服务。
frameworks/av/media/mediaserver/main_mediaserver.cpp
using namespace android;
int main(int argc __unused, char** argv)
{
signal(SIGPIPE, SIG_IGN);
char value[PROPERTY_VALUE_MAX];
bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
pid_t childPid;
if (doLog && (childPid = fork()) != 0) {
......
} else {
// all other services
......
CameraService::instantiate();
......
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
}
再来看一下对应的 mk 文件,果然编译为 EXECUTABLE 类型。BUILD_EXECUTABLE 会生成可执行二进制文件到 /system/bin/ 下。
frameworks/av/media/mediaserver/Android.mk
LOCAL_PATH:= $(call my-dir)
......
LOCAL_SRC_FILES:= \
main_mediaserver.cpp
......
LOCAL_MODULE:= mediaserver
LOCAL_32_BIT_ONLY := true
include $(BUILD_EXECUTABLE)
CameraService 类 instantiate() 实际继承自 BinderService。instantiate() 方法内部调用了 publish() 方法。这里将 CameraService 服务注册到了“总管” ServiceManager 中。对应的查询名称是通过 CameraService::getServiceName() 方法获取的,这个方法返回了 “media.camera”。我们从 Java 层查询的服务正是 Native 注册的相机服务。
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 instantiate() { publish(); }
......
};
}; // namespace android
// ---------------------------------------------------------------------------
再看 CameraService 类定义,就不难理解上面描述的内容了,BinderService 是一个模板类。这里其 SERVICE 对应的就是 CameraService。
frameworks/av/services/camera/libcameraservice/CameraService.h
class CameraService :
public BinderService<CameraService>,
public BnCameraService,
public IBinder::DeathRecipient,
public camera_module_callbacks_t
{
friend class BinderService<CameraService>;
public:
......
// Implementation of BinderService<T>
static char const* getServiceName() { return "media.camera"; }
......
}
CameraService 构造函数中没干什么大事,初始化了一些成员变量。
frameworks/av/services/camera/libcameraservice/CameraService.cpp
static CameraService *gCameraService;
CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
mSoundRef(0), mModule(0), mFlashlight(0) {
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
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);
}
onFirstRef() 属于其父类 RefBase,该函数在强引用 sp 新增引用计数时调用。延迟加载相机 HAL 模块。
- 加载相机 HAL 模块
- 初始化相机 HAL 模块
- 获取 camera 个数
- 查找闪光灯
- 初始化每个相机设备的状态
- 将 CameraService 注册到 CameraDeviceFactory
- ping CameraServiceProxy
frameworks/av/services/camera/libcameraservice/CameraService.cpp
void CameraService::onFirstRef()
{
ALOGI("CameraService process starting");
BnCameraService::onFirstRef();
// 如果服务正在重启,则更新电池寿命跟踪
BatteryNotifier& notifier(BatteryNotifier::getInstance());
notifier.noteResetCamera();
notifier.noteResetFlashlight();
// 加载相机 HAL 模块
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
if (err < 0) {
ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
logServiceError("Could not load camera HAL module", err);
mNumberOfCameras = 0;
return;
}
// 初始化相机 HAL 模块
mModule = new CameraModule(rawModule);
err = mModule->init();
if (err != OK) {
ALOGE("Could not initialize camera HAL module: %d (%s)", err,
strerror(-err));
logServiceError("Could not initialize camera HAL module", err);
mNumberOfCameras = 0;
delete mModule;
mModule = nullptr;
return;
}
ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
// 获取 camera 个数
mNumberOfCameras = mModule->getNumberOfCameras();
mNumberOfNormalCameras = mNumberOfCameras;
// 在我们第一次调用 get_camera_info 之前设置供应商标签,
// 因为 HAL 可能需要在 get_camera_info 中设置静态供应商密钥
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
setUpVendorTags();
}
mFlashlight = new CameraFlashlight(*mModule, *this);
// 查找闪光灯
status_t res = mFlashlight->findFlashUnits();
if (res) {
// impossible because we haven't open any camera devices.
ALOGE("Failed to find flash units.");
}
int latestStrangeCameraId = INT_MAX;
for (int i = 0; i < mNumberOfCameras; i++) {
String8 cameraId = String8::format("%d", i);
// 获取相机信息,填充 camera_info
struct camera_info info;
bool haveInfo = true;
status_t rc = mModule->getCameraInfo(i, &info);
if (rc != NO_ERROR) {
ALOGE("%s: Received error loading camera info for device %d, cost and"
" conflicting devices fields set to defaults for this device.",
__FUNCTION__, i);
haveInfo = false;
}
// 检查向后兼容性支持
if (haveInfo) {
if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) {
delete mModule;
mModule = nullptr;
return;
}
}
// Defaults to use for cost and conflicting devices
int cost = 100;
char** conflicting_devices = nullptr;
size_t conflicting_devices_length = 0;
// If using post-2.4 module version, query the cost + conflicting devices from the HAL
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) {
cost = info.resource_cost;
conflicting_devices = info.conflicting_devices;
conflicting_devices_length = info.conflicting_devices_length;
}
std::set<String8> conflicting;
for (size_t i = 0; i < conflicting_devices_length; i++) {
conflicting.emplace(String8(conflicting_devices[i]));
}
// 初始化每个相机设备的状态
{
Mutex::Autolock lock(mCameraStatesLock);
mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost,
conflicting));
}
if (mFlashlight->hasFlashUnit(cameraId)) {
mTorchStatusMap.add(cameraId,
ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
}
}
if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_1) {
mModule->setCallbacks(this);
}
// 将 CameraService 注册到 CameraDeviceFactory
CameraDeviceFactory::registerService(this);
// ping CameraServiceProxy
CameraService::pingCameraServiceProxy();
}
先来了解一下 camera_module_t,注释的非常详细。
hardware/libhardware/include/hardware/camera_common.h
typedef struct camera_module {
/**
* 摄像头模块的常用方法。 *必须*是 camera_module 的第一个成员
*/
hw_module_t common;
/**
* 返回通过相机模块可访问的相机设备的数量。
* 摄像机设备的编号从 0 到 N-1,其中 N 是这个调用返回的值。
* open() 的相机设备名称只是转换成字符串的数字。
*/
int (*get_number_of_cameras)(void);
/**
* 返回给定相机设备的静态相机信息。
*/
int (*get_camera_info)(int camera_id, struct camera_info *info);
/**
* 提供指向 HAL 模块的回调函数指针,以通知框架异步相机模块事件。
*/
int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
/**
* 获取查询供应商扩展元数据标签信息的方法。
* HAL 应该填写所有供应商标签操作方法,
* 或者如果未定义供应商标签,则保持 ops 不变。
*
* 这里使用的 vendor_tag_ops 结构定义在:
* system/media/camera/include/system/vendor_tags.h
*/
void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
/**
* 如果此摄像机 HAL 模块支持多个设备 HAL API 版本,则打开特定的旧摄像机 HAL 设备。
* 例如,如果相机模块同时支持 CAMERA_DEVICE_API_VERSION_1_0 和 CAMERA_DEVICE_API_VERSION_3_2 设备 API,
* 则框架可以调用此函数以将相机设备作为 CAMERA_DEVICE_API_VERSION_1_0 设备打开。
*/
int (*open_legacy)(const struct hw_module_t* module, const char* id,
uint32_t halVersion, struct hw_device_t** device);
/**
* 打开或关闭与给定相机 ID 相关联的闪光灯的手电筒模式。
* 如果操作成功,则 HAL 必须通过使用新状态调用 camera_module_callbacks.torch_mode_status_change() 来通知框架闪光灯状态。
*
*/
int (*set_torch_mode)(const char* camera_id, bool enabled);
/**
* 在成功调用相机 HAL 库之后,相机服务将在调用任何其他方法之前调用此方法。
* 如果不需要初始化,则 HAL 模块可以将其保留为 NULL。
*
*/
int (*init)();
/* 留作将来使用 */
void* reserved[5];
} camera_module_t;
加载相机 HAL 模块调用了标准方法 hw_get_module(…),入参是 CAMERA_HARDWARE_MODULE_ID,代表相机 HAL 模块 ID。这样就能获取到 hw_module_t 结构,由于 hw_module_t 是 camera_module_t 第一个成员,变相的我们就得到了 camera_module_t 结构。接着是初始化相机 HAL 模块的过程。首先将 camera_module_t 作为入参封装为 CameraModule,接着调用 CameraModule 类 init() 方法进行初始化。
为什么需要 CameraModule?从这个类的注释我们得到了答案。
CameraModule 是 HAL 相机模块的包装器类。此类包装从 HAL 返回的 camera_module_t,以提供包装的 get_camera_info 实现,CameraService 会生成一些在较旧的 HAL 上以较新的 HAL 版本定义的照相机特性的键。
CameraModule 类 init() 方法最终会调用 camera_module_t 结构中的 init() 方法进行初始化。
frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
CameraModule::CameraModule(camera_module_t *module) {
if (module == NULL) {
ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
assert(0);
}
mModule = module;
}
int CameraModule::init() {
ATRACE_CALL();
int res = OK;
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
mModule->init != NULL) {
ATRACE_BEGIN("camera_module->init");
res = mModule->init();
ATRACE_END();
}
mCameraInfoMap.setCapacity(getNumberOfCameras());
return res;
}
获取摄像头个数,实际上也是调用 CameraModule 类 getNumberOfCameras() 方法。不出意外调用 HAL camera_module_t 结构体中的 get_number_of_cameras() 方法实现。
frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
int CameraModule::getNumberOfCameras() {
int numCameras;
ATRACE_BEGIN("camera_module->get_number_of_cameras");
numCameras = mModule->get_number_of_cameras();
ATRACE_END();
return numCameras;
}
再来看查找闪光灯的实现。主要是调用 CameraFlashlight 类 findFlashUnits() 查找闪光灯。 CameraFlashlight 类的主要作用是给相机服务提供控制闪光灯的一个接口。
- 获取相机个数
- 创建 ModuleFlashControl 对象
- 调用 ModuleFlashControl 类 hasFlashUnit(…) 方法检查闪光灯组件是否存在
- 将 Camera 对应的闪光灯组件是否存在一起添加到 HasFlashlightMap 中
frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp
CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
const camera_module_callbacks_t& callbacks) :
mCameraModule(&cameraModule),
mCallbacks(&callbacks),
mFlashlightMapInitialized(false) {
}
status_t CameraFlashlight::findFlashUnits() {
Mutex::Autolock l(mLock);
status_t res;
// 1.获取相机个数
int32_t numCameras = mCameraModule->getNumberOfCameras();
mHasFlashlightMap.clear();
mFlashlightMapInitialized = false;
for (int32_t i = 0; i < numCameras; i++) {
bool hasFlash = false;
String8 id = String8::format("%d", i);
// 2.创建 ModuleFlashControl 对象
res = createFlashlightControl(id);
if (res) {
ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
id.string());
} else {
res = mFlashControl->hasFlashUnit(id, &hasFlash);
if (res == -EUSERS || res == -EBUSY) {
ALOGE("%s: failed to check if camera %s has a flash unit. Some "
"camera devices may be opened", __FUNCTION__,
id.string());
return res;
} else if (res) {
ALOGE("%s: failed to check if camera %s has a flash unit. %s"
" (%d)", __FUNCTION__, id.string(), strerror(-res),
res);
}
mFlashControl.clear();
}
// 3.添加到 HasFlashlightMap 中
mHasFlashlightMap.add(id, hasFlash);
}
mFlashlightMapInitialized = true;
return OK;
}
createFlashlightControl(…) 方法中主要创建了 ModuleFlashControl 对象。
frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp
status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
cameraId.string());
if (mFlashControl != NULL) {
return INVALID_OPERATION;
}
status_t res = OK;
if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
if (mFlashControl == NULL) {
ALOGV("%s: cannot create flash control for module api v2.4+",
__FUNCTION__);
return NO_MEMORY;
}
} else {
......
}
return OK;
}
- 获取 camera_info
- 从 CameraMetadata 中查找是否存在闪光灯组件
frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp
status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
if (!hasFlash) {
return BAD_VALUE;
}
*hasFlash = false;
Mutex::Autolock l(mLock);
camera_info info;
status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
&info);
if (res != 0) {
return res;
}
CameraMetadata metadata;
metadata = info.static_camera_characteristics;
camera_metadata_entry flashAvailable =
metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
*hasFlash = true;
}
return OK;
}
现在是时候分析获取相机信息了,实际为填充 camera_info 结构。主要调用了 HAL camera_module_t 结构体中的 get_camera_info(…) 方法实现。
frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
ATRACE_CALL();
Mutex::Autolock lock(mCameraInfoLock);
if (cameraId < 0) {
ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
return -EINVAL;
}
// 仅为 API2 设备覆盖 static_camera_characteristics
int apiVersion = mModule->common.module_api_version;
if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
int ret;
ATRACE_BEGIN("camera_module->get_camera_info");
ret = mModule->get_camera_info(cameraId, info);
ATRACE_END();
return ret;
}
ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
if (index == NAME_NOT_FOUND) {
// 从 raw 模块获取相机信息并缓存它
camera_info rawInfo, cameraInfo;
ATRACE_BEGIN("camera_module->get_camera_info");
int ret = mModule->get_camera_info(cameraId, &rawInfo);
ATRACE_END();
if (ret != 0) {
return ret;
}
int deviceVersion = rawInfo.device_version;
if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
// static_camera_characteristics is invalid
*info = rawInfo;
return ret;
}
CameraMetadata m;
m = rawInfo.static_camera_characteristics;
deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
cameraInfo = rawInfo;
cameraInfo.static_camera_characteristics = m.release();
index = mCameraInfoMap.add(cameraId, cameraInfo);
}
assert(index != NAME_NOT_FOUND);
// return the cached camera info
*info = mCameraInfoMap[index];
return OK;
}
最后来分析一下 将 CameraService 注册到 CameraDeviceFactory 和 ping CameraServiceProxy。CameraService 注册到 CameraDeviceFactory 中仅仅是做了一个赋值动作。
frameworks/av/services/camera/libcameraservice/CameraDeviceFactory.cpp
namespace android {
wp<CameraService> CameraDeviceFactory::sService;
......
void CameraDeviceFactory::registerService(wp<CameraService> service) {
ALOGV("%s: Registered service %p", __FUNCTION__,
service.promote().get());
sService = service;
}
}; // namespace android
最后来看 ping CameraServiceProxy 干了什么?
- 调用 getCameraServiceProxy() 获取 ICameraServiceProxy 代理对象
- 调用 ICameraServiceProxy.Stub.Proxy 类 pingForUserUpdate() 方法,实际由远端 CameraService Java 类中的成员 mCameraServiceProxy 中的 pingForUserUpdate() 方法实现
frameworks/av/services/camera/libcameraservice/CameraService.cpp
sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.camera.proxy"));
if (binder == nullptr) {
return nullptr;
}
sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder);
return proxyBinder;
}
void CameraService::pingCameraServiceProxy() {
sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
if (proxyBinder == nullptr) return;
proxyBinder->pingForUserUpdate();
}
pingForUserUpdate() 内部又调用了 CameraService 类 notifySwitchWithRetries(…) 方法。主要是为了完成将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。
frameworks/base/services/core/java/com/android/server/camera/CameraService.java
public class CameraService extends SystemService {
......
private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
@Override
public void pingForUserUpdate() {
notifySwitchWithRetries(30);
}
......
};
......
private void notifySwitchWithRetries(int retries) {
synchronized(mLock) {
if (mEnabledCameraUsers == null) {
return;
}
// 将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。
if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
retries = 0;
}
}
if (retries <= 0) {
return;
}
Slog.i(TAG, "Could not notify camera service of user switch, retrying...");
// 无法通知相机服务的用户切换,30ms 后重试...
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null),
RETRY_DELAY_TIME);
}
......
}
handleMessage(…) 方法中再次调用 notifySwitchWithRetries(…) 进行了重试。
frameworks/base/services/core/java/com/android/server/camera/CameraService.java
public class CameraService extends SystemService {
......
@Override
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MSG_SWITCH_USER: {
notifySwitchWithRetries(msg.arg1);
} break;
default: {
Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
} break;
}
return true;
}
......
}
后面继续分析 Camera HAL 中如何实现 camera_module_t 结构体中的函数指针。我们以 moto Nexus 6 device/moto/shamu/camera/QCamera2/ 为例进行分析。