基于Android Camera2 openCamera流程分析

基于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流程便结束了。

相关推荐
深海呐6 分钟前
Android AlertDialog圆角背景不生效的问题
android
ljl_jiaLiang7 分钟前
android10 系统定制:增加应用使用数据埋点,应用使用时长统计
android·系统定制
花花鱼8 分钟前
android 删除系统原有的debug.keystore,系统运行的时候,重新生成新的debug.keystore,来完成App的运行。
android
canonical_entropy1 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
落落落sss1 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
沛沛老爹2 小时前
服务监控插件全览:提升微服务可观测性的利器
微服务·云原生·架构·datadog·influx·graphite
huaqianzkh3 小时前
了解华为云容器引擎(Cloud Container Engine)
云原生·架构·华为云
消失的旧时光-19434 小时前
kotlin的密封类
android·开发语言·kotlin
Kika写代码4 小时前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
刘某某.4 小时前
使用OpenFeign在不同微服务之间传递用户信息时失败
java·微服务·架构