前言
随着Android系统的不断升级,相机子系统框架也在不断进化,由最初的API1和HAL1到现在的API2和HAL3,由最初简单的拍照,录制到现在的连拍,AI人脸识别;可以说是架构上变动最大最频繁的子系统。
如果您希望通过相机 HAL1 支持性能略低的前置摄像头,并通过相机 HAL3 支持更为高级的后置摄像头,Android 相机服务还支持同时实现两种 HAL1 和 HAL3,
Android 的相机硬件抽象层 (HAL) 可将 Camera Api v2 中较高级别的相机框架 API 连接到底层的相机驱动程序和硬件,相机 HAL 则可提供用于实现您的这些组件版本的接口。
在前面的文章中描述 Android 系统 android.hardware.Camera (api1) 是如何通过JNI接口调用 libcamera_client.so库、管理系统摄像头; 本篇从 CameraManager 看如何使用 android.hardware.Camera2 接口框架来使用相机,Android 应用中涉及到相机类如下:
Android Camera-Camera2
CameraManager 相机系统服务,用于管理和连接相机设备
CameraDevice 相机设备类,和Camera1中的Camera同级
CameraCharacteristics 主要用于获取相机信息,内部携带大量的相机信息,包含摄像头的正反(LENS_FACING)、AE模式、AF模式等,
和Camera1中的Camera.Parameters类似
CaptureRequest 相机捕获图像的设置请求,包含传感器,镜头,闪光灯等
CaptureRequest.Builder CaptureRequest的构造器,使用Builder模式,设置更加方便
CameraCaptureSession 请求抓取相机图像帧的会话,会话的建立主要会建立起一个通道。一个CameraDevice一次只能开启一个CameraCaptureSession。
源端是相机,另一端是 Target,Target可以是Preview,也可以是ImageReader。
ImageReader 用于从相机打开的通道中读取需要的格式的原始图像数据,可以设置多个ImageReader。
用户App 使用 api V2 接口、打开摄像头
用户通过 CameraManager类 openCamera 方法打开摄像头、代码如下:
public static final String CAMERA_SERVICE = "camera";
private void openCamera(int width, int height) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestCameraPermission();
return;
}
setUpCameraOutputs(width, height);
configureTransform(width, height);
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
}
}
源码 manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler); 调用 CameraManager 类的 openCamera()方法内容如下:
@frameworks/base/core/java/android/hardware/camera2/CameraManager.java
@SystemService(Context.CAMERA_SERVICE)
public final class CameraManager {
@SuppressWarnings("unused")
private static final int API_VERSION_1 = 1;
private static final int API_VERSION_2 = 2;
private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;
private static final int CAMERA_TYPE_ALL = 1;
private ArrayList<String> mDeviceIdList;
private final Context mContext;
private final Object mLock = new Object();
public CameraManager(Context context) {
synchronized(mLock) {
mContext = context;
}
}
//> 1. openCamera 方法
@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
}
//> 2 进一步调用 openCameraForUid 函数
public void openCameraForUid(@NonNull String cameraId,
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
int clientUid)
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");
}
}
if (CameraManagerGlobal.sCameraServiceDisabled) {
throw new IllegalArgumentException("No cameras available on device");
}
openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
}
//> 3 最后调用到 openCameraDeviceUserAsync() 函数、返回 CameraDevice 抽象接口类对象
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Handler handler, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
//> 通过 CameraDeviceImpl 获取 ICameraDeviceCallbacks 回调服务
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
handler,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
//> 检查是否服务是否支持 Api V2
if (supportsCamera2ApiLocked(cameraId)) {
//> 获取 "media.camera" 的 ICameraService 服务,
//> Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
//> 4. 通过 cameraService服务 连接到摄像头设备
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid);
} else {
//> 使用 api v1 版本接口
// 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);
}
//> 使用 V1 API 连接到摄像头设备
Log.i(TAG, "Using legacy camera HAL.");
cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
}
} 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.
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
}
源码中关键部分笔者标注了注释,我们看到 supportsCamera2ApiLocked(cameraId) 检查该摄像头的api版本,此处是兼容性设计、我们只关注 API V2版本的过程,
ICameraService cameraService = CameraManagerGlobal.get().getCameraService(); 获取 ICameraService 服务和 ICameraDeviceUser cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid); 过程,成功连接摄像头后,也即是 CameraManager::openCamera() 方法成功打开摄像头过程,用户 App 就可以实现拍照、连续拍照或录像的操作了。
先看如何获取 ICameraService 服务,CameraManagerGlobal 类是 CameraManager 的子类、内容如下:
/**
* A per-process global camera manager instance, to retain a connection to the camera service,
* and to distribute camera availability notices to API-registered callbacks
*/
private static final class CameraManagerGlobal extends ICameraServiceListener.Stub
implements IBinder.DeathRecipient {
private static final String TAG = "CameraManagerGlobal";
private final boolean DEBUG = false;
private final int CAMERA_SERVICE_RECONNECT_DELAY_MS = 1000;
// Singleton instance
private static final CameraManagerGlobal gCameraManager =
new CameraManagerGlobal();
/**
* This must match the ICameraService definition 服务名称 "media.camera"
*/
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
// Camera ID -> Status map
private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
// Registered availablility callbacks and their handlers
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
// torch client binder to set the torch mode with.
private Binder mTorchClientBinder = new Binder();
// Camera ID -> Torch status map
private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>();
// Registered torch callbacks and their handlers
private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap =
new ArrayMap<TorchCallback, Handler>();
private final Object mLock = new Object();
// Access only through getCameraService to deal with binder death
private ICameraService mCameraService;
// Singleton, don't allow construction
private CameraManagerGlobal() {
}
public static final boolean sCameraServiceDisabled =
SystemProperties.getBoolean("config.disable_cameraservice", false);
//> get 静态方法内容
public static CameraManagerGlobal get() {
return gCameraManager;
}
@Override
public IBinder asBinder() {
return this;
}
/**
* Return a best-effort ICameraService.
*
* <p>This will be null if the camera service is not currently available. If the camera
* service has died since the last use of the camera service, will try to reconnect to the
* service.</p>
*/
public ICameraService getCameraService() {
synchronized(mLock) {
connectCameraServiceLocked();
if (mCameraService == null && !sCameraServiceDisabled) {
Log.e(TAG, "Camera service is unavailable");
}
return mCameraService;
}
}
/**
* Connect to the camera service if it's available, and set up listeners.
* If the service is already connected, do nothing.
*
* <p>Sets mCameraService to a valid pointer or null if the connection does not succeed.</p>
*/
private void connectCameraServiceLocked() {
// Only reconnect if necessary
if (mCameraService != null || sCameraServiceDisabled) return;
Log.i(TAG, "Connecting to camera service");
//> 获取 "media.camera" 名称的服务
IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
if (cameraServiceBinder == null) {
// Camera service is now down, leave mCameraService as null
return;
}
try {
cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
return;
}
//> 通过 ICameraService.Stub.asInterface() 把 cameraServiceBinder 转化为 ICameraService 代理
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
try {
CameraMetadataNative.setupGlobalVendorTagDescriptor();
} catch (ServiceSpecificException e) {
handleRecoverableSetupErrors(e);
}
try {
CameraStatus[] cameraStatuses = cameraService.addListener(this);
for (CameraStatus c : cameraStatuses) {
onStatusChangedLocked(c.status, c.cameraId);
}
//> 把 cameraService 保存起来
mCameraService = cameraService;
} catch(ServiceSpecificException e) {
// Unexpected failure
throw new IllegalStateException("Failed to register a camera service listener", e);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
}
源码 ICameraService.Stub.asInterface() 做了什么转化,代码如下:
源码路径:@out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/dotdot/av/camera/aidl/android/hardware/ICameraService.java
文件 ICameraService.java 是由 @frameworks/av/camera/aidl/android/hardware/ICameraService.aidl 文件内容编译系统自动生成的内容、如下:
public interface ICameraService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.hardware.ICameraService
{
private static final java.lang.String DESCRIPTOR = "android.hardware.ICameraService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
private static class Proxy implements android.hardware.ICameraService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
}
/**
* Cast an IBinder object into an android.hardware.ICameraService interface,
* generating a proxy if needed.
*/
public static android.hardware.ICameraService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.hardware.ICameraService))) {
return ((android.hardware.ICameraService)iin);
}
return new android.hardware.ICameraService.Stub.Proxy(obj);
}
通过 Stub.asInterface() 就生成 ICameraService 代理服务,
接下来 ICameraDeviceUser cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid);把 android.os.Parcel 内容给了谁呢?
连接谁呢? 内容如下:
/**
* Open a camera device through the new camera API
* Only supported for device HAL versions >= 3.2
*/
@Override public android.hardware.camera2.ICameraDeviceUser connectDevice(android.hardware.camera2.ICameraDeviceCallbacks callbacks, java.lang.String cameraId, java.lang.String opPackageName, int clientUid) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.hardware.camera2.ICameraDeviceUser _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((callbacks!=null))?(callbacks.asBinder()):(null)));
_data.writeString(cameraId);
_data.writeString(opPackageName);
_data.writeInt(clientUid);
mRemote.transact(Stub.TRANSACTION_connectDevice, _data, _reply, 0);
_reply.readException();
_result = android.hardware.camera2.ICameraDeviceUser.Stub.asInterface(_reply.readStrongBinder());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
网上很多关于 Camera 框架的描述博客、都没有描述这个过程,就直接跳转到 CameraService 侧的 CameraService::connectDevice() 代码上,
分析 CameraService::connectDevice 是如何创建 CameraClient 的过程。
我们一起梳理这块内容:
分析如下:
//> 获取 "media.camera" 名称的服务, cameraServiceBinder 对象持有 BnInterface
IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
//> 通过 ICameraService.Stub.asInterface() 把 cameraServiceBinder 转化为 ICameraService 代理
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
代理就是 ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME) 获取到的服务,就是 “media.camera” 服务;ICameraServer 所持有的 mRemote 是 ICameraService 对象,通过 Stub.TRANSACTION_connectDevice 命令、使用transact方法发送给
CameraService 的服务端、服务端解码后、调用 CameraService::connectDevice() 代码来处理;代码如下:
代码路径:@@out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_arm64_armv8-a_cortex-a53_shared_core/
gen/aidl/android/hardware/ICameraService.cpp
::android::status_t BnCameraService::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags)
{
::android::status_t _aidl_ret_status = ::android::OK;
switch (_aidl_code) {
case Call::CONNECTDEVICE:
{
::android::sp<::android::hardware::camera2::ICameraDeviceCallbacks> in_callbacks;
::android::String16 in_cameraId;
::android::String16 in_opPackageName;
int32_t in_clientUid;
::android::sp<::android::hardware::camera2::ICameraDeviceUser> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readStrongBinder(&in_callbacks);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readString16(&in_cameraId);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readString16(&in_opPackageName);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_clientUid);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
//> 此处调用 connectDevice(in_callbacks, in_cameraId, in_opPackageName, in_clientUid, &_aidl_return)
::android::binder::Status _aidl_status(connectDevice(in_callbacks, in_cameraId, in_opPackageName, in_clientUid, &_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::camera2::ICameraDeviceUser::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
case Call::CONNECTLEGACY:
{
::android::sp<::android::hardware::ICameraClient> in_client;
int32_t in_cameraId;
int32_t in_halVersion;
::android::String16 in_opPackageName;
int32_t in_clientUid;
::android::sp<::android::hardware::ICamera> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readStrongBinder(&in_client);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_cameraId);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_halVersion);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readString16(&in_opPackageName);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_clientUid);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
::android::binder::Status _aidl_status(connectLegacy(in_client, in_cameraId, in_halVersion, in_opPackageName, in_clientUid, &_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::ICamera::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
default:
{
_aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
}
break;
}
if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
_aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
}
return _aidl_ret_status;
}
那接下来看看 CameraService 服务端的 connectDevice() 代码,内容如下:
源码路径:@frameworks/av/services/camera/libcameraservcie/CameraService.cpp 中 connectDevice 方法内容如下:
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();
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
clientUid, USE_CALLING_PID, API_2,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
该方法中调用 connectHelper() 来连接摄像头,代码如下:
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, 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));
sp<CLIENT> client = nullptr;
{
// Acquire mServiceLock and prevent other clients from connecting
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;
}
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
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
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());
}
//> 1. 创建 CameraClient
sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, 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__);
//> 2. 初始化 client
err = client->initialize(mCameraProviderManager);
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
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
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;
}
代码调用 makeClient() 和 client->initialize() 函数,打开相机就完成了。
我们先看 makeClient() 创建不同 hal 版本的 BasicClient 的相机。
Status 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) {
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, cameraIdToInt(cameraId),
facing, clientPid, clientUid, getpid(), legacyMode);
} 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:
if (effectiveApiLevel == API_1) {
// Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
} 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, cameraIdToInt(cameraId),
facing, clientPid, clientUid, servicePid, legacyMode);
} 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();
}
代码中创建 client 有 CameraClient()、Camera2Client() 和 CameraDeviceClient() 方法,根据相机 HAL 中的 deviceVersion 描述的内容,分别对应起来;
我关注的 CameraDeviceClient() 是 API_2 的方法, 因笔者虚拟摄像头就使用api V2 .
源码路径: @frameworks/av/services/camera/libcameraservcie/api2/CameraDeviceClient.h
class CameraDeviceClient :
public Camera2ClientBase<CameraDeviceClientBase>,
public camera2::FrameProcessorBase::FilteredListener
{
public:
/**
* ICameraDeviceUser interface (see ICameraDeviceUser for details)
*/
// Note that the callee gets a copy of the metadata.
virtual binder::Status submitRequest(
const hardware::camera2::CaptureRequest& request,
bool streaming = false,
/*out*/
hardware::camera2::utils::SubmitInfo *submitInfo = nullptr) override;
virtual binder::Status createStream(
const hardware::camera2::params::OutputConfiguration &outputConfiguration,
/*out*/
int32_t* newStreamId = NULL) override;
// Create an input stream of width, height, and format.
virtual binder::Status createInputStream(int width, int height, int format,
/*out*/
int32_t* newStreamId = NULL) override;
/**
* Interface used by CameraService
*/
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);
}
源码路径: @frameworks/av/services/camera/libcameraservcie/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, cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
//> 初始化函数
status_t CameraDeviceClient::initialize(sp<CameraProviderManager> 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;
}
构造函数和初始化函数都调用 Camera2ClientBase 类的方法.源码如下:
源码路径:@frameworks/av/services/libcameraservcie/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 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.");
}
//> 初始化函数
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::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<CameraDeviceBase::NotificationListener> weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
构造方法中 new Camera3Device(cameraId) 相机,
源码路径:@frameworks/av/services/camera/libcameraservcie/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),
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());
}
//> 初始化函数
status_t Camera3Device::initialize(sp<CameraProviderManager> 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<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 retrive camera characteristics: %s (%d)", strerror(-res), res);
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 (auto iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
mInterface = new HalInterface(session, queue);
std::string providerType;
mVendorTagId = manager->getProviderTagIdLocked(mId.string());
return initializeCommonLocked();
}
由上面的构建函数和初始化函数、我们看到 ICameraDeviceSession、mResultMetadataQueue 等新特征变量内容,在看看 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();
/** Create buffer manager */
mBufferManager = new Camera3BufferManager();
mTagMonitor.initialize(mVendorTagId);
/** Start up request queue thread */
mRequestThread = new RequestThread(this, mStatusTracker, mInterface);
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]));
}
}
return OK;
}
HAL 3 相机子系统将多个运行模式整合为一个统一的视图,您可以使用这种视图实现之前的任何模式以及一些其他模式,例如连拍模式。这样一来,便可以提高用户对聚焦、曝光以及更多后期处理(例如降噪、对比度和锐化)效果的控制能力。此外,这种简化的视图还能够使应用开发者更轻松地使用相机的各种功能。