之前已经分析了从 App 到 CameraService 的连路创建流程,接下来要分析的是从 CameraService 到 HAL Service 的连接过程。
由于 Android O 中加入了 Treble 机制,它带来的一个巨大变化就是将原本的 CameraServer
进程分隔成 CameraServer
与 Provider service
两个进程,它们之间通过 HIDL(一个类似 Binder 的机制)进行通信。
在这种情况下,CameraServer
一端主体为 CameraService,它将会寻找现存的 Provider service
,将其加入到内部的 CameraProviderManager 中进行管理,相关操作都是通过远端调用进行的。
而 Provider service
一端的主体为 CameraProvider,它在初始化时就已经连接到 libhardware
的 Camera HAL 实现层,并以 CameraModule 来进行管理。
这两个进程的启动与初始化是在系统启动时就进行的,相关的分析可以参照我的另一篇博文。
进程的启动后,连路的 “载体” 就搭建完成了(需要注意,此时 QCamera3HWI 还未创建),可用下图简单表示。
(我之前的博文中没有分析远端 CameraDevice 的创建,但这个类确实需要注意,因为它是连接到 HAL 接口层的中介。)
而在打开相机时,该层的完整连路会被创建出来。
上回讲到,在 CameraService::makeClient
中,实例化了一个 CameraDeviceClient。现在我们就从它的构造函数开始,继续探索打开相机的流程。
这一部分主要活动在 Runtime
层,这里分成 CameraService 与 HAL Service 两侧来分析。
文件路径:frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp
先来看看它的构造函数,主要注意第 9、10 行,关于它的父类 Camera2ClientBase 的构造,这是创建连路的一个关键节点。在下一个小节会对它进行分析。
CameraDeviceClient::CameraDeviceClient(const sp& cameraService,
const sp& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0),
mPrivilegedClient(false) {
char value[PROPERTY_VALUE_MAX];
property_get("persist.camera.privapp.list", value, "");
String16 packagelist(value);
if (packagelist.contains(clientPackageName.string())) {
mPrivilegedClient = true;
}
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
CameraService 在创建 CameraDeviceClient 之后,会调用它的初始化函数:
initialize
。TProviderPtr
在此处即是 CameraProviderManager 类。status_t CameraDeviceClient::initialize(sp manager) {
return initializeImpl(manager);
}
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
ATRACE_CALL();
status_t res;
res = Camera2ClientBase::initialize(providerPtr);
if (res != OK) {
return res;
}
String8 threadName;
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
mFrameProcessor->run(threadName.string());
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
return OK;
}
文件路径:frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp
先来看构造函数:
TClientBase
,在 CameraDeviceClient 继承 Camera2ClientBase 时被指定为 CameraDeviceClientBase。TCamCallbacks
在 CameraDeviceClientBase 中被指定为了 ICameraDeviceCallbacks。template <typename TClientBase>
Camera2ClientBase::Camera2ClientBase(
const sp& cameraService,
const sp& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
mDevice = new Camera3Device(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
再来看看初始化函数:
initializeImpl
中。TClientBase
对应 CameraDeviceClientBase,而 TProviderPtr
对应的是 CameraProviderManager。startCameraOps
方法,检查 ops 的权限。template <typename TClientBase>
status_t Camera2ClientBase::initialize(sp manager) {
return initializeImpl(manager);
}
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase::initializeImpl(TProviderPtr providerPtr) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
TClientBase::mCameraIdStr.string());
status_t res;
// Verify ops permissions
res = TClientBase::startCameraOps();
if (res != OK) {
return res;
}
if (mDevice == NULL) {
ALOGE("%s: Camera %s: No device connected",
__FUNCTION__, TClientBase::mCameraIdStr.string());
return NO_INIT;
}
res = mDevice->initialize(providerPtr);
if (res != OK) {
ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
wp weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
文件路径:frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp
观察构造函数,注意第 18、19 行设定了两个回调接口。
Camera3Device::Camera3Device(const String8 &id):
mId(id),
mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mTimestampOffset(0),
mNextResultFrameNumber(0),
mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mListener(NULL),
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
{
ATRACE_CALL();
camera3_callback_ops::notify = &sNotify;
camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}
其初始化函数篇幅较长,这里省略掉了关于 RequestMetadataQueue 的相关操作。我们需要关注的是,在初始化时,调用了 CameraProviderManager 的 openSession
方法(第 13~21 行),开启了远端的 Session。
status_t Camera3Device::initialize(sp manager) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
if (manager == nullptr) return INVALID_OPERATION;
sp session;
ATRACE_BEGIN("CameraHal::openSession");
status_t res = manager->openSession(mId.string(), this,
/*out*/ &session);
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
return res;
}
/* Do something in */
......
/* Do something out */
return initializeCommonLocked();
}
文件位置:frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp
来看看 openSession
是如何实现的:
findDeviceInfoLocked
,获取 HAL3 相关的 DeviceInfo3
,这个东西在服务启动与初始化的时候就已经创建出来,并保存下来了。open
方法,创建 CameraDeviceSession 实例并将其本地调用接口通过入参 session
返回。 (DeviceInfo3 这个类的 mInterface
成员类型是 ICameraDevice,通过它可以调用远端 CameraDevice 中的方法。)status_t CameraProviderManager::openSession(const std::string &id,
const sp& callback,
/*out*/
sp *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *deviceInfo3 = static_cast(deviceInfo);
Status status;
hardware::Return<void> ret;
ret = deviceInfo3->mInterface->open(callback, [&status, &session]
(Status s, const sp& cameraSession) {
status = s;
if (status == Status::OK) {
*session = cameraSession;
}
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
return mapToStatusT(status);
}
文件位置:hardware\interfaces\camera\device\3.2\default\CameraDevice.cpp
CameraDevice 的实例实际上在初始化 HAL Service 之后就存在了。
前面说到,通过 CameraProviderManager 中的 deviceInfo
接口,调用远端 CameraDevice 实例的 open
方法,下面就来看看它的代码实现:
mModule
是在 HAL Service 初始化时就已经配置好的,它对从 libhardware
库中加载的 Camera HAL 接口进行了一层封装。从这里往下就会一路走到 QCamera3HWI 的构造流程去,在这一章中暂时不进行分析。mSession
持有,具体实现的函数为 creatSession
。Return<void> CameraDevice::open(const sp& callback, open_cb _hidl_cb) {
Status status = initStatus();
sp session = nullptr;
if (callback == nullptr) {
ALOGE("%s: cannot open camera %s. callback is null!",
__FUNCTION__, mCameraId.c_str());
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
if (status != Status::OK) {
/* Do something in */
......
/* Do something out */
} else {
mLock.lock();
/* Do something in */
......
/* Do something out */
/** Open HAL device */
status_t res;
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
res = mModule->open(mCameraId.c_str(),
reinterpret_cast(&device));
ATRACE_END();
/* Do something in */
......
/* Do something out */
session = createSession(
device, info.static_camera_characteristics, callback);
/* Do something in */
......
/* Do something out */
mSession = session;
IF_ALOGV() {
session->getInterface()->interfaceChain([](
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
ALOGV("Session interface chain:");
for (auto iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
mLock.unlock();
}
_hidl_cb(status, session->getInterface());
return Void();
}
而 creatSession
中的实现就非常简单了,直接创建了一个 CameraDeviceSession。当然在其构造函数中会调用内部的初始化函数,然后会进入 HAL 接口层 QCamera3HWI 的初始化流程,这里就先不分析了。
至此,从 CameraService 到 HAL Service 这一部分的打开相机流程就基本走通了。
sp CameraDevice::createSession(camera3_device_t* device,
const camera_metadata_t* deviceInfo,
const sp& callback) {
return new CameraDeviceSession(device, deviceInfo, callback);
}