基于Android P版本分析
基于Android Camera2 openCamera流程分析
openCamera流程图:
openCamera整体流程的时序图:
整个过程中涉及到的类之间的关联关系:
1.openCamera()
less
@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);
}
CameraManager.openCamera直接调用了openCameraForUid()方法,其中USE_CALLING_UID是CameraManager定义的常量值,值为-1;
2.openCameraForUid()
less
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);
}
在该方法中对cameraId和callback进行判空,然后对CameraService的状态进行判断(该值在CameraManager类中定义),最后调用openCameraDeviceUserAsync()方法。
在openCameraDeviceUserAsync()方法的第三个参数为Executor类型的对象,这个其实是根据之前传入的handler获取的,获取方式为:CameraDeviceImpl.checkAndWrapHandler(handler),
typescript
public static Executor checkAndWrapHandler(Handler handler) {
return new CameraHandlerExecutor(checkHandler(handler));
}
java
private static class CameraHandlerExecutor implements Executor {
private final Handler mHandler;
public CameraHandlerExecutor(@NonNull Handler handler) {
mHandler = Preconditions.checkNotNull(handler);
}
@Override
public void execute(Runnable command) {
// Return value of 'post()' will be ignored in order to keep the
// same camera behavior. For further details see b/74605221 .
mHandler.post(command);
}
}
其实最终就是通过调用CameraHandlerExecutor.execute()方法进行handler的callback回调;
3.openCameraDeviceUserAsync()
java
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;
//创建了Camera Client,即deviceImpl,此对象也就是通过onOpened()回调返回的device对象;
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
callback,
executor,
characteristics,
mContext.getApplicationInfo().targetSdkVersion);
// 该CallBack最终会传到HAL层,HAL通过该callback进行的result回调
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
try {
//判断是否支持Camera2的接口,即是否支持camera2.0的协议
if (supportsCamera2ApiLocked(cameraId)) {
// Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
//1.获取ICameraService对象
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
if (cameraService == null) {
throw new ServiceSpecificException(
ICameraService.ERROR_DISCONNECTED,
"Camera service is currently unavailable");
}
//这一步就是最关键的一步,用于将刚刚创建好的deviceImpl对象和CameraService关联起来
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);
}
} catch (ServiceSpecificException e) {
......
}
//2.在这一步中,最终会执行mDeviceCallback中的onOpened()回调方法,返回deviceImpl对象
deviceImpl.setRemoteDevice(cameraUser);
device = deviceImpl;
}
return device;
}
3.1 CameraManagerGlobal类分析
java
private static final class CameraManagerGlobal extends ICameraServiceListener.Stub
implements IBinder.DeathRecipient {
private static final String TAG = "CameraManagerGlobal";
private final int CAMERA_SERVICE_RECONNECT_DELAY_MS = 1000;
private static final CameraManagerGlobal gCameraManager =
new CameraManagerGlobal();
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
private final ScheduledExecutorService mScheduler = Executors.newScheduledThreadPool(1);
private Binder mTorchClientBinder = new Binder();
private final Object mLock = new Object();
private ICameraService mCameraService;
private CameraManagerGlobal() {
}
public static final boolean sCameraServiceDisabled =
SystemProperties.getBoolean("config.disable_cameraservice", false);
public static CameraManagerGlobal get() {
return gCameraManager;
}
@Override
public IBinder asBinder() {
return this;
}
public ICameraService getCameraService() {
synchronized(mLock) {
connectCameraServiceLocked();
if (mCameraService == null && !sCameraServiceDisabled) {
Log.e(TAG, "Camera service is unavailable");
}
return mCameraService;
}
}
}
通过aidl的方式,获取CameraService,使用的是单例模式,保证全局只有一个CameraService实例。
3.2 deviceImpl.setRemoteDevice()
ini
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;
......
}
在初始化deviceImpl对象的时候,mDeviceExecutor变量被赋值为通过handler参数创建的Executor对象,mDeviceCallback被赋值为了openCamera传入的callback参数;
scss
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
synchronized(mInterfaceLock) {
......
mDeviceExecutor.execute(mCallOnOpened);
mDeviceExecutor.execute(mCallOnUnconfigured);
}
}
在setRemoteDevice()方法最后,执行了execute()方法,即CameraHandlerExecutor.execute()方法执行了mCallOnopened回调;
mCallOnopened回调定义:
java
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
......
mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
}
最后调用了mDeviceCallback.onOpened()方法,即openCamera时传入的callback参数的回调方法;
4.cameraService.connectDevice()
这一步是openCamera过程中最重要的一环。
主要做了两件事情:
- 一个是创建CameraDeviceClient;
- 一个是对CameraDeviceClient进行初始化,并将其给Framework;
less
cameraService.connectDevice(callbacks, cameraId,
mContext.getOpPackageName(), uid)
分别有4个参数:
callbacks:这个callbacks是在CameraDeviceImpl类中定义的一个CameraDeviceCallbacks类型的回调;
cameraId:openCamera()方法中传入的cameraId
mContext.getOpPackageName():当前所在进程的packageName
ini
mOpPackageName = ActivityThread.currentPackageName();
uid:openCamera()方法中传入的uid,即USE_CALLING_UID;
php
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,
/*api1CameraId*/-1,
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;
}
在connectDevice()方法中,主要执行了connectHelper()方法,然后将client对象地址赋值给device(类型为ICameraDeviceUser),返回device。
5.connectHelper()
这个方法里面,主要处理了一些连接的情况,例如Camera占用、flush、预开启等情况
arduino
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 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;
{
......
// 1.检查当前CameraId指向的device是否可用,只是简单的判断device是否存在
// 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;
// 2.处理camera独占情况,是进行相机多进程互斥逻辑的方法。多个应用无法同时打开相机就是在这个方法中进行管理的
if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
switch (err) {
// err异常情况处理
......
}
}
if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
device = static_cast<CLIENT*>(clientTmp.get());
return ret;
}
// 3.预备连接CameraDevice,必要时给手电筒关闭设备的机会
// give flashlight a chance to close devices if necessary.
mFlashlight->prepareDeviceOpen(cameraId);
int facing = -1;
// 获取当前camera device的version版本,即HAL版本
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;
// 4.根据device version创建对应的CameraDeviceClient对象
if(!(ret = makeClient(this, cameraCb, clientPackageName,
cameraId, api1CameraId, 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__);
// 5.通过CameraProviderManager与Camera 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) {
// err异常情况处理
......
}
}
// 省略
......
} // 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;
}
5.1 validateConnectLocked()
判断当前cameraId指向的device是否可用;
c
Status CameraService::validateConnectLocked(const String8& cameraId,
const String8& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid,
/*out*/int& originalClientPid) const {
......
int callingPid = getCallingPid();
// 1
if (!mInitialized) {
ALOGE("CameraService::connect X (PID %d) rejected (camera HAL module not loaded)",
callingPid);
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera HAL module available to open camera device "%s"", cameraId.string());
}
// 2
if (getCameraState(cameraId) == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
cameraId.string());
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID "%s" available", cameraId.string());
}
// 3
status_t err = checkIfDeviceIsUsable(cameraId);
if (err != NO_ERROR) {
switch(err) {
case -ENODEV:
case -EBUSY:
return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
"No camera device with ID "%s" currently available", cameraId.string());
default:
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Unknown error connecting to ID "%s"", cameraId.string());
}
}
return Status::ok();
}
1.首先判断Camera HAL层的module模块是否已经初始化mInitialized,这个值是在启动CameraService时调用CameraProviderManager::ProviderInfo::initialize()函数中赋值的;
2.然后判断CameraState是否为空,CameraState内部实现了CameraParameters的get、set方法。如果不为空,那么通过取得的cameraState对象就能够得到CameraParameters,从而得到相机各种size相关的参数,例如fps range、preview sizes、video sizes等;
3.最后通过checkIfDeviceIsUsable()判断相机是否已经被占用,如果对应camera id的相机正常就返回状态NO_ERROR。
scss
status_t CameraService::checkIfDeviceIsUsable(const String8& cameraId) const {
auto cameraState = getCameraState(cameraId);
int callingPid = getCallingPid();
if (cameraState == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
cameraId.string());
return -ENODEV;
}
StatusInternal currentStatus = cameraState->getStatus();
if (currentStatus == StatusInternal::NOT_PRESENT) {
ALOGE("CameraService::connect X (PID %d) rejected (camera %s is not connected)",
callingPid, cameraId.string());
return -ENODEV;
} else if (currentStatus == StatusInternal::ENUMERATING) {
ALOGE("CameraService::connect X (PID %d) rejected, (camera %s is initializing)",
callingPid, cameraId.string());
return -EBUSY;
}
return NO_ERROR;
}
5.2 handleEvictionsLocked()
这个方法主要是行相机多进程互斥逻辑的方法。多个应用无法同时打开相机就是在这个方法中进行管理的;
根据相机使用的经历,我们可知:
1.两个应用不能同时打开同一个camera device;
2.同一个应用,根据平台不同(高通、MTK),不一定能同时打开两个camera device;
3.分屏模式下两个应用分别打开不同的相机,哪个应用获得焦点,哪个应用的相机可以活动,另一个无法活动;
c
// Get current active client PIDs
std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
ownerPids.push_back(clientPid);
std::vector<int> priorityScores(ownerPids.size());
std::vector<int> states(ownerPids.size());
// Get priority scores of all active PIDs
status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
ownerPids.size(), &ownerPids[0], /*out*/&states[0],
/*out*/&priorityScores[0]);
if (err != OK) {
ALOGE("%s: Priority score query failed: %d",
__FUNCTION__, err);
return err;
}
// Update all active clients' priorities
std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
for (size_t i = 0; i < ownerPids.size() - 1; i++) {
pidToPriorityMap.emplace(ownerPids[i],
resource_policy::ClientPriority(priorityScores[i], states[i]));
}
mActiveClientManager.updatePriorities(pidToPriorityMap);
获取所有活动进程的优先级,并将优先级更新到mActiveClientManager中;
mActiveClientManager对象是CameraClientManager类型的,继承了ClientManager、BasicClient和ClientEventListener,其中BasicClient和ClientEventListener都是CameraService的内部类;
Listener监听client的add和remove操作。BasicClient定义了CameraClient的一些基本操作,CameraDeviceClientBase类继承了BasicClient,所以这个类实际上是所有CameraClient的父类;
ClientManager类是对client进行管理的类,内部定义了一个client的描述类ClientDescriptor,包括key(这个key实际上就是camera id,在冲突处理中将全使用key来表示)、value、cost、ownerId、priority和conflicting等属性。ClientManager类就围绕被add进来的client进行属性的get、set等操作;
scss
// Get state for the given cameraId
auto state = getCameraState(cameraId);
if (state == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (no camera device with ID %s)",
clientPid, cameraId.string());
// Should never get here because validateConnectLocked should have errored out
return BAD_VALUE;
}
在更新过优先级之后,就去获取Camera的状态;
注:所有相机的状态在camera service启动的时候就已经被获取了,所以在CameraService中直接调用getCameraState方法就可以得到指定id的状态;
scss
// Make descriptor for incoming client
clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
state->getConflicting(),
priorityScores[priorityScores.size() - 1],
clientPid,
states[states.size() - 1]);
接下来根据前面两步获取到的优先级、CameraState等信息构建clientDescriptor对象;
scss
//查找冲突的client
/*
冲突的关键条件:
1.id相同必然冲突
2.totalCost超过最大maxCost必然冲突;
3.底层冲突;
*/
// Find clients that would be evicted
auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
// If the incoming client was 'evicted,' higher priority clients have the camera in the
// background, so we cannot do evictions
if (std::find(evicted.begin(), evicted.end(), clientDescriptor) != evicted.end()) {
ALOGE("CameraService::connect X (PID %d) rejected (existing client(s) with higher"
" priority).", clientPid);
sp<BasicClient> clientSp = clientDescriptor->getValue();
String8 curTime = getFormattedCurrentTime();
auto incompatibleClients =
mActiveClientManager.getIncompatibleClients(clientDescriptor);
String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
"(PID %d, score %d state %d) due to eviction policy", curTime.string(),
cameraId.string(), packageName.string(), clientPid,
priorityScores[priorityScores.size() - 1],
states[states.size() - 1]);
for (auto& i : incompatibleClients) {
msg.appendFormat("\n - Blocked by existing device %s client for package %s"
"(PID %" PRId32 ", score %" PRId32 ", state %" PRId32 ")",
i->getKey().string(),
String8{i->getValue()->getPackageName()}.string(),
i->getOwnerId(), i->getPriority().getScore(),
i->getPriority().getState());
ALOGE(" Conflicts with: Device %s, client package %s (PID %"
PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().string(),
String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
i->getPriority().getScore(), i->getPriority().getState());
}
// Log the client's attempt
Mutex::Autolock l(mLogLock);
mEventLog.add(msg);
return -EBUSY;
}
查找与这个clientDescriptor冲突的client,返回的是一个vector队列。此后方法进入到冲突处理阶段,如果冲突的client在这个队列中,就不能打开相机,给出提示,方法返回;
scss
for (auto& i : evicted) {
sp<BasicClient> clientSp = i->getValue();
if (clientSp.get() == nullptr) {
ALOGE("%s: Invalid state: Null client in active client list.", __FUNCTION__);
// TODO: Remove this
LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, null client in active list",
__FUNCTION__);
mActiveClientManager.remove(i);
continue;
}
ALOGE("CameraService::connect evicting conflicting client for camera ID %s",
i->getKey().string());
evictedClients.push_back(i);
// Log the clients evicted
logEvent(String8::format("EVICT device %s client held by package %s (PID"
" %" PRId32 ", score %" PRId32 ", state %" PRId32 ")\n - Evicted by device %s client for"
" package %s (PID %d, score %" PRId32 ", state %" PRId32 ")",
i->getKey().string(), String8{clientSp->getPackageName()}.string(),
i->getOwnerId(), i->getPriority().getScore(),
i->getPriority().getState(), cameraId.string(),
packageName.string(), clientPid,
priorityScores[priorityScores.size() - 1],
states[states.size() - 1]));
// Notify the client of disconnection
clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
CaptureResultExtras());
}
如果当前client不在evicted冲突队列中,说明当前应用与其他应用已经打开的相机存在冲突,但是当前相机应用优先级高,cameraservice会将之前被其他应用打开的相机关闭;
5.3 prepareDeviceOpen()
scss
status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
ALOGV("%s: prepare for device open", __FUNCTION__);
Mutex::Autolock l(mLock);
if (!mFlashlightMapInitialized) {
ALOGE("%s: findFlashUnits() must be called before this method.",
__FUNCTION__);
return NO_INIT;
}
if (isBackwardCompatibleMode(cameraId)) {
// framework is going to open a camera device, all flash light control
// should be closed for backward compatible support.
// 关闭所有闪光灯的控制
mFlashControl.clear();
if (mOpenedCameraIds.size() == 0) {
// notify torch unavailable for all cameras with a flash
// 关闭所有已打开的手电筒
std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
int numCameras = static_cast<int>(ids.size());
for (int i = 0; i < numCameras; i++) {
String8 id8(ids[i].c_str());
if (hasFlashUnitLocked(id8)) {
mCallbacks->onTorchStatusChanged(
id8, TorchModeStatus::NOT_AVAILABLE);
}
}
}
// close flash control that may be opened by calling hasFlashUnitLocked.
mFlashControl.clear();
}
if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
mOpenedCameraIds.add(cameraId);
}
return OK;
}
相机打开的情况下,闪光灯的控制必须交由相机控制,所以此时会关闭所有闪光灯的控制,如果手电筒打开,就会在此时被关闭;
5.4 makeClient()
在makeClient()方法之前,首先会调用getDeviceVersion方法取得对应底层HAL的版本(可以简单的理解为HAL3的小版本【3.2或者是3.4】),根据Device version调用makeClient()方法创建Camera Client对象;
php
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,
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,
api1CameraId, 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,
cameraId, api1CameraId,
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,
api1CameraId, 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();
}
makeClient()方法主要有2个操作:
1.判断API+HAL版本组合,并根据判定结果决定创建对应的client;
client有3种类型:CameraClient、Camera2Client以及CameraDeviceClient;
API1+HAL3->CameraClient
API1+HAL3->Camera2Client
API2+HAL3->CameraDeviceClient
2.将应用层传入的callback(这个callbacks是在CameraDeviceImpl类中定义的一个CameraDeviceCallbacks类型的回调)存入到CameraDeviceClient中,这样一旦有结果就可以将结果通过回调传给Framework;
5.5 client->initialize()
我们以API2+HAL3->CameraDeviceClient为例。
arduino
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;
// 调用父类Camera2ClientBase的initialize方法进行初始化
res = Camera2ClientBase::initialize(providerPtr, monitorTags);
if (res != OK) {
return res;
}
String8 threadName;
// FrameProcessor 的创建与初始化配置,用来处理预览帧的,他继承了Thread类
mFrameProcessor = new FrameProcessorBase(mDevice);
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
mFrameProcessor->run(threadName.string());
// 将CameraDeviceClient注册到FrameProcessorBase内部,建立了与CameraDeviceClient的联系
mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
return OK;
}
mFrameProcessor赋值,从该成员的命名上就可以看出来,它就是用来处理预览帧的,它是继承了Thread类的,我们看到相机的预览实际就是它在一个无限循环当中不断的处理request来完成的;
实例化FrameProcessorBase对象并且将内部的Camera3Device对象传入其中,这样就建立了FrameProcessorBase和Camera3Device的联系,之后将内部线程运行起来,等待来自Camera3Device的结果;
scss
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Camera2-FrameProcessorBase"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Trace.h>
#include "common/FrameProcessorBase.h"
#include "common/CameraDeviceBase.h"
namespace android {
namespace camera2 {
FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
Thread(/*canCallJava*/false),
mDevice(device),
mNumPartialResults(1) {
sp<CameraDeviceBase> cameraDevice = device.promote();
if (cameraDevice != 0) {
CameraMetadata staticInfo = cameraDevice->info();
camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
if (entry.count > 0) {
mNumPartialResults = entry.data.i32[0];
}
}
}
FrameProcessorBase::~FrameProcessorBase() {
ALOGV("%s: Exit", __FUNCTION__);
}
status_t FrameProcessorBase::registerListener(int32_t minId,
int32_t maxId, const wp<FilteredListener>& listener, bool sendPartials) {
Mutex::Autolock l(mInputMutex);
List<RangeListener>::iterator item = mRangeListeners.begin();
while (item != mRangeListeners.end()) {
if (item->minId == minId &&
item->maxId == maxId &&
item->listener == listener) {
// already registered, just return
ALOGV("%s: Attempt to register the same client twice, ignoring",
__FUNCTION__);
return OK;
}
item++;
}
ALOGV("%s: Registering listener for frame id range %d - %d",
__FUNCTION__, minId, maxId);
RangeListener rListener = { minId, maxId, listener, sendPartials };
mRangeListeners.push_back(rListener);
return OK;
}
status_t FrameProcessorBase::removeListener(int32_t minId,
int32_t maxId,
const wp<FilteredListener>& listener) {
Mutex::Autolock l(mInputMutex);
List<RangeListener>::iterator item = mRangeListeners.begin();
while (item != mRangeListeners.end()) {
if (item->minId == minId &&
item->maxId == maxId &&
item->listener == listener) {
item = mRangeListeners.erase(item);
} else {
item++;
}
}
return OK;
}
void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) {
String8 result(" Latest received frame:\n");
write(fd, result.string(), result.size());
CameraMetadata lastFrame;
{
// Don't race while dumping metadata
Mutex::Autolock al(mLastFrameMutex);
lastFrame = CameraMetadata(mLastFrame);
}
lastFrame.dump(fd, 2, 6);
}
bool FrameProcessorBase::threadLoop() {
status_t res;
sp<CameraDeviceBase> device;
{
device = mDevice.promote();
if (device == 0) return false;
}
// 这个线程会在回调数据帧的时候被唤醒
res = device->waitForNextFrame(kWaitDuration);
if (res == OK) {
processNewFrames(device);
} else if (res != TIMED_OUT) {
ALOGE("FrameProcessorBase: Error waiting for new "
"frames: %s (%d)", strerror(-res), res);
}
return true;
}
void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
status_t res;
ATRACE_CALL();
CaptureResult result;
ALOGV("%s: Camera %s: Process new frames", __FUNCTION__, device->getId().string());
while ( (res = device->getNextResult(&result)) == OK) {
// TODO: instead of getting frame number from metadata, we should read
// this from result.mResultExtras when CameraDeviceBase interface is fixed.
camera_metadata_entry_t entry;
entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
if (entry.count == 0) {
ALOGE("%s: Camera %s: Error reading frame number",
__FUNCTION__, device->getId().string());
break;
}
ATRACE_INT("cam2_frame", entry.data.i32[0]);
if (!processSingleFrame(result, device)) {
break;
}
if (!result.mMetadata.isEmpty()) {
Mutex::Autolock al(mLastFrameMutex);
mLastFrame.acquire(result.mMetadata);
}
}
if (res != NOT_ENOUGH_DATA) {
ALOGE("%s: Camera %s: Error getting next frame: %s (%d)",
__FUNCTION__, device->getId().string(), strerror(-res), res);
return;
}
return;
}
bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
const sp<CameraDeviceBase> &device) {
ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
__FUNCTION__, device->getId().string(), result.mMetadata.isEmpty());
return processListeners(result, device) == OK;
}
status_t FrameProcessorBase::processListeners(const CaptureResult &result,
const sp<CameraDeviceBase> &device) {
ATRACE_CALL();
camera_metadata_ro_entry_t entry;
// Check if this result is partial.
bool isPartialResult =
result.mResultExtras.partialResultCount < mNumPartialResults;
// TODO: instead of getting requestID from CameraMetadata, we should get it
// from CaptureResultExtras. This will require changing Camera2Device.
// Currently Camera2Device uses MetadataQueue to store results, which does not
// include CaptureResultExtras.
entry = result.mMetadata.find(ANDROID_REQUEST_ID);
if (entry.count == 0) {
ALOGE("%s: Camera %s: Error reading frame id", __FUNCTION__, device->getId().string());
return BAD_VALUE;
}
int32_t requestId = entry.data.i32[0];
List<sp<FilteredListener> > listeners;
{
Mutex::Autolock l(mInputMutex);
List<RangeListener>::iterator item = mRangeListeners.begin();
// Don't deliver partial results to listeners that don't want them
while (item != mRangeListeners.end()) {
if (requestId >= item->minId && requestId < item->maxId &&
(!isPartialResult || item->sendPartials)) {
sp<FilteredListener> listener = item->listener.promote();
if (listener == 0) {
item = mRangeListeners.erase(item);
continue;
} else {
listeners.push_back(listener);
}
}
item++;
}
}
ALOGV("%s: Camera %s: Got %zu range listeners out of %zu", __FUNCTION__,
device->getId().string(), listeners.size(), mRangeListeners.size());
List<sp<FilteredListener> >::iterator item = listeners.begin();
for (; item != listeners.end(); item++) {
(*item)->onResultAvailable(result);
}
return OK;
}
}; // namespace camera2
}; // namespace android
上述代码中涉及到的device变量,其实就是Camera3Device实例;
Camera3Device主要实现了对Camera Provider的ICameraDeviceCallbacks回调接口的实现,通过该接口接收来自Provider的结果上传,进而传给CameraDeviceClient以及FrameProcessBase;
其中Camera3Device会将事件通过notify方法给到CameraDeviceClient。Camera3Device会将meta data以及image data 会给到FrameProcessBase,进而给到CameraDeviceClient。
所以FrameProcessBase主要用于metadata以及image data的中转处理;
mFrameProcessor构造好之后,调用mFrameProcessor->run(threadName.string())来启动它, run方法中的参数就是对当前线程的命名,如果我们碰到相机ANR的问题,也可以通过命名来分析这条线程的逻辑;
调用mFrameProcessor->registerListener来注册回调。第三个参数的定义类型为FilteredListener,实际参数就是当前的CameraDeviceClient对象,FilteredListener也是定义在FrameProcessorBase.h头文件中,它只有一个方法,onResultAvailable,很明显就是一帧处理好了,需要回调给应用层时,就会通过该方法来完成;
scss
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;
}
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);
// 调用Camera3Device的setNotifyCallback方法将自身注册到Camera3Device内部,
// 一旦Camera3Device有事件就会通过notify发送到CameraDeviceClient中
res = mDevice->setNotifyCallback(weakThis);
return OK;
}
在父类Camera2ClientBase::initializeImpl方法中,调用了mDevice->initialize()方法,mDevice这个变量是在Camera2ClientBase::Camera2ClientBase()方法中定义赋值的;
ini
mDevice = new Camera3Device(cameraId);
5.6 Camera3Device::initialize()
scss
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");
// 1.manager为CameraProviderManager实例,开启远端session
// 获取一个Provider中的ICameraDeviceSession代理
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;
}
// 通过相机参数获取device
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());
mTagMonitor.initialize(mVendorTagId);
if (!monitorTags.isEmpty()) {
mTagMonitor.parseTagsToMonitor(String8(monitorTags));
}
// Common初始化
return initializeCommonLocked();
}
在Camera3Device的initialize()方法中,调用了manager->openSession()方法创建ICameraDeviceSession实例;
php
status_t CameraProviderManager::openSession(const std::string &id,
const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
// 这一步已经涉及到了HAL层,通过findDeviceInfoLocked()方法获取到了hal层的camera device
// std::vector<std::unique_ptr<DeviceInfo>> mDevices;
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
Status status;
hardware::Return<void> ret;
// 这一步涉及到了Hal层,ICameraDeviceSession是hal层的
// 这一步用于在camera provider与 camera service之间建立的一个会话机制
ret = deviceInfo3->mInterface->open(callback, [&status, &session]
(Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
status = s;
if (status == Status::OK) {
*session = cameraSession;
}
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
return mapToStatusT(status);
}
manager为CameraProviderManager,通过内部的DeviceInfo保存的ICameraDeviceSession代理,调用deviceInfo3->mInterface->open方法从Camera Provider中打开并获取一个ICameraDeviceSession远程代理,这个代理是指为了操作camera device,camera provider与 camera service之间建立的一个会话机制,可以保证camera service IPC调用到camera provider进程中的代码;
5.7 Camera3Device::initializeCommonLocked()
紧接着执行status_t Camera3Device::initializeCommonLocked()方法,其中主要做了3件事:
1.开启状态跟踪线程:
scss
/** 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();
2.创建BufferManager:
scss
/** Create buffer manager */
mBufferManager = new Camera3BufferManager();
Camera3BufferManager是用来管理buffer的;
3.开启RequestThread线程:
scss
/** Start up request queue thread */
mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys);
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();
RequestThread是用来处理预览的request的,主要用于处理Request的接收和下发工作,PreparerThread是用来作一些准备工作的。大家知道,因为相机预览是一帧接一帧,不断的在创建、处理请求,频率非常高,一般是30fps,当然,比Android的Vsync信号同步的16ms还是要慢,所以这里开了多条线程用来同时处理不同的工作,以保证相机的效率。
启动Capture Request队列,放在RequestThread线程中执行,这个线程会一直执行,当有新的capture request发过来,会将capture request放进当前会话的请求队列中,继续执行。这个轮转很重要,这是camera能正常工作的前提;
这个过程在获取到ICameraDeviceSession代理之后,就会执行RequestThread线程,等待Request的下发;
轮转的主要工作在Camera3Device::RequestThread::threadLoop 函数中完成,这是native中定义的一个线程执行函数块;
scss
bool Camera3Device::RequestThread::threadLoop() {
ATRACE_CALL();
status_t res;
// Handle paused state.
if (waitIfPaused()) {
return true;
}
// Wait for the next batch of requests.
waitForNextRequestBatch();
if (mNextRequests.size() == 0) {
return true;
}
//......
// Prepare a batch of HAL requests and output buffers.
res = prepareHalRequests();
if (res == TIMED_OUT) {
// Not a fatal error if getting output buffers time out.
cleanUpFailedRequests(/*sendRequestError*/ true);
// Check if any stream is abandoned.
checkAndStopRepeatingRequest();
return true;
} else if (res != OK) {
cleanUpFailedRequests(/*sendRequestError*/ false);
return false;
}
// Inform waitUntilRequestProcessed thread of a new request ID
{
Mutex::Autolock al(mLatestRequestMutex);
mLatestRequestId = latestRequestId;
mLatestRequestSignal.signal();
}
//......
bool submitRequestSuccess = false;
nsecs_t tRequestStart = systemTime(SYSTEM_TIME_MONOTONIC);
if (mInterface->supportBatchRequest()) {
submitRequestSuccess = sendRequestsBatch();
} else {
submitRequestSuccess = sendRequestsOneByOne();
}
//......
return submitRequestSuccess;
}
scss
void Camera3Device::RequestThread::waitForNextRequestBatch() {
ATRACE_CALL();
// Optimized a bit for the simple steady-state case (single repeating
// request), to avoid putting that request in the queue temporarily.
Mutex::Autolock l(mRequestLock);
assert(mNextRequests.empty());
NextRequest nextRequest;
// 获取下一个请求
nextRequest.captureRequest = waitForNextRequestLocked();
if (nextRequest.captureRequest == nullptr) {
//请求队列和repeating类型的请求都没有
return;
}
nextRequest.halRequest = camera3_capture_request_t();
nextRequest.submitted = false;
mNextRequests.add(nextRequest);
// Wait for additional requests
// 获取到camera HAL设备支持的最大批量数量
// 通过日志分析,一般batchSize为1
const size_t batchSize = nextRequest.captureRequest->mBatchSize;
// 因为batchSize为1,所以不会进入for循环
for (size_t i = 1; i < batchSize; i++) {
NextRequest additionalRequest;
additionalRequest.captureRequest = waitForNextRequestLocked();
if (additionalRequest.captureRequest == nullptr) {
break;
}
additionalRequest.halRequest = camera3_capture_request_t();
additionalRequest.submitted = false;
mNextRequests.add(additionalRequest);
}
// 因为batchSize为1,所以不会if判断
if (mNextRequests.size() < batchSize) {
ALOGE("RequestThread: only get %zu out of %zu requests. Skipping requests.",
mNextRequests.size(), batchSize);
cleanUpFailedRequests(/*sendRequestError*/true);
}
return;
}
sp<Camera3Device::CaptureRequest>
Camera3Device::RequestThread::waitForNextRequestLocked() {
status_t res;
sp<CaptureRequest> nextRequest;
// 当队列为空的时候,才回去尝试获取repeating请求,获取不到说明当前没有任何请求可以获取,则阻塞等待
while (mRequestQueue.empty()) {
if (!mRepeatingRequests.empty()) {
// Always atomically enqueue all requests in a repeating request
// list. Guarantees a complete in-sequence set of captures to
// application.
const RequestList &requests = mRepeatingRequests;
// 获取一个repeating request
RequestList::const_iterator firstRequest =
requests.begin();
nextRequest = *firstRequest;
// 插入到请求队列中
mRequestQueue.insert(mRequestQueue.end(),
++firstRequest,
requests.end());
// No need to wait any longer
mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;
break;
}
// 没有获取到任何请求, 阻塞等待新的请求到来;
res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);
if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||
exitPending()) {
Mutex::Autolock pl(mPauseLock);
if (mPaused == false) {
ALOGV("%s: RequestThread: Going idle", __FUNCTION__);
mPaused = true;
// Let the tracker know
sp<StatusTracker> statusTracker = mStatusTracker.promote();
if (statusTracker != 0) {
statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
}
}
// Stop waiting for now and let thread management happen
return NULL;
}
}
// 当!mRequestQueue.empty()为true时,从请求队列中获取新的请求
if (nextRequest == NULL) {
// Don't have a repeating request already in hand, so queue
// must have an entry now.
RequestList::iterator firstRequest =
mRequestQueue.begin();
nextRequest = *firstRequest;
// 这个是和RepeatingRequests最大的区别
mRequestQueue.erase(firstRequest);
if (mRequestQueue.empty() && !nextRequest->mRepeating) {
sp<NotificationListener> listener = mListener.promote();
if (listener != NULL) {
listener->notifyRequestQueueEmpty();
}
}
}
// In case we've been unpaused by setPaused clearing mDoPause, need to
// update internal pause state (capture/setRepeatingRequest unpause
// directly).
Mutex::Autolock pl(mPauseLock);
if (mPaused) {
ALOGV("%s: RequestThread: Unpaused", __FUNCTION__);
sp<StatusTracker> statusTracker = mStatusTracker.promote();
if (statusTracker != 0) {
statusTracker->markComponentActive(mStatusId);
}
}
mPaused = false;
// Check if we've reconfigured since last time, and reset the preview
// request if so. Can't use 'NULL request == repeat' across configure calls.
if (mReconfigured) {
mPrevRequest.clear();
mReconfigured = false;
}
if (nextRequest != NULL) {
nextRequest->mResultExtras.frameNumber = mFrameNumber++;
nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
// Since RequestThread::clear() removes buffers from the input stream,
// get the right buffer here before unlocking mRequestLock
if (nextRequest->mInputStream != NULL) {
res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
if (res != OK) {
// Can't get input buffer from gralloc queue - this could be due to
// disconnected queue or other producer misbehavior, so not a fatal
// error
ALOGE("%s: Can't get input buffer, skipping request:"
" %s (%d)", __FUNCTION__, strerror(-res), res);
sp<NotificationListener> listener = mListener.promote();
if (listener != NULL) {
listener->notifyError(
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
nextRequest->mResultExtras);
}
return NULL;
}
}
}
return nextRequest;
}
waitForNextRequestBatch() 不断去轮训底层是否有InputBuffer数据,获取的inputBuffer数据放在request中,这些数据会在之后被消费;
threadLoop()时序图:
综上,第4节和第5节描述的就是openCamera在Camera Framework层的调用流程,直到调用到HAL层为至,RequestThread启动开始轮训之后,CameraManager.openCameraDeviceUserAsync()方法继续调用deviceImpl.setRemoteDevice(cameraUser)执行CameraDevice.StateCallback中的Onopened()回调方法;
其实就是创建了Framework层的cameraUser实例,而该实例对应的CameraServer层就是CameraDeviceClient,CameraDeviceClient调用Camera3Device,Camera3Device通过CameraProviderManager open Camera Device,同时获取到了HAL层的CameraDeviceSession代理,间接的与HAL层进行通信;
Framework层将创建好的CameraUser传递给CameraDeviceImpl,然后通过onOpened()回调将CameraDeviceImpl实例回调给Application
执行到onOpened之后,整个openCamera流程便结束了。