1,CameraManager介绍
CameraManager是Android系统中的一项服务,主要用于检测和打开相机,以及获取相机设备的特性。它是在Android 5.0(API级别21)及以上版本中引入的,属于android.hardware.camera2包。
要获取CameraManager实例,可以通过Context类的getSystemService()方法来实现,参数可以使用Context.CAMERA_SERVICE或CameraManager.class。此外,根据最新的Android系统框架,CameraManager运行在app进程中,与camera server进程和hal进程(provider进程)共同构成了Android的Camera整体框架。
在实际编程过程中,可以直接使用CameraManager类的相关函数,例如:openCamera(), setTorchMode(), startFaceDetection(), stopFaceDetection()等。此外,CameraManager还提供了一些回调函数,如AvailabilityCallback, TorchCallback等,以便于开发者对相机的状态进行监测和控制。
2,CameraCharacteristics介绍
CameraCharacteristics是Android系统中一个专门用于描述相机设备属性的类,其中的属性对于指定的CameraCharacteristics是Android系统中一个专门用于描述相机设备属性的类,其中的属性对于指定的CameraDevice而言是固定的。此类继承自CameraMetadata类,类似于旧版API中的CameraInfo类。
在CameraCharacteristics中,开发者可以找到各种与相机硬件相关的参数和设置,例如:曝光补偿(Exposure compensation)、自动曝光/自动对焦/自动白平衡模式(AE / AF / AWB mode)、自动曝光/自动白平衡范围、最小/最大亮度值、最大帧率等。这些属性的具体数值可以通过CameraManager接口的getCameraCharacteristics方法进行查询。
3,CameraDeviceImpl.java介绍
CameraDeviceImpl.java是Android系统中一个关键的类,它实现了android.hardware.camera2.CameraDevice接口。这个接口代表了一个连接的相机设备,你可以把它看作为相机设备在 java 代码中的表现,类似于旧版API中的Camera类。
CameraDeviceImpl的主要作用是建立与Camera框架的连接,负责管理相机设备的状态和配置信息。为了实现这一目标,它借助JNI层进行Java到C++的转换,到达native层,然后在native层通过实现CameraClient来与Camera系统进行交互。
在实际编程过程中,当调用CameraManager的openCamera()方法时,会返回一个CameraDevice对象。如果成功,该对象就代表了应用程序与相机硬件之间的一个连接。开发者可以通过这个对象的方法和回调来控制相机的各种功能,如拍照、录像等。
4,CameraCaptureSessionImpl.java介绍
CameraCaptureSessionImpl.java是Android系统中一个关键的类,它实现了android.hardware.camera2.CameraCaptureSession接口。这个接口代表了一个与相机设备进行通信的会话,我们可以将其看作为在Java代码中相机设备的表现,类似于旧版API中的Camera类。
CameraCaptureSession的主要作用是用来向相机设备发送获取图像的请求。它主要有setRepeatingRequest()和capture()两种方法。其中,setRepeatingRequest()用于重复请求获取图像数据,常用于预览或连拍;capture()则用于获取一次图像,常用于单张拍照。值得注意的是,CameraCaptureSession是一个抽象类,其直接的实现类为CameraConstrainedHighSpeedCaptureSession。
在实际编程过程中,当调用CameraManager的openCamera()方法时,会返回一个CameraDevice对象。如果成功,该对象就代表了应用程序与相机硬件之间的一个连接。开发者可以通过这个对象的方法和回调来控制相机的各种功能,如拍照、录像等。例如,当需要创建新的CameraCaptureSession时,会先判断当前CameraDevice是否已经存在一个active的CameraCaptureSession对象。如果有的话,就会先关闭这个session对象,然后再创建新的session对象。此外,一旦新的CameraCaptureSession创建完成,App便可以通过它向底层发送CaptureRequest。
5,CaptureRequest.java介绍
CaptureRequest在Android系统中是一个关键的类,主要用于表示对相机底层的捕捉请求。我们可以为预览、拍照等不同的场景创建不同的CaptureRequest,并为其配置各种属性,例如:预览分辨率、预览目标、对焦模式和曝光模式等。
具体来说,一个CaptureRequest包含了两部分内容:Settings和Output Surfaces。Settings部分包含了硬件相关的参数,比如sensor, lens, flash等,以及ISP Processing Pipeline相关参数和3A相关参数。这些参数都是用于告诉Camera底层如何处理某一帧数据的。而Output Surfaces则是指CaptureRequest中带的Surfaces,这些Surfaces必须在创建CameraCaptureSession时使用的Surface List的子集。
在实际编程过程中,可以通过CameraCaptureSession的createCaptureRequest()方法来获取CaptureRequest对象。一旦新的CaptureRequest创建完成,App便可以通过它向底层发送请求以获取图像数据。
7,Camera open在framework中的代码实现
camera open在CameraManager中代码实现过程
1,获取camera的logic ID信息的时候实现如下
public String[] getCameraIdList() {
String[] cameraIds = null;
synchronized (mLock) {
// Try to make sure we have an up-to-date list of camera devices.
connectCameraServiceLocked();
cameraIds = extractCameraIdListLocked();
}
sortCameraIds(cameraIds);
return cameraIds;
}
这里先拿到cameraservice的接口,然后拿到camera的连接状态和ID,如下:
private void connectCameraServiceLocked() {
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
try {
CameraStatus[] cameraStatuses = cameraService.addListener(this);
for (CameraStatus c : cameraStatuses) {
onStatusChangedLocked(c.status, c.cameraId);
}
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
}
}
这个将拿到的状态和ID添加到devicestatus表中,如下:
private void onStatusChangedLocked(int status, String id) {
Integer oldStatus;
if (status == ICameraServiceListener.STATUS_NOT_PRESENT) {
oldStatus = mDeviceStatus.remove(id);
mUnavailablePhysicalDevices.remove(id);
} else {
oldStatus = mDeviceStatus.put(id, status);
if (oldStatus == null) {
mUnavailablePhysicalDevices.put(id, new ArrayList<String>());
}
}
} // onStatusChangedLocked
如上就可以拿到cameraID。
2,获取camerametadata的代码实现过程,CameraCharacteristics 调用:
public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId)
throws CameraAccessException {
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
Size displaySize = getDisplaySize();
CameraMetadataNative info = cameraService.getCameraCharacteristics(cameraId,
mContext.getApplicationInfo().targetSdkVersion);
characteristics = new CameraCharacteristics(info);
return characteristics;
}
这个拿到cameraservice后直接获取到camerametadata,在封装到CameraCharacteristics。这里就可以通过tagID就看获取到metadata的数据信息。
3,openCamera调用:
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);
}
private CameraDevice openCameraDeviceUserAsync(String cameraId,
CameraDevice.StateCallback callback, Executor executor, final int uid,
final int oomScoreOffset) throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
Map<String, CameraCharacteristics> physicalIdsToChars =
getPhysicalIdToCharsMap(characteristics);
synchronized (mLock) {
ICameraDeviceUser cameraUser = null;
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
executor,
characteristics,
physicalIdsToChars,
mContext.getApplicationInfo().targetSdkVersion,
mContext);
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
cameraUser = cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), mContext.getAttributionTag(), uid,
oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
} deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
这个先创建了CameraDeviceImpl对象,接着调用cameraservice的connectDevice拿到service端的cameradevice接口。然后将这个接口设置给CameraDeviceImpl,如下:
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
synchronized(mInterfaceLock) {
// TODO: Move from decorator to direct binder-mediated exceptions
// If setRemoteFailure already called, do nothing
if (mInError) return;
mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
mDeviceExecutor.execute(mCallOnOpened);
mDeviceExecutor.execute(mCallOnUnconfigured);
}
}
这里就回调app callback,这样app端就拿到cameradevice这个接口了。如下:
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
};
4,createCaptureSession调用:在app拿到cameradevice后就可以创建capturesession了,如下:
private void createCaptureSessionInternal(InputConfiguration inputConfig,
List<OutputConfiguration> outputConfigurations,
CameraCaptureSession.StateCallback callback, Executor executor,
int operatingMode, CaptureRequest sessionParams) throws CameraAccessException {
newSession = new CameraCaptureSessionImpl(mNextSessionId++, input,
callback, executor, this, mDeviceExecutor, configureSuccess);
// TODO: wait until current session closes, then create the new session
mCurrentSession = newSession;
mSessionStateCallback = mCurrentSession.getDeviceStateCallback();
}
}
这里就是创建CameraCaptureSession,如下:
CameraCaptureSessionImpl(int id, Surface input,
CameraCaptureSession.StateCallback callback, Executor stateExecutor,
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
Executor deviceStateExecutor, boolean configureSuccess) {
mStateCallback = createUserStateCallbackProxy(mStateExecutor, callback);
if (configureSuccess) {
mStateCallback.onConfigured(this);
if (DEBUG) Log.v(TAG, mIdString + "Created session successfully");
mConfigureSuccess = true;
} else {
mStateCallback.onConfigureFailed(this);
mClosed = true; // do not fire any other callbacks, do not allow any other work
Log.e(TAG, mIdString + "Failed to create capture session; configuration failed");
mConfigureSuccess = false;
}
}
到这里app端就可以获取到capturesession了。
5,CaptureRequest调用:这块就是操作camerametadata相关接口,如下:
public CaptureRequest.Builder createCaptureRequest(int templateType)
throws CameraAccessException {
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
CameraMetadataNative templatedRequest = null;
templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
CaptureRequest.Builder builder = new CaptureRequest.Builder(
templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE,
getId(), /*physicalCameraIdSet*/ null);
return builder;
}
}
public Builder(CameraMetadataNative template, boolean reprocess,
int reprocessableSessionId, String logicalCameraId,
Set<String> physicalCameraIdSet) {
mRequest = new CaptureRequest(template, reprocess, reprocessableSessionId,
logicalCameraId, physicalCameraIdSet);
}
capturerequest主要是camerametadata相关操作。
6,camera preview request调用:
public int setRepeatingBurst(List<CaptureRequest> requests,
CaptureCallback callback, Handler handler) throws CameraAccessException {
return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
}
}
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback,
Executor executor) throws CameraAccessException {
return submitCaptureRequest(requests, callback, executor, /*streaming*/true);
}
private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
Executor executor, boolean repeating) throws CameraAccessException {
CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
}
这块就是把capturerequest传递到cameraservice端的cameradevice中,进行下一步的处理。
到这来整个open过程在framework里面cameramanager的调用过程就实现了。
7,总结框架
你的鼓励将是我创作的最大动力