- 一、相机架构
- 二、应用框架
- 1.Camera APP
- 2.AIDL
- 3.原生框架
- 4.binder IPC 接口
- 5.相机服务
- 6.HAL
- 三、open流程分析
- 1. CameraManager.openCamera()
- 1) new CameraDeviceImpl
- 2. CameraService.connectDevice()
- 1) makeClient()
- 1.1) new CameraDeviceClient
- 3. Camera2ClientBase
- 1) CameraDeviceClientBase
- 2) new Camera3Device
- 4. Camera2ClientBase::initialize()
- 5. manager->openSession()
(详细资料参见:source.android.google.cn/devices/camera)
应用代码位于应用框架级别,它使用 Camera 2 API 与相机硬件进行互动。在内部,此代码会调用相应的 Binder 接口,以访问与相机互动的原生代码。
2.AIDL与 CameraService 关联的 binder 接口可在 frameworks/av/camera/aidl/android/hardware 中找到。生成的代码会调用较低级别的原生代码以获取对实体相机的访问权限,并返回用于在框架级别创建 CameraDevice 并最终创建 CameraCaptureSession 对象的数据。
ICameraService.aidl——相机服务的接口;
ICameraServiceListener.aidl——应用框架CameraService的回调;
ICameraDeviceUser.aidl——已打开的特定相机设备的接口;
ICameraDeviceCallbacks.aidl——对应用框架CameraDevice的回调。
3.原生框架
此框架位于 frameworks/av/ 中,并提供相当于 CameraDevice 和 CameraCaptureSession 类的原生类。
4.binder IPC 接口IPC binder 接口用于实现跨越进程边界的通信。调用相机服务的若干个相机 binder 类位于 frameworks/av/camera/camera/aidl/android/hardware 目录中。ICameraService 是相机服务的接口;ICameraDeviceUser 是已打开的特定相机设备的接口;ICameraServiceListener 和 ICameraDeviceCallbacks 分别是对应用框架的 CameraService 和 CameraDevice 回调。
5.相机服务位于 frameworks/av/services/camera/libcameraservice/CameraService.cpp 下的相机服务是与 HAL 进行互动的实际代码。
6.HAL硬件抽象层定义了由相机服务调用、且您必须实现以确保相机硬件正常运行的标准接口。
HAL 位于相机驱动程序和更高级别的 Android 框架之间,它定义您必须实现的接口,以便应用可以正确地 *** 作相机硬件。相机 HAL 的 HIDL 接口在 hardware/interfaces/camera 中定义。
典型的绑定式 HAL 必须实现以下 HIDL 接口:
1. ICameraProvider:用于枚举单个设备并管理其状态。
2. ICameraDevice:相机设备接口。
3. ICameraDeviceSession:活跃的相机设备会话接口。
参考 HIDL 实现适用于 CameraProvider.cpp、CameraDevice.cpp 和 CameraDeviceSession.cpp。该实现封装了仍在使用旧版 API 的旧 HAL。
从 Android 8.0 开始,相机 HAL 实现必须使用 HIDL API;不支持使用旧版接口。
以高通平台Android10为例,流程图如下所示:
openCamera() 首先做了必要的参数检查,最后直接调用 openCameraDeviceUserAsync() 处理真正的打开相机流程。代码示例如下:
//代码位置:\frameworks\base\core\java\android\hardware\camera2\CameraManager.java
/*
@param cameraId 要打开的相机设备的唯一标识符
@param callback 打开相机后调用的回调
@param handler 应该在其上调用回调的 Handler,或者是 null 以使用当前线程的 android.os.Looper
*/
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
USE_CALLING_UID);
}
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
int clientUid)
throws CameraAccessException {
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
} else if (callback == null) {
throw new IllegalArgumentException("callback was null");
}
if (CameraManagerGlobal.sCameraServiceDisabled) {
throw new IllegalArgumentException("No cameras available on device");
}
openCameraDeviceUserAsync(cameraId, callback, executor, clientUid);
}
/*
返回 CameraDeviceImpl 对象
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
// 1. 创建 CameraDeviceImpl 对象,它继承自 CameraDevice
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
executor,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
if (supportsCamera2ApiLocked(cameraId)) {
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
// 2. 假设支持 Camera2Api,获取 CameraService
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
//because it's assigned a logic id (openparm id), no real
try{
java.lang.reflect.Field idField = deviceImpl.getClass().getDeclaredField("mCameraId");
idField.setAccessible(true);
idField.set(deviceImpl, cameraService.getRealCamIdFromMapping(cameraId));
Log.e("CameraIDMappingManager","CameraDeviceImpl mCameraId = "+deviceImpl.getId());
}catch(Exception e){
e.printStackTrace();
}
// 3. 调用 CameraService connectDevice 方法连接相机设备CameraDeviceUser
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
} else {
// Use legacy camera implementation for HAL1 devices
int id;
try {
id = Integer.parseInt(cameraId);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+ cameraId);
}
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id,
getDisplaySize());
}
} catch (ServiceSpecificException e) {
if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
throw new AssertionError("Should've gone down the shim path");
} else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
e.errorCode == ICameraService.ERROR_DISABLED ||
e.errorCode == ICameraService.ERROR_DISCONNECTED ||
e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
// Received one of the known connection errors
// The remote camera device cannot be connected to, so
// set the local camera to the startup error state
deviceImpl.setRemoteFailure(e);
if (e.errorCode == ICameraService.ERROR_DISABLED ||
e.errorCode == ICameraService.ERROR_DISCONNECTED ||
e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
// Per API docs, these failures call onError and throw
throwAsPublicException(e);
}
} else {
// Unexpected failure - rethrow
throwAsPublicException(e);
}
} catch (RemoteException e) {
// Camera service died - act as if it's a CAMERA_DISCONNECTED case
ServiceSpecificException sse = new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
deviceImpl.setRemoteFailure(sse);
throwAsPublicException(sse);
}
// TODO: factor out callback to be non-nested, then move setter to constructor
// For now, calling setRemoteDevice will fire initial
// onOpened/onUnconfigured callbacks.
// This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
// cameraUser dies during setup.
// 4. CameraDeviceImpl 对象上调用 setRemoteDevice() 方法
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
1) new CameraDeviceImpl
//代码位置:\frameworks\base\core\java\android\hardware\camera2\impl\CameraDeviceImpl.java
/*
CameraDevice具体实现。使用 CameraManager#open 实例化。
1. 获取 TAG
2. 获取 partialCount
*/
public class CameraDeviceImpl extends CameraDevice
implements IBinder.DeathRecipient {
...
public CameraDeviceImpl(String cameraId, StateCallback callback, Executor executor,
CameraCharacteristics characteristics, int appTargetSdkVersion) {
if (cameraId == null || callback == null || executor == null || characteristics == null) {
throw new IllegalArgumentException("Null argument given");
}
mCameraId = cameraId;
mDeviceCallback = callback;
mDeviceExecutor = executor;
mCharacteristics = characteristics;
mAppTargetSdkVersion = appTargetSdkVersion;
final int MAX_TAG_LEN = 23;
String tag = String.format("CameraDevice-JV-%s", mCameraId);
if (tag.length() > MAX_TAG_LEN) {
tag = tag.substring(0, MAX_TAG_LEN);
}
TAG = tag;
Integer partialCount = mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
// REQUEST_PARTIAL_RESULT_COUNT 定义结果将由多少个子组件组成。为了消除流水线延迟,可以在部分结果可用时立即将其从相机设备传递到应用程序层。
if (partialCount == null) {
// 1 means partial result is not supported.
// 默认值为 1。表示不支持部分结果, 并且相机设备将仅生成最终的 TotalCaptureResult
// 一个典型的用例可能是:请求自动对焦(AF)锁定后, 新的 AF 状态在整个管道中可能有 50%可用
mTotalPartialCount = 1;
} else {
// 相机设备可以通过部分结果立即将状态分发给应用程序, 其余的元数据则通过以后的部分结果进行分发
mTotalPartialCount = partialCount;
}
mIsPrivilegedApp = checkPrivilegedAppList();
}
...
}
2. CameraService.connectDevice()
CameraDevice 类代表连接到 Android 设备的单个相机的表示形式,允许以高帧率对图像捕获和后处理进行细粒度控制。继续分析open流程 CameraService.connectDevice 方法,代码如下所示:
//代码位置:\frameworks\av\services\camera\libcameraservice\CameraService.cpp
Status CameraService::connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
ATRACE_CALL();
Status ret = Status::ok();
// start: deal with bug of conflictmanager, get wrong status when pre-process is openning camera
isOpenningCamera = true;
// start: add camera id mapping
_setCamParabyExposeID(String8(cameraId).string());
String8 id = _getRealIDStrfromMap(String8(cameraId));
//String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
String16 clientPackageNameAdj = clientPackageName;
if (hardware::IPCThreadState::self()->isServingCall()) {
std::string vendorClient =
StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
clientPackageNameAdj = String16(vendorClient.c_str());
}
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,
clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
// start: deal with bug of conflictmanager, get wrong status when pre-process is openning camera
isOpenningCamera = false;
if(!ret.isOk()) {
logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageNameAdj),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
String8 clientName8(clientPackageName);
int originalClientPid = 0;
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
(halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
static_cast<int>(effectiveApiLevel));
if (shouldRejectHiddenCameraConnection(cameraId)) {
ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
cameraId.c_str());
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID \"%s\" currently available",
cameraId.string());
}
sp<CLIENT> client = nullptr;
{
// Acquire mServiceLock and prevent other clients from connecting
// 获取 AutoConditionLock 并阻止其他客户端连接
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
, clientPid);
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
cameraId.string(), clientName8.string(), clientPid);
}
// Enforce client permissions and do basic sanity checks
// 强制执行客户端权限并进行基本的健全性检查
if(!(ret = validateConnectLocked(cameraId, clientName8,
/*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
return ret;
}
// start: move camera conflict from validateConnectLocked() to these,
// because deadlock of mServiceLock when scan use ndk connect cs.
// start: restructure conflict manager for multi-user
// start: move conflict process back to here.
int32_t callpid = CameraThreadState::getCallingPid();
ALOGI("CameraService::conflictManager. start for pid(%d)", callpid);
//find pid of openning camera
std::vector<int32_t> activeCltPids;
{
Mutex::Autolock lock(mCameraStatesLock);
for (auto& state : mCameraStates) {
String8 cameraId = state.first;
auto clientDescriptor = mActiveClientManager.get(cameraId);
if (clientDescriptor != nullptr) {
activeCltPids.push_back(clientDescriptor->getOwnerId());
ALOGI("CameraService::conflictManager. camera (%s) has alive client (%d)", cameraId.string(), clientDescriptor->getOwnerId());
}
}
}
bool MgrLocked = gStatusMgrLock.tryLock()==NO_ERROR;
//start deal with NOLY mode
int32_t ONLY_pid = -1;
for(auto& it : gExtraStatusManager){
if(it.second.first == STATUS_ONLY){
ONLY_pid = it.first;
break;
}
}
if(ONLY_pid!=-1 && callpid !=ONLY_pid){
if(MgrLocked) gStatusMgrLock.unlock();
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"ohter process(pid %d) set ONLY mode, so this process(pid %d) with ID \"%s\" currently unavailable",
ONLY_pid, callpid, cameraId.string());
}
//start deal with RACE mode
if(ONLY_pid == -1){
for (size_t i = 0; i < activeCltPids.size(); i++) {
if(activeCltPids[i] == callpid){
ALOGI("CameraService::conflictManager. no need deal for pid(%d)", callpid);
break;
}else if(gExtraStatusManager.find(activeCltPids[i])!=gExtraStatusManager.end()){
auto it = gExtraStatusManager.find(activeCltPids[i]);
if(it->second.first != STATUS_RACE){
continue;
}
//do callback
if(MgrLocked){
gStatusMgrLock.unlock();
MgrLocked = false;
}
if(it->second.second.get() !=NULL){
mServiceLock.unlock();
int64_t token = CameraThreadState::clearCallingIdentity();
binder::Status ret = it->second.second.get()->onRelease(0);
CameraThreadState::restoreCallingIdentity(token);
mServiceLock.lock();
ALOGI("CameraService::conflictManager. cb: onRelease() finish by ret=%s", ret.toString8().string());
}else{
ALOGI("CameraService::conflictManager. cb is null.");
}
MgrLocked = gStatusMgrLock.tryLock()==NO_ERROR;
}
}
}
if(MgrLocked) gStatusMgrLock.unlock();
ALOGE("CameraService::conflictManager finish for pid(%d)", callpid);
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
// 在获取锁后检查 shim 参数,如果它们已经被更新并且我们正在进行 shim 更新,立即返回
if (shimUpdateOnly) {
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
if (!cameraState->getShimParams().isEmpty()) return ret;
}
}
status_t err;
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
// 抢占机制
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID \"%s\" currently available",
cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Higher-priority client using camera, ID \"%s\" currently unavailable",
cameraId.string());
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unexpected error %s (%d) opening camera \"%s\"",
strerror(-err), err, cameraId.string());
}
}
if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
// 处理 API1 MediaRecorder 的特殊情况,其中返回了现有客户端
device = static_cast<CLIENT*>(clientTmp.get());
return ret;
}
// give flashlight a chance to close devices if necessary.
// 如果有必要,让手电筒有机会关闭设备。
mFlashlight->prepareDeviceOpen(cameraId);
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
if (facing == -1) {
ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.string());
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unable to get camera device \"%s\" facing", cameraId.string());
}
sp<BasicClient> tmp = nullptr;
// 获取 BasicClient
if(!(ret = makeClient(this, cameraCb, clientPackageName,
cameraId, api1CameraId, facing,
clientPid, clientUid, getpid(),
halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
// 从 HAL 模块初始化客户端
err = client->initialize(mCameraProviderManager, mMonitorTags);
if (err != OK) {
ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
// Errors could be from the HAL module open call or from AppOpsManager
switch(err) {
case BAD_VALUE:
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Illegal argument to HAL module for camera \"%s\"", cameraId.string());
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
"Camera \"%s\" is already open", cameraId.string());
case -EUSERS:
return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
"Too many cameras already open, cannot open camera \"%s\"",
cameraId.string());
case PERMISSION_DENIED:
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"No permission to open camera \"%s\"", cameraId.string());
case -EACCES:
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Camera \"%s\" disabled by policy", cameraId.string());
case -ENODEV:
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
strerror(-err), err);
}
}
// Update shim paremeters for legacy clients
// 更新旧版客户端的 shim 参数
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
String8 rawParams = shimClient->getParameters();
CameraParameters params(rawParams);
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
cameraState->setShimParams(params);
} else {
ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
__FUNCTION__, cameraId.string());
}
}
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
// 如果仅更新旧的 shim 参数,请立即断开客户端连接
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
// 否则,将客户端添加到活动客户端列表
finishConnectLocked(client, partial);
}
} // lock is destroyed, allow further connect calls
// Important: release the mutex here so the client can call back into the service from its
// destructor (can be at the end of the call)
device = client;
return ret;
}
1) makeClient()
走分支 Camera2 API 路由,会创建 CameraDeviceClient 对象。代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\CameraService.cpp
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
if (halVersion < 0 || halVersion == deviceVersion) {
// Default path: HAL version is unspecified by caller, create CameraClient
// based on device version reported by the HAL.
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
getpid());
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%s\" HAL version %d does not support camera2 API",
cameraId.string(), deviceVersion);
}
break;
case CAMERA_DEVICE_API_VERSION_3_0:
case CAMERA_DEVICE_API_VERSION_3_1:
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
case CAMERA_DEVICE_API_VERSION_3_4:
case CAMERA_DEVICE_API_VERSION_3_5:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName,
cameraId, api1CameraId,
facing, clientPid, clientUid,
servicePid);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Camera device \"%s\" has unknown HAL version %d",
cameraId.string(), deviceVersion);
}
} else {
// A particular HAL version is requested by caller. Create CameraClient
// based on the requested HAL version.
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName,
api1CameraId, facing, clientPid, clientUid,
servicePid);
} else {
// Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
" opened as HAL %x device", halVersion, deviceVersion,
CAMERA_DEVICE_API_VERSION_1_0);
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
cameraId.string(), deviceVersion, halVersion);
}
}
return Status::ok();
}
1.1) new CameraDeviceClient
CameraDeviceClient 构造函数中创建了 Camera2ClientBase 对象。
// 代码位置:\frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp
// Interface used by CameraService
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, /*API1 camera ID*/ -1,
cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0),
mPrivilegedClient(false) {
char value[PROPERTY_VALUE_MAX];
property_get("persist.vendor.camera.privapp.list", value, "");
String16 packagelist(value);
if (packagelist.contains(clientPackageName.string())) {
mPrivilegedClient = true;
}
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
//代码位置:\frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.h
class CameraDeviceClient :
public Camera2ClientBase<CameraDeviceClientBase>,
public camera2::FrameProcessorBase::FilteredListener
{
...
}
3. Camera2ClientBase
Camera2ClientBase 构造器是一个模板函数,TClientBase 会被 CameraDeviceClientBase 替换,会先构造一个 CameraDeviceClientBase 对象。代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp
// Interface used by CameraService
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDevice(new Camera3Device(cameraId)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
1) CameraDeviceClientBase
CameraDeviceClientBase 构造器中又构造了一个 BasicClient 对象。代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
BasicClient(cameraService,
IInterface::asBinder(remoteCallback),
clientPackageName,
cameraId,
cameraFacing,
clientPid,
clientUid,
servicePid),
mRemoteCallback(remoteCallback) {
// We don't need it for API2 clients, but Camera2ClientBase requires it.
(void) api1CameraId;
}
BasicClient 定义在 CameraService.cpp 中,代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\CameraService.cpp
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
const String16& clientPackageName,
const String8& cameraIdStr, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
mDisconnected(false),
mRemoteBinder(remoteCallback)
{
if (sCameraService == nullptr) {
sCameraService = cameraService;
}
mOpsActive = false;
mDestructionStarted = false;
// In some cases the calling code has no access to the package it runs under.
// For example, NDK camera API.
// In this case we will get the packages for the calling UID and pick the first one
// for attributing the app op. This will work correctly for runtime permissions
// as for legacy apps we will toggle the app op for all packages in the UID.
// The caveat is that the operation may be attributed to the wrong package and
// stats based on app ops may be slightly off.
if (mClientPackageName.size() <= 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(kPermissionServiceName));
if (binder == 0) {
ALOGE("Cannot get permission service");
// Leave mClientPackageName unchanged (empty) and the further interaction
// with camera will fail in BasicClient::startCameraOps
return;
}
sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
Vector<String16> packages;
permCtrl->getPackagesForUid(mClientUid, packages);
if (packages.isEmpty()) {
ALOGE("No packages for calling UID");
// Leave mClientPackageName unchanged (empty) and the further interaction
// with camera will fail in BasicClient::startCameraOps
return;
}
mClientPackageName = packages[0];
}
if (!hardware::IPCThreadState::self()->isServingCall()) {
mAppOpsManager = std::make_unique<AppOpsManager>();
}
}
2) new Camera3Device
回到 Camera2ClientBase 构造器,mDevice(new Camera3Device(cameraId))会创建一个 Camera3Device 对象。代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp
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),
mNextZslStillResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mNextZslStillShutterFrameNumber(0),
mListener(NULL),
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
mLastTemplateId(-1),
mNeedFixupMonochromeTags(false)
{
ATRACE_CALL();
ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}
回到connectHelper(),从 HAL 模块初始化客户端。这会首先调用 CameraDeviceClient::initialize() 方法。
1. 调用 Camera2ClientBase::initialize() 方法进一步初始化
2. 创建 FrameProcessorBase 对象,并 run 起来,然后注册一些 RangeListener。FrameProcessorBase 类代表输出帧元数据处理线程。这个线程等待来自设备的新帧,并在必要时分析它们。
代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
ATRACE_CALL();
status_t res;
res = Camera2ClientBase::initialize(providerPtr, monitorTags);
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);
auto deviceInfo = mDevice->info();
camera_metadata_entry_t physicalKeysEntry = deviceInfo.find(
ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS);
if (physicalKeysEntry.count > 0) {
mSupportedPhysicalRequestKeys.insert(mSupportedPhysicalRequestKeys.begin(),
physicalKeysEntry.data.i32,
physicalKeysEntry.data.i32 + physicalKeysEntry.count);
}
mProviderManager = providerPtr;
return OK;
}
4. Camera2ClientBase::initialize()
Camera2ClientBase 类 initialize() 方法最终调用了 Camera3Device initialize() 方法。代码如下:
//代码位置:\frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
const String8& monitorTags) {
return initializeImpl(manager, monitorTags);
}
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
const String8& monitorTags) {
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;
}
// mDevice即Camera3Device
res = mDevice->initialize(providerPtr, monitorTags);
if (res != OK) {
ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
wp<CameraDeviceBase::NotificationListener> weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
初始化的时候和 camera HAL 关联了起来。
//代码位置:\frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp
status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
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<ICameraDeviceSession> 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;
}
res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
if (res != OK) {
SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
session->close();
return res;
}
std::vector<std::string> physicalCameraIds;
bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
if (isLogical) {
for (auto& physicalId : physicalCameraIds) {
res = manager->getCameraCharacteristics(
physicalId, &mPhysicalDeviceInfoMap[physicalId]);
if (res != OK) {
SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
physicalId.c_str(), strerror(-res), res);
session->close();
return res;
}
if (DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId])) {
mDistortionMappers[physicalId].setupStaticInfo(mPhysicalDeviceInfoMap[physicalId]);
if (res != OK) {
SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
"correction", physicalId.c_str());
session->close();
return res;
}
}
}
}
std::shared_ptr<RequestMetadataQueue> queue;
auto requestQueueRet = session->getCaptureRequestMetadataQueue(
[&queue](const auto& descriptor) {
queue = std::make_shared<RequestMetadataQueue>(descriptor);
if (!queue->isValid() || queue->availableToWrite() <= 0) {
ALOGE("HAL returns empty request metadata fmq, not use it");
queue = nullptr;
// don't use the queue onwards.
}
});
if (!requestQueueRet.isOk()) {
ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
requestQueueRet.description().c_str());
return DEAD_OBJECT;
}
std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
auto resultQueueRet = session->getCaptureResultMetadataQueue(
[&resQueue](const auto& descriptor) {
resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
ALOGE("HAL returns empty result metadata fmq, not use it");
resQueue = nullptr;
// Don't use the resQueue onwards.
}
});
if (!resultQueueRet.isOk()) {
ALOGE("Transaction error when getting result metadata queue from camera session: %s",
resultQueueRet.description().c_str());
return DEAD_OBJECT;
}
IF_ALOGV() {
session->interfaceChain([](
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
ALOGV("Session interface chain:");
for (const auto& iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
camera_metadata_entry bufMgrMode =
mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
if (bufMgrMode.count > 0) {
mUseHalBufManager = (bufMgrMode.data.u8[0] ==
ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
}
// 将CameraDeviceSession赋值给HalInterface::mHidlSession_3_X
mInterface = new HalInterface(session, queue, mUseHalBufManager);
std::string providerType;
mVendorTagId = manager->getProviderTagIdLocked(mId.string());
mTagMonitor.initialize(mVendorTagId);
if (!monitorTags.isEmpty()) {
mTagMonitor.parseTagsToMonitor(String8(monitorTags));
}
// Metadata tags needs fixup for monochrome camera device version less
// than 3.5.
hardware::hidl_version maxVersion{0,0};
res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
if (res != OK) {
ALOGE("%s: Error in getting camera device version id: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
int deviceVersion = HARDWARE_DEVICE_API_VERSION(
maxVersion.get_major(), maxVersion.get_minor());
bool isMonochrome = false;
camera_metadata_entry_t entry = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
for (size_t i = 0; i < entry.count; i++) {
uint8_t capability = entry.data.u8[i];
if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
isMonochrome = true;
}
}
mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
return initializeCommonLocked();
}
status_t Camera3Device::initializeCommonLocked() {
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
if (res != OK) {
SET_ERR_L("Unable to start status tracking thread: %s (%d)",
strerror(-res), res);
mInterface->close();
mStatusTracker.clear();
return res;
}
/** Register in-flight map to the status tracker */
mInFlightStatusId = mStatusTracker->addComponent();
if (mUseHalBufManager) {
res = mRequestBufferSM.initialize(mStatusTracker);
if (res != OK) {
SET_ERR_L("Unable to start request buffer state machine: %s (%d)",
strerror(-res), res);
mInterface->close();
mStatusTracker.clear();
return res;
}
}
/** Create buffer manager */
mBufferManager = new Camera3BufferManager();
Vector<int32_t> sessionParamKeys;
camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
if (sessionKeysEntry.count > 0) {
sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
}
/** Start up request queue thread */
mRequestThread = new RequestThread(
this, mStatusTracker, mInterface, sessionParamKeys, mUseHalBufManager);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
if (res != OK) {
SET_ERR_L("Unable to start request queue thread: %s (%d)",
strerror(-res), res);
mInterface->close();
mRequestThread.clear();
return res;
}
mPreparerThread = new PreparerThread();
internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNextStreamId = 0;
mDummyStreamId = NO_STREAM;
mNeedConfig = true;
mPauseStateNotify = false;
// Measure the clock domain offset between camera and video/hw_composer
camera_metadata_entry timestampSource =
mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);
if (timestampSource.count > 0 && timestampSource.data.u8[0] ==
ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {
mTimestampOffset = getMonoToBoottimeOffset();
}
// Will the HAL be sending in early partial result metadata?
camera_metadata_entry partialResultsCount =
mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
if (partialResultsCount.count > 0) {
mNumPartialResults = partialResultsCount.data.i32[0];
mUsePartialResult = (mNumPartialResults > 1);
}
camera_metadata_entry configs =
mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
for (uint32_t i = 0; i < configs.count; i += 4) {
if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
configs.data.i32[i + 3] ==
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],
configs.data.i32[i + 2]));
}
}
if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
if (res != OK) {
SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
return res;
}
}
return OK;
}
5. manager->openSession()
这里面最重要的一步就是manager->openSession(),接下来看看这个openSession()里面做的事情,代码如下:
代码位置:\frameworksavservicescameralibcameraservicecommon\CameraProviderManager.cpp
status_t CameraProviderManager::openSession(const std::string &id,
const sp<device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<device::V3_2::ICameraDeviceSession> *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
// 根据CameraDevice的版本,从所有Provider中,找到对应的DeviceInfo
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
// 根据刚刚deviceInfo中对应的provider的信息,获取到对应CameraProvider服务
const sp<provider::V2_4::ICameraProvider> provider =
deviceInfo->mParentProvider->startProviderInterface();
if (provider == nullptr) {
return DEAD_OBJECT;
}
saveRef(DeviceMode::CAMERA, id, provider);
Status status;
hardware::Return<void> ret;
// 通过CameraProvider的getCameraDeviceInterface_V3_x()实例化一个CameraDevice。这一步是通过HIDL调用到了Hal层
auto interface = deviceInfo3->startDeviceInterface<
CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
if (interface == nullptr) {
return DEAD_OBJECT;
}
// 这个interface就是前面startDeviceInterface()得到的CameraDevice,这里是要通过CameraDevicce::open()创建一个有效的CameraDeviceSession。这一步也是通过HIDL调用到了HAL层
ret = interface->open(callback, [&status, &session]
(Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
status = s;
if (status == Status::OK) {
*session = cameraSession;
}
});
if (!ret.isOk()) {
removeRef(DeviceMode::CAMERA, id);
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);
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)