打开相机的起点从 CameraManager 类 openCamera(…) 方法开始。
打开具有给定 ID 的相机连接。
使用 getCameraIdList 获取可用相机设备的列表。请注意,即使列出了 ID,但如果在对 getCameraIdList 和 openCamera 的调用之间断开了设备的连接,或者如果优先级更高的相机 API 客户端开始使用相机设备,则打开可能会失败。
从 API 级别 23 开始,由于优先级较低的后台相机 API 客户端正在使用该设备,因此已调用 AvailabilityCallback#onCameraUnavailable(String) 回调的设备仍可以通过调用此方法,来打开当调用相机 API 客户端的优先级高于使用此设备的当前相机 API 客户端时。通常,如果最顶层的前台活动正在您的应用程序进程中运行,则在访问相机时,将为您的进程赋予最高优先级,并且即使另一个相机 API 客户端正在使用相机设备,此方法也会成功。以此方式失去控制权的所有低优先级应用程序都将收到 android.hardware.camera2.CameraDevice.StateCallback#onDisconnected 回调。
成功打开相机后,将使用新打开的 CameraDevice 调用 CameraDevice.StateCallback#onOpened。然后可以通过调用 CameraDevice#createCaptureSession 和 CameraDevice#createCaptureRequest 设置相机设备进行操作。
由于相机设备将以异步方式打开,因此对返回的 CameraDevice 实例执行的所有异步操作都将排队,直到设备启动完成并调用回调的 CameraDevice.StateCallback#onOpened 方法为止。然后按顺序处理挂起的操作。
如果在此函数调用返回后初始化期间相机断开连接,则 CameraDevice.StateCallback#onDisconnected 的 CameraDevice 处于断开状态(并且 CameraDevice.StateCallback#onOpened 将被跳过)。
如果打开相机设备失败,则将调用设备回调的 CameraDevice.StateCallback#onError 方法,并且在相机设备上进行的后续调用将引发 CameraAccessException。
@param cameraId 要打开的相机设备的唯一标识符
@param callback 打开相机后调用的回调
@param handler 应该在其上调用回调的 Handler,或者是 null 以使用当前线程的 android.os.Looper
openCamera(…) 首先做了必要的参数检查,最后直接调用 openCameraDeviceUserAsync(…) 处理真正的打开相机流程。
frameworks/base/core/java/android/hardware/camera2/CameraManager.java
public final class CameraManager {
......
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
} else if (callback == null) {
throw new IllegalArgumentException("callback was null");
} else if (handler == null) {
if (Looper.myLooper() != null) {
handler = new Handler();
} else {
throw new IllegalArgumentException(
"Handler argument is null, but no looper exists in the calling thread");
}
}
openCameraDeviceUserAsync(cameraId, callback, handler);
}
......
}
帮助打开与给定 ID 的相机连接。
- 创建 CameraDeviceImpl 对象,它继承自 CameraDevice
- 假设支持 Camera2Api,获取 CameraService
- 调用 CameraService connectDevice 方法连接相机设备
- 获取 CameraDeviceUser
- CameraDeviceImpl 对象上调用 setRemoteDevice(…) 方法
- 返回 CameraDeviceImpl 对象
frameworks/base/core/java/android/hardware/camera2/CameraManager.java
public final class CameraManager {
......
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Handler handler)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
try {
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
handler,
characteristics);
BinderHolder holder = new BinderHolder();
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
int id = Integer.parseInt(cameraId);
try {
if (supportsCamera2ApiLocked(cameraId)) {
// 使用 cameraservice 的 cameradeviceclient 实现 HAL3.2+ 设备
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new CameraRuntimeException(
CameraAccessException.CAMERA_DISCONNECTED,
"Camera service is currently unavailable");
}
cameraService.connectDevice(callbacks, id,
mContext.getOpPackageName(), USE_CALLING_UID, holder);
cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
} else {
// 对 HAL1 设备使用旧版相机实现
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
}
} catch (CameraRuntimeException e) {
......
} catch (RemoteException e) {
......
}
// TODO: factor out callback to be non-nested, then move setter to constructor
// 目前,调用 setRemoteDevice 将触发初始的 onOpened/onUnconfigured 回调。
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
} catch (NumberFormatException e) {
......
} catch (CameraRuntimeException e) {
......
}
return device;
}
......
}
HAL2.1+ CameraDevice 实现。使用 CameraManager#open 实例化。
- 获取 TAG
- 获取 partialCount
REQUEST_PARTIAL_RESULT_COUNT 定义结果将由多少个子组件组成。
为了消除流水线延迟,可以在部分结果可用时立即将其从相机设备传递到应用程序层。
可选的; 默认值为 1。值 1 表示不支持部分结果,并且相机设备将仅生成最终的 TotalCaptureResult。一个典型的用例可能是:请求自动对焦(AF)锁定后,新的 AF 状态在整个管道中可能有 50% 可用。然后,相机设备可以通过部分结果立即将状态分发给应用程序,其余的元数据则通过以后的部分结果进行分发。
frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
public class CameraDeviceImpl extends CameraDevice {
......
public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler,
CameraCharacteristics characteristics) {
if (cameraId == null || callback == null || handler == null || characteristics == null) {
throw new IllegalArgumentException("Null argument given");
}
mCameraId = cameraId;
mDeviceCallback = callback;
mDeviceHandler = handler;
mCharacteristics = characteristics;
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);
if (partialCount == null) {
// 1 means partial result is not supported.
mTotalPartialCount = 1;
} else {
mTotalPartialCount = partialCount;
}
}
......
}
现在了解一下 CameraDevice 类。
CameraDevice 类代表连接到 Android 设备的单个相机的表示形式,允许以高帧率对图像捕获和后处理进行细粒度控制。
应用必须在其清单中声明 android.Manifest.permission#CAMERA Camera 权限,才能访问相机设备。
给定的相机设备可以提供以下两个级别之一的支持:受限或完全支持。 如果设备仅支持有限级别,则 Camera2 会公开一个功能集,该功能集与旧版 android.hardware.Camera Camera API 大致相同,尽管接口更加简洁高效。与旧版相机 API 相比,实现全面支持的设备提供了显着改进的功能。 针对有限级别设备的应用程序将在完整级别设备上保持不变;如果应用程序需要完整级别的设备才能正常运行,请在清单中声明 “ android.hardware.camera.level.full” 功能。
frameworks/base/core/java/android/hardware/camera2/CameraDevice.java
public abstract class CameraDevice implements AutoCloseable {
......
}
获取 CameraService 相机服务具体可以参见《Android 源码 Camera2 获取 CameraId 列表》一节。继续分析调用 CameraService connectDevice 方法。这会调到 BpCameraService 同名方法。
frameworks/av/camera/ICameraService.cpp
class BpCameraService: public BpInterface<ICameraService>
{
public:
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraCb));
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
status_t status;
status = remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);
if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICameraDeviceUser>(reply.readStrongBinder());
}
return status;
}
}
接着在 BnCameraService onTransact(…) 方法中接收 Client 发来的消息,调用它的 connectDevice(…) 具体实现。
frameworks/av/camera/ICameraService.cpp
status_t BnCameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
......
case CONNECT_DEVICE: {
CHECK_INTERFACE(ICameraService, data, reply);
sp<ICameraDeviceCallbacks> cameraClient =
interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
int32_t cameraId = data.readInt32();
const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp<ICameraDeviceUser> camera;
status_t status = connectDevice(cameraClient, cameraId,
clientName, clientUid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
reply->writeInt32(1);
reply->writeStrongBinder(IInterface::asBinder(camera));
} else {
reply->writeInt32(0);
}
return NO_ERROR;
} break;
......
}
......
}
CameraService::connectDevice(…) 主要调用了 connectHelper(…) 方法。
frameworks/av/services/camera/libcameraservice/CameraService.cpp
status_t CameraService::connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device) {
ATRACE_CALL();
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, API_2, false, false,
/*out*/client);
if(ret != NO_ERROR) {
logRejected(id, getCallingPid(), String8(clientPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
device = client;
return NO_ERROR;
}
下面重点关注获取 BasicClient 和 从 HAL 模块初始化客户端。
frameworks/av/services/camera/libcameraservice/CameraService.h
template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
status_t ret = NO_ERROR;
String8 clientName8(clientPackageName);
int clientPid = getCallingPid();
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));
sp<CLIENT> client = nullptr;
{
// 获取 AutoConditionLock 并阻止其他客户端连接
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)."
, clientPid);
return -EBUSY;
}
// 强制执行客户端权限并进行基本的健全性检查
if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
return ret;
}
// 在获取锁后检查 shim 参数,如果它们已经被更新并且我们正在进行 shim 更新,立即返回
if (shimUpdateOnly) {
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
if (!cameraState->getShimParams().isEmpty()) return NO_ERROR;
}
}
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
if ((ret = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
return ret;
}
if (clientTmp.get() != nullptr) {
// 处理 API1 MediaRecorder 的特殊情况,其中返回了现有客户端
device = static_cast<CLIENT*>(clientTmp.get());
return NO_ERROR;
}
// 如果有必要,让手电筒有机会关闭设备。
mFlashlight->prepareDeviceOpen(cameraId);
// TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs
int id = cameraIdToInt(cameraId);
if (id == -1) {
ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__,
cameraId.string());
return BAD_VALUE;
}
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
// 获取 BasicClient
if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)) != NO_ERROR) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
// 从 HAL 模块初始化客户端
if ((ret = client->initialize(mModule)) != OK) {
ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
return ret;
}
// 更新旧版客户端的 shim 参数
if (effectiveApiLevel == API_1) {
// 假设我们一直收到 API1 的 Client 子类
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) {
// 如果仅更新旧的 shim 参数,请立即断开客户端连接
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// 否则,将客户端添加到活动客户端列表
finishConnectLocked(client, partial);
}
} // 锁被销毁,允许进一步连接调用
// 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 NO_ERROR;
}
假设走分支 Camera2 API 路由,这会创建 CameraDeviceClient 对象。
frameworks/av/services/camera/libcameraservice/CameraService.cpp
status_t CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
// TODO: Update CameraClients + HAL interface to use strings for Camera IDs
int id = cameraIdToInt(cameraId);
if (id == -1) {
ALOGE("%s: Invalid camera ID %s, cannot convert to integer.", __FUNCTION__,
cameraId.string());
return BAD_VALUE;
}
if (halVersion < 0 || halVersion == deviceVersion) {
// 默认路径:调用者未指定 HAL 版本,根据 HAL 报告的设备版本创建 CameraClient。
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, id, facing,
clientPid, clientUid, getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return -EOPNOTSUPP;
}
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
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:
if (effectiveApiLevel == API_1) { // Camera1 API 路由
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, id, facing,
clientPid, clientUid, servicePid, legacyMode);
} else { // Camera2 API 路由
sp<ICameraDeviceCallbacks> tmp =
static_cast<ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, id,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return INVALID_OPERATION;
}
} else {
// 调用者要求特定的 HAL 版本。根据请求的 HAL 版本创建 CameraClient。
if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// 只支持高 HAL 版本设备打开为 HAL1.0 设备。
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, id, facing,
clientPid, clientUid, servicePid, legacyMode);
} else {
// 目前尚不支持其他组合(例如,以HAL2.x 打开的 HAL3.x)。
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 INVALID_OPERATION;
}
}
return NO_ERROR;
}
CameraDeviceClient 构造函数中创建了 Camera2ClientBase 对象。
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mRequestIdCounter(0) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %d: Opened", cameraId);
}
Camera2ClientBase 构造器是一个模板函数,TClientBase 会被 CameraDeviceClientBase 替换,会先构造一个 CameraDeviceClientBase 对象。
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(cameraId)),
mDeviceActive(false)
{
ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
mDevice = CameraDeviceFactory::createDevice(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
CameraDeviceClientBase 构造器中又构造了一个 BasicClient 对象。
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
const sp<ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
BasicClient(cameraService,
IInterface::asBinder(remoteCallback),
clientPackageName,
cameraId,
cameraFacing,
clientPid,
clientUid,
servicePid),
mRemoteCallback(remoteCallback) {
}
BasicClient 定义在 CameraService.cpp 中。
frameworks/av/services/camera/libcameraservice/CameraService.cpp
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
mClientPackageName(clientPackageName), mDisconnected(false)
{
mCameraService = cameraService;
mRemoteBinder = remoteCallback;
mCameraId = cameraId;
mCameraFacing = cameraFacing;
mClientPid = clientPid;
mClientUid = clientUid;
mServicePid = servicePid;
mOpsActive = false;
mDestructionStarted = false;
}
回到 Camera2ClientBase 构造器,CameraDeviceFactory::createDevice(…) 会创建 CameraDevice。
- 由 CameraService 弱引用提升为强引用
- 根据 HAL 版本去创建不同的 Camera2Device 或 Camera3Device 对象
frameworks/av/services/camera/libcameraservice/CameraDeviceFactory.cpp
sp<CameraDeviceBase> CameraDeviceFactory::createDevice(int cameraId) {
sp<CameraService> svc = sService.promote();
if (svc == 0) {
ALOGE("%s: No service registered", __FUNCTION__);
return NULL;
}
int deviceVersion = svc->getDeviceVersion(cameraId, /*facing*/NULL);
sp<CameraDeviceBase> device;
switch (deviceVersion) {
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
device = new Camera2Device(cameraId);
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:
device = new Camera3Device(cameraId);
break;
default:
ALOGE("%s: Camera %d: Unknown HAL device version %d",
__FUNCTION__, cameraId, deviceVersion);
device = NULL;
break;
}
ALOGV_IF(device != 0, "Created a new camera device for version %d",
deviceVersion);
return device;
}
假设工厂方法创建了 Camera3Device。
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
Camera3Device::Camera3Device(int id):
mId(id),
mIsConstrainedHighSpeedConfiguration(false),
mHal3Device(NULL),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mNextResultFrameNumber(0),
mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mListener(NULL)
{
ATRACE_CALL();
camera3_callback_ops::notify = &sNotify;
camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
ALOGV("%s: Created device for camera %d", __FUNCTION__, id);
}
现在来回看从 HAL 模块初始化客户端。这会首先调用 CameraDeviceClient::initialize(…) 方法。
- 调用 Camera2ClientBase::initialize(…) 方法进一步初始化
- 创建 FrameProcessorBase 对象,并 run 起来,然后注册一些 RangeListener。FrameProcessorBase 类代表输出帧元数据处理线程。这个线程等待来自设备的新帧,并在必要时分析它们。
RangeListener 为一系列 ID [minId,maxId)注册一个监听器。多个监听者可以监听同一范围。使用相同范围的 ID 注册相同的监听器无效。sendPartials 控制是否发送部分结果。
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
status_t CameraDeviceClient::initialize(CameraModule *module)
{
ATRACE_CALL();
status_t res;
res = Camera2ClientBase::initialize(module);
if (res != OK) {
return res;
}
String8 threadName;
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%d-FrameProc", mCameraId);
mFrameProcessor->run(threadName.string());
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
return OK;
}
Camera2ClientBase 类 initialize(…) 方法最终调用了 Camera3Device initialize(…) 方法。
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
TClientBase::mCameraId);
status_t res;
// 验证操作权限
res = TClientBase::startCameraOps();
if (res != OK) {
return res;
}
if (mDevice == NULL) {
ALOGE("%s: Camera %d: No device connected",
__FUNCTION__, TClientBase::mCameraId);
return NO_INIT;
}
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
return res;
}
res = mDevice->setNotifyCallback(this);
return OK;
}
初始化的时候和 camera HAL 关联了起来。
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
status_t Camera3Device::initialize(CameraModule *module)
{
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
/** 打开 HAL device */
status_t res;
String8 deviceName = String8::format("%d", mId);
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
res = module->open(deviceName.string(),
reinterpret_cast<hw_device_t**>(&device));
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
return res;
}
/** 交叉检查设备版本 */
if (device->common.version < CAMERA_DEVICE_API_VERSION_3_0) {
SET_ERR_L("Could not open camera: "
"Camera device should be at least %x, reports %x instead",
CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
camera_info info;
res = CameraService::filterGetInfoErrorCode(module->getCameraInfo(
mId, &info));
if (res != OK) return res;
if (info.device_version != device->common.version) {
SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
" and device version (%x).",
info.device_version, device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
/** 使用回调函数初始化设备 */
ATRACE_BEGIN("camera3->initialize");
res = device->ops->initialize(device, this);
ATRACE_END();
if (res != OK) {
SET_ERR_L("Unable to initialize HAL device: %s (%d)",
strerror(-res), res);
device->common.close(&device->common);
return BAD_VALUE;
}
/** 启动状态跟踪器线程 */
mStatusTracker = new StatusTracker(this);
res = mStatusTracker->run(String8::format("C3Dev-%d-Status", mId).string());
if (res != OK) {
SET_ERR_L("Unable to start status tracking thread: %s (%d)",
strerror(-res), res);
device->common.close(&device->common);
mStatusTracker.clear();
return res;
}
bool aeLockAvailable = false;
camera_metadata_ro_entry aeLockAvailableEntry;
res = find_camera_metadata_ro_entry(info.static_camera_characteristics,
ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry);
if (res == OK && aeLockAvailableEntry.count > 0) {
aeLockAvailable = (aeLockAvailableEntry.data.u8[0] ==
ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
}
/** 启动请求队列线程 */
mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable);
res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
if (res != OK) {
SET_ERR_L("Unable to start request queue thread: %s (%d)",
strerror(-res), res);
device->common.close(&device->common);
mRequestThread.clear();
return res;
}
mPreparerThread = new PreparerThread();
/** Everything is good to go */
mDeviceVersion = device->common.version;
mDeviceInfo = info.static_camera_characteristics;
mHal3Device = device;
internalUpdateStatusLocked(STATUS_UNCONFIGURED);
mNextStreamId = 0;
mDummyStreamId = NO_STREAM;
mNeedConfig = true;
mPauseStateNotify = false;
// HAL是否会发送早期的部分结果元数据?
if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
camera_metadata_entry partialResultsCount =
mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
if (partialResultsCount.count > 0) {
mNumPartialResults = partialResultsCount.data.i32[0];
mUsePartialResult = (mNumPartialResults > 1);
}
} else {
camera_metadata_entry partialResultsQuirk =
mDeviceInfo.find(ANDROID_QUIRKS_USE_PARTIAL_RESULT);
if (partialResultsQuirk.count > 0 && partialResultsQuirk.data.u8[0] == 1) {
mUsePartialResult = true;
}
}
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]));
}
}
return OK;
}
CameraModule::open(…) 方法内部调用了 camera_module 结构体 common 成员,这是一个 hw_module_t 结构体,其内部定义了 hw_module_methods_t 结构体,hw_module_methods_t 结构体内部又定义了 open 函数指针。这部分需要遵守 HAL 层定义。
frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
int CameraModule::open(const char* id, struct hw_device_t** device) {
int res;
ATRACE_BEGIN("camera_module->open");
res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
ATRACE_END();
return res;
}
我们以 moto Nexus 6 HAL device/moto/shamu/camera/QCamera2/ 为例进行分析。QCamera2Hal.cpp 中给 hw_module_t 结构体 camera_common 进行了赋值,methods 中定义了 open(…) 方法。
device/moto/shamu/camera/QCamera2/QCamera2Hal.cpp
#include "QCamera2Factory.h"
#include "HAL3/QCamera3VendorTags.h"
static hw_module_t camera_common = {
tag: HARDWARE_MODULE_TAG,
module_api_version: CAMERA_MODULE_API_VERSION_2_4,
hal_api_version: HARDWARE_HAL_API_VERSION,
id: CAMERA_HARDWARE_MODULE_ID,
name: "QCamera Module",
author: "Qualcomm Innovation Center Inc",
methods: &qcamera::QCamera2Factory::mModuleMethods,
dso: NULL,
reserved: {0},
};
open 函数指针实际指向 QCamera2Factory::camera_device_open(…) 函数。
device/moto/shamu/camera/QCamera2/QCamera2Factory.cpp
struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
open: QCamera2Factory::camera_device_open,
};
QCamera2Factory::camera_device_open(…) 方法内部做了入参检查,然后调用 QCamera2Factory::cameraDeviceOpen(…) 方法。gQCamera2Factory 是在 QCamera2Factory::get_number_of_cameras() 方法中构造的。
device/moto/shamu/camera/QCamera2/QCamera2Factory.cpp
int QCamera2Factory::camera_device_open(
const struct hw_module_t *module, const char *id,
struct hw_device_t **hw_device)
{
if (module != &HAL_MODULE_INFO_SYM.common) {
ALOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
ALOGE("Invalid camera id");
return BAD_VALUE;
}
return gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
}
假设我们走 HAL3 分支,这里会创建 QCamera3HardwareInterface 对象,接着调用其 openCamera(…) 方法。
device/moto/shamu/camera/QCamera2/QCamera2Factory.cpp
int QCamera2Factory::cameraDeviceOpen(int camera_id,
struct hw_device_t **hw_device)
{
int rc = NO_ERROR;
if (camera_id < 0 || camera_id >= mNumOfCameras)
return -ENODEV;
if ( NULL == mHalDescriptors ) {
ALOGE("%s : Hal descriptor table is not initialized!", __func__);
return NO_INIT;
}
if ( mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_3_0 ) {
QCamera3HardwareInterface *hw = new QCamera3HardwareInterface(mHalDescriptors[camera_id].cameraId,
mCallbacks);
if (!hw) {
ALOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != 0) {
delete hw;
}
} else if (mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_1_0) {
......
} else {
ALOGE("%s: Device version for camera id %d invalid %d",
__func__,
camera_id,
mHalDescriptors[camera_id].device_version);
return BAD_VALUE;
}
return rc;
}
QCamera3HardwareInterface 构造函数如下:
device/moto/shamu/camera/QCamera2/HAL3/QCamera3HWI.cpp
QCamera3HardwareInterface::QCamera3HardwareInterface(int cameraId,
const camera_module_callbacks_t *callbacks)
: mCameraId(cameraId),
mCameraHandle(NULL),
mCameraOpened(false),
mCameraInitialized(false),
mCallbackOps(NULL),
mMetadataChannel(NULL),
mPictureChannel(NULL),
mRawChannel(NULL),
mSupportChannel(NULL),
mRawDumpChannel(NULL),
mFirstRequest(false),
mFlush(false),
mParamHeap(NULL),
mParameters(NULL),
m_bIsVideo(false),
m_bIs4KVideo(false),
mEisEnable(0),
mLoopBackResult(NULL),
mMinProcessedFrameDuration(0),
mMinJpegFrameDuration(0),
mMinRawFrameDuration(0),
m_pPowerModule(NULL),
mMetaFrameCount(0),
mCallbacks(callbacks),
mCaptureIntent(0)
{
getLogLevel();
mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
mCameraDevice.common.version = CAMERA_DEVICE_API_VERSION_3_3;
mCameraDevice.common.close = close_camera_device;
mCameraDevice.ops = &mCameraOps;
mCameraDevice.priv = this;
gCamCapability[cameraId]->version = CAM_HAL_V3;
// TODO: hardcode for now until mctl add support for min_num_pp_bufs
//TBD - To see if this hardcoding is needed. Check by printing if this is filled by mctl to 3
gCamCapability[cameraId]->min_num_pp_bufs = 3;
pthread_cond_init(&mRequestCond, NULL);
mPendingRequest = 0;
mCurrentRequestId = -1;
pthread_mutex_init(&mMutex, NULL);
for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++)
mDefaultMetadata[i] = NULL;
#ifdef HAS_MULTIMEDIA_HINTS
if (hw_get_module(POWER_HARDWARE_MODULE_ID, (const hw_module_t **)&m_pPowerModule)) {
ALOGE("%s: %s module not found", __func__, POWER_HARDWARE_MODULE_ID);
}
#endif
char prop[PROPERTY_VALUE_MAX];
property_get("persist.camera.raw.dump", prop, "0");
mEnableRawDump = atoi(prop);
if (mEnableRawDump)
CDBG("%s: Raw dump from Camera HAL enabled", __func__);
}
QCamera3HardwareInterface::openCamera(…) 在内部调用了无入参的重载方法,实际工作是由 camera_open(…) 函数完成的。mm_camera_vtbl_t 是包含相机句柄和操作表的虚拟表。
device/moto/shamu/camera/QCamera2/HAL3/QCamera3HWI.cpp
int QCamera3HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
int rc = 0;
if (mCameraOpened) {
*hw_device = NULL;
return PERMISSION_DENIED;
}
rc = openCamera();
if (rc == 0) {
*hw_device = &mCameraDevice.common;
} else
*hw_device = NULL;
#ifdef HAS_MULTIMEDIA_HINTS
if (rc == 0) {
if (m_pPowerModule) {
if (m_pPowerModule->powerHint) {
m_pPowerModule->powerHint(m_pPowerModule, POWER_HINT_VIDEO_ENCODE,
(void *)"state=1");
}
}
}
#endif
return rc;
}
int QCamera3HardwareInterface::openCamera()
{
int rc = 0;
ATRACE_CALL();
if (mCameraHandle) {
ALOGE("Failure: Camera already opened");
return ALREADY_EXISTS;
}
rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId);
if (rc < 0) {
ALOGE("%s: Failed to reserve flash for camera id: %d",
__func__,
mCameraId);
return UNKNOWN_ERROR;
}
mCameraHandle = camera_open(mCameraId);
if (!mCameraHandle) {
ALOGE("camera_open failed.");
return UNKNOWN_ERROR;
}
mCameraOpened = true;
rc = mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
camEvtHandle, (void *)this);
if (rc < 0) {
ALOGE("%s: Error, failed to register event callback", __func__);
/* Not closing camera here since it is already handled in destructor */
return FAILED_TRANSACTION;
}
return NO_ERROR;
}
camera device 打开是由 mm_camera_open(…) 函数完成的。
device/moto/shamu/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
mm_camera_vtbl_t * camera_open(uint8_t camera_idx)
{
int32_t rc = 0;
mm_camera_obj_t* cam_obj = NULL;
CDBG("%s: E camera_idx = %d\n", __func__, camera_idx);
if (camera_idx >= g_cam_ctrl.num_cam) {
CDBG_ERROR("%s: Invalid camera_idx (%d)", __func__, camera_idx);
return NULL;
}
pthread_mutex_lock(&g_intf_lock);
/* opened already */
if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
/* Add reference */
g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
pthread_mutex_unlock(&g_intf_lock);
CDBG("%s: opened alreadyn", __func__);
return &g_cam_ctrl.cam_obj[camera_idx]->vtbl;
}
cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
if(NULL == cam_obj) {
pthread_mutex_unlock(&g_intf_lock);
CDBG("%s: no mem", __func__);
return NULL;
}
/* initialize camera obj */
memset(cam_obj, 0, sizeof(mm_camera_obj_t));
cam_obj->ctrl_fd = -1;
cam_obj->ds_fd = -1;
cam_obj->ref_count++;
cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
cam_obj->vtbl.ops = &mm_camera_ops;
pthread_mutex_init(&cam_obj->cam_lock, NULL);
rc = mm_camera_open(cam_obj);
if(rc != 0) {
CDBG_ERROR("%s: mm_camera_open err = %d", __func__, rc);
pthread_mutex_destroy(&cam_obj->cam_lock);
g_cam_ctrl.cam_obj[camera_idx] = NULL;
free(cam_obj);
cam_obj = NULL;
pthread_mutex_unlock(&g_intf_lock);
return NULL;
}else{
CDBG("%s: Open succeded\n", __func__);
g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
pthread_mutex_unlock(&g_intf_lock);
return &cam_obj->vtbl;
}
}
到这里才真正的打开了设备节点,到此为止,如果继续深入分析,则要进入驱动程序。
device/moto/shamu/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c
int32_t mm_camera_open(mm_camera_obj_t *my_obj)
{
char dev_name[MM_CAMERA_DEV_NAME_LEN];
int32_t rc = 0;
int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
unsigned int cam_idx = 0;
CDBG("%s: begin\n", __func__);
if (NULL == my_obj) {
goto on_error;
}
snprintf(dev_name, sizeof(dev_name), "/dev/%s",
mm_camera_util_get_dev_name(my_obj->my_hdl));
sscanf(dev_name, "/dev/video%u", &cam_idx);
CDBG_HIGH("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx);
do{
n_try--;
errno = 0;
// 这里真正打开相机设备节点
my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
CDBG("%s: ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
CDBG_HIGH("%s: opened, break out while loop", __func__);
break;
}
ALOGE("%s:Failed with %s error, retrying after %d milli-seconds",
__func__, strerror(errno), sleep_msec);
usleep(sleep_msec * 1000);
}while (n_try > 0);
if (my_obj->ctrl_fd < 0) {
CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
__func__, dev_name, strerror(errno));
rc = -1;
goto on_error;
}
/* 打开 domain socket*/
n_try = MM_CAMERA_DEV_OPEN_TRIES;
do {
n_try--;
my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
CDBG("%s: ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
CDBG("%s: opened, break out while loop", __func__);
break;
}
CDBG("%s:failed with I/O error retrying after %d milli-seconds",
__func__, sleep_msec);
usleep(sleep_msec * 1000);
} while (n_try > 0);
if (my_obj->ds_fd < 0) {
CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
__func__, dev_name, strerror(errno));
rc = -1;
goto on_error;
}
pthread_mutex_init(&my_obj->msg_lock, NULL);
pthread_mutex_init(&my_obj->cb_lock, NULL);
pthread_mutex_init(&my_obj->evt_lock, NULL);
pthread_cond_init(&my_obj->evt_cond, NULL);
CDBG("%s : Launch evt Thread in Cam Open",__func__);
mm_camera_cmd_thread_launch(&my_obj->evt_thread,
mm_camera_dispatch_app_event,
(void *)my_obj);
/* 启动事件轮询线程
* 我们将在用户首次注册 evt 时将 evt fd 添加到事件轮询线程中*/
CDBG("%s : Launch evt Poll Thread in Cam Open", __func__);
mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
MM_CAMERA_POLL_TYPE_EVT);
mm_camera_evt_sub(my_obj, TRUE);
CDBG("%s: end (rc = %d)\n", __func__, rc);
/* 我们不需要在返回之前在这里解锁cam_lock,
* 因为对于打开,它是在intf_lock中完成的 */
return rc;
on_error:
if (NULL == my_obj) {
CDBG_ERROR("%s: Invalid camera object\n", __func__);
rc = -1;
} else {
if (my_obj->ctrl_fd >= 0) {
close(my_obj->ctrl_fd);
my_obj->ctrl_fd = -1;
}
if (my_obj->ds_fd >= 0) {
mm_camera_socket_close(my_obj->ds_fd);
my_obj->ds_fd = -1;
}
}
/* 我们不需要在返回之前在这里解锁cam_lock,
* 因为对于打开,它是在intf_lock中完成的 */
return rc;
}