Android 13 openCamera流程详解

欢迎关注微信公众号 无限无羡

本篇文章稍长,希望大家耐心阅读。代码也很多,所以尽量多的加了注解,也希望阅读到此文章的“同道中人”提出宝贵建议。

Android从5.0开始已经引入了Camera API2,所以我们后面的流程都是Camera API2调用流程。

Open Camera的流程分为下面两个步骤

// 1. 获取CameraManager
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
// 2. 调用CameraManager的openCamera函数
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);

CameraManager的获取是常规的系统服务代理的获取方法,这里就不具体介绍了。下面我们开始介绍openCamera函数的实现

// frameworks/base/core/java/android/hardware/camera2/CameraManager.java
// 调用该函数的App需要申请动态权限android.Manifest.permission.CAMERA
@RequiresPermission(android.Manifest.permission.CAMERA)
// 第一个参数是cameraId
// 第二个参数是一个Callback对象,用于给应用返回open camera的结果
// 第三个参数是一个Handler对象,上面的callback回调函数将会执行在这个Handler对象所在的线程中
public void openCamera(@NonNull String cameraId,
        @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
        throws CameraAccessException {

    openCameraForUid(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
            USE_CALLING_UID);
}

接下来调用内部的openCameraForUid函数,这里第三个参数对Handler对象作了一个检查和包装,我们看一下

// frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
public static Executor checkAndWrapHandler(Handler handler) {
    return new CameraHandlerExecutor(checkHandler(handler));
}

// 这里返回了一个CameraHandlerExecutor对象,并且传入了checkHandler(handler)作为参数,看下checkHandler的实现
// 比较简单,如果handler为空的话就获取当前线程的Looper对象并且以此为参数构造一个新的Handler对象返回
static Handler checkHandler(Handler handler) {
    if (handler == null) {
        Looper looper = Looper.myLooper();
        if (looper == null) {
            throw new IllegalArgumentException(
                "No handler given, and current thread has no looper!");
        }
        handler = new Handler(looper);
    }
    return handler;
}

// 再看下CameraHandlerExecutor类的实现
// 1. 实现了Executor接口
// 2. 内部有一个Handler成员变量
// 3. 其execute函数实际上执行的就是Handler的post函数
private static class CameraHandlerExecutor implements Executor {
    private final Handler mHandler;

    public CameraHandlerExecutor(@NonNull Handler handler) {
        mHandler = Objects.requireNonNull(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);
    }
}

接下来继续看openCameraForUid的实现

// frameworks/base/core/java/android/hardware/camera2/CameraManager.java
public void openCameraForUid(@NonNull String cameraId,
        @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
        int clientUid) throws CameraAccessException {
        // 又调用了另一个函数,并且多加了一个参数oomScoreOffset=0,这个值会在CameraService里用到,
        // 当多个进程打开同一个cameraid时,会有一个抢占机制,这里的oomScoreOffset是其中一个优先级指标,
        // 值越小,优先级越高,这里默认是0,后面用到时再具体展开讲解
        // 第四个参数clientUid为USE_CALLING_UID=-1,这个参数是固定的
        openCameraForUid(cameraId, callback, executor, clientUid, /*oomScoreOffset*/0);
}

public void openCameraForUid(@NonNull String cameraId,
        @NonNull final CameraDevice.StateCallback callback, @NonNull Executor executor,
        int clientUid, int oomScoreOffset) throws CameraAccessException {
	
    if (cameraId == null) { // 检查cameraId参数,不能为空
        throw new IllegalArgumentException("cameraId was null");
    } else if (callback == null) { // 检查callback参数,不能为空
        throw new IllegalArgumentException("callback was null");
    }
    // 判断CameraService是否被禁用,这个静态变量是由属性config.disable_cameraservice(true/false)控制的
    if (CameraManagerGlobal.sCameraServiceDisabled) {
        throw new IllegalArgumentException("No cameras available on device");
    }

	// 上面的检查都没问题后,调用openCameraDeviceUserAsync
    openCameraDeviceUserAsync(cameraId, callback, executor, clientUid, oomScoreOffset);
}

// 从这里开始进入正题,这里面有几个关键点,我们按数字标出来,然后逐个破解
private CameraDevice openCameraDeviceUserAsync(String cameraId,
        CameraDevice.StateCallback callback, Executor executor, final int uid,
        final int oomScoreOffset) throws CameraAccessException {
    // 1. 根据cameraId获取CameraCharacteristics
    CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
    CameraDevice device = null;
    Map<String, CameraCharacteristics> physicalIdsToChars =
            getPhysicalIdToCharsMap(characteristics);
    synchronized (mLock) {
		
        ICameraDeviceUser cameraUser = null;
        // 2. 构建CameraDeviceImpl对象
        android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                new android.hardware.camera2.impl.CameraDeviceImpl(
                    cameraId,
                    callback,
                    executor,
                    characteristics,
                    physicalIdsToChars,
                    mContext.getApplicationInfo().targetSdkVersion,
                    mContext);

        ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();

        try {
        	// 3. 获取CameraService对象的代理,并且调用CameraService对象的connectDevice函数
        	//    openCamera的关键实现都从这个函数展开,这里会调用到CameraServer进程再进入Camera HAL
        	//    (CameraProvider)进程
            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
            if (cameraService == null) {
                throw new ServiceSpecificException(
                    ICameraService.ERROR_DISCONNECTED,
                    "Camera service is currently unavailable");
            }
            cameraUser = cameraService.connectDevice(callbacks, cameraId,
                mContext.getOpPackageName(),  mContext.getAttributionTag(), uid,
                oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);
        } catch (ServiceSpecificException e) {
            if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
                throw new AssertionError("Should've gone down the shim path");
            } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
                    e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
                    e.errorCode == ICameraService.ERROR_DISABLED ||
                    e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                    e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
                // Received one of the known connection errors
                // The remote camera device cannot be connected to, so
                // set the local camera to the startup error state
                deviceImpl.setRemoteFailure(e);

                if (e.errorCode == ICameraService.ERROR_DISABLED ||
                        e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                        e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
                    // Per API docs, these failures call onError and throw
                    throwAsPublicException(e);
                }
            } else {
                // Unexpected failure - rethrow
                throwAsPublicException(e);
            }
        } catch (RemoteException e) {
            // Camera service died - act as if it's a CAMERA_DISCONNECTED case
            ServiceSpecificException sse = new ServiceSpecificException(
                ICameraService.ERROR_DISCONNECTED,
                "Camera service is currently unavailable");
            deviceImpl.setRemoteFailure(sse);
            throwAsPublicException(sse);
        }

        // TODO: factor out callback to be non-nested, then move setter to constructor
        // For now, calling setRemoteDevice will fire initial
        // onOpened/onUnconfigured callbacks.
        // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
        // cameraUser dies during setup.
        // 4. 调用CameraDeviceImpl的setRemoteDevice函数,cameraUser是connectHelper函数返回的
        //    一个binder代理,其服务端实现在CameraService里,对应CameraDeviceClient对象。
        //    同时,这个函数中也会执行openCamera时传入的callback函数,通知App打开的结果
        deviceImpl.setRemoteDevice(cameraUser);
        device = deviceImpl;
    }

    return device;
}

上面我们列出了4个关键步骤,接下来我们逐一分析

// 1. 根据cameraId获取CameraCharacteristics
// CameraCharacteristics封装的是cameraId对应的设备的硬件信息,内部实现其实就是CameraMetadata。
// CameraMetadata是一个Parcelable对象,可以在App、CameraServer,Camera HAL之间通过binder传递。
// App可以通过它拿到设备信息,也可以通过它下发参数给到Camera HAL(比如打开闪光灯),Camera HAL再跟驱动进行交互。
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);

// 下面代码是获取到物理Camera Id对应的CameraCharacteristics,一个物理Camera Id对应一个真实的摄像头;
// 上面的cameraId是逻辑Id,一个逻辑Id可以对应多个物理Id,比如有的手机上打开前置摄像头时实际上看到的图像是多个真实
// 摄像头数据融合之后的画面。
Map<String, CameraCharacteristics> physicalIdsToChars =
                getPhysicalIdToCharsMap(characteristics);

// 关于CameraCharacteristics我们就讲这么多,后面我们会单独开章节详细进行介绍
// 2. 构建CameraDeviceImpl对象
// 这里创建了CameraDeviceImpl对象,并且拿到了ICameraDeviceCallbacks,这个后面跟CameraServer交互时会使用。
ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
// 这里拿到CameraService binder代理后调用connectDevice函数,实现在CameraService.cpp文件
// 这个函数也是openCamera流程的核心,要重点关注。
ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
// 这个函数参数一共有7个,我们到这里先梳理一下
// (1)callbacks: ICameraDeviceCallbacks对象,从deviceImpl获取,可以跨进程传输
// (2)cameraId: openCamera时传入的cameraId
// (3)mContext.getOpPackageName(): 应用的包名
// (4)mContext.getAttributionTag(): 这里看了好几个应用都是null
// (5)uid: USE_CALLING_UID=-1
// (6)oomScoreOffset: 0
// (7)mContext.getApplicationInfo().targetSdkVersion: 应用指定的targetSdkVersion
ICameraDeviceUser cameraUser = cameraService.connectDevice(callbacks, cameraId,
    mContext.getOpPackageName(),  mContext.getAttributionTag(), uid,
    oomScoreOffset, mContext.getApplicationInfo().targetSdkVersion);

// 下面开始看connectDevice函数实现
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        const std::optional<String16>& clientFeatureId,
        int clientUid, int oomScoreOffset, int targetSdkVersion,
        /*out*/
        // 最后一个参数是出参,用于返回ICameraDeviceUser对象指针
        sp<hardware::camera2::ICameraDeviceUser>* device) {

    ATRACE_CALL();
    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;
    String16 clientPackageNameAdj = clientPackageName;
    int callingPid = CameraThreadState::getCallingPid();
    bool systemNativeClient = false;
    // 如果是native程序调用的话systemNativeClient = true
    // native程序没有包名,并且必须是系统native程序
    if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
        std::string systemClient =
                StringPrintf("client.pid<%d>", CameraThreadState::getCallingPid());
        clientPackageNameAdj = String16(systemClient.c_str());
        systemNativeClient = true;
    }

	// oomScoreOffset 这个值为0,如果小于0的话直接返回错误
    if (oomScoreOffset < 0) {
        String8 msg =
                String8::format("Cannot increase the priority of a client %s pid %d for "
                        "camera id %s", String8(clientPackageNameAdj).string(), callingPid,
                        id.string());
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
    }

	// 获取clientUserId
    userid_t clientUserId = multiuser_get_user_id(clientUid);
    int callingUid = CameraThreadState::getCallingUid();
    // 根据前面可知,clientUid=USE_CALLING_UID
    if (clientUid == USE_CALLING_UID) {
    	// 这里拿到的是真正的App的Uid
        clientUserId = multiuser_get_user_id(callingUid);
    }

	// Camera是否被DevicePolicy禁用
    if (CameraServiceProxyWrapper::isCameraDisabled(clientUserId)) {
        String8 msg =
                String8::format("Camera disabled by device policy");
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_DISABLED, msg.string());
    }

    // enforce system camera permissions
    // 如果oomScoreOffset大于0的话,则必须是系统应用,拥有系统签名,而且必须声明两个权限:
    // android.permission.SYSTEM_CAMERA和android.permission.CAMERA
    // android.permission.SYSTEM_CAMERA 这个权限是Android 11添加的,想要此权限生效
    // 的话,应用必须有系统签名且必须是系统应用。此类应用可以打开SYSTEM_ONLY_CAMERA类型的camera。
    // SYSTEM_ONLY_CAMERA 类型的camera无法被三方应用获取到。
    // 普通应用的话oomScoreOffset=0,所以不会检查SYSTEM_CAMERA权限
    if (oomScoreOffset > 0 &&
            !hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid())) {
        String8 msg =
                String8::format("Cannot change the priority of a client %s pid %d for "
                        "camera id %s without SYSTEM_CAMERA permissions",
                        String8(clientPackageNameAdj).string(), callingPid, id.string());
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.string());
    }

	// 接下来调用connectHelper方法,此方法返回CameraDeviceClient
    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
            /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId,
            clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
            targetSdkVersion, /*out*/client);

    if(!ret.isOk()) {
        logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8());
        return ret;
    }

	// CameraDeviceClient是ICameraDeviceUser的binder Bn端的实现
	// 所以Java层返回的ICameraDeviceUser对应的是CameraService里的CameraDeviceClient对象
    *device = client;
    Mutex::Autolock lock(mServiceLock);

    // Clear the previous cached logs and reposition the
    // file offset to beginning of the file to log new data.
    // If either truncate or lseek fails, close the previous file and create a new one.
    if ((ftruncate(mMemFd, 0) == -1) || (lseek(mMemFd, 0, SEEK_SET) == -1)) {
        ALOGE("%s: Error while truncating the file: %s", __FUNCTION__, sFileName);
        // Close the previous memfd.
        close(mMemFd);
        // If failure to wipe the data, then create a new file and
        // assign the new value to mMemFd.
        mMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
        if (mMemFd == -1) {
            ALOGE("%s: Error while creating the file: %s", __FUNCTION__, sFileName);
        }
    }
    return ret;
}

// 接下来继续看connectHelper函数的实现
// CALLBACK:hardware::camera2::ICameraDeviceCallbacks
// CLIENT: CameraDeviceClient
template<class CALLBACK, class CLIENT>
// 我们先梳理一下每个参数:
// cameraCb: ICameraDeviceCallbacks,应用进程传进来的回调函数
// cameraId: 要打开的cameraId
// api1CameraId: -1
// clientPackageNameMaybe: 调用app的包名,调用者是native进程的话就是client.pid+进程号
// systemNativeClient: 是否为系统native进程调用
// clientFeatureId: null (app调用的话这个值为null,native进程的话还未验证是否也为null)
// clientUid: USE_CALLING_UID=-1
// clientPid: USE_CALLING_PID=-1
// effectiveApiLevel:API_2
// shimUpdateOnly:false
// oomScoreOffset: 一般为0,如果是打开系统camera的话会大于0
// targetSdkVersion:应用设置的targetSdkVersion
// device: 出参,返回CameraDeviceClient对象
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
        const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
        apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
        /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();

    bool isNonSystemNdk = false;
    String16 clientPackageName;
    //如果是系统Ndk调用的话,重新赋值包名,该包名是同一个uid下的选择的一个包名,拥有相同的权限。
    if (clientPackageNameMaybe.size() <= 0) {
        // NDK calls don't come with package names, but we need one for various cases.
        // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
        // do exist. For all authentication cases, all packages under the same UID get the
        // same permissions, so picking any associated package name is sufficient. For some
        // other cases, this may give inaccurate names for clients in logs.
        isNonSystemNdk = true;
        int packageUid = (clientUid == USE_CALLING_UID) ?
            CameraThreadState::getCallingUid() : clientUid;
        clientPackageName = getPackageNameFromUid(packageUid);
    } else {
        clientPackageName = clientPackageNameMaybe;
    }

    String8 clientName8(clientPackageName);

    int originalClientPid = 0;

    int packagePid = (clientPid == USE_CALLING_PID) ?
        CameraThreadState::getCallingPid() : clientPid;
    ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and "
            "Camera API version %d", packagePid, clientName8.string(), cameraId.string(),
            static_cast<int>(effectiveApiLevel));

    nsecs_t openTimeNs = systemTime();

    sp<CLIENT> client = nullptr;
    int facing = -1;
    int orientation = 0;

    {
    	// 这里先申请一个锁,在锁持有期间如果有其他client调用open camera,将会返回ERROR_MAX_CAMERAS_IN_USE
    	// 该锁3秒超时,也就是3秒内不能有两个client open camera,但是3秒后可以。
        // Acquire mServiceLock and prevent other clients from connecting
        std::unique_ptr<AutoConditionLock> lock =
                AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);

        if (lock == nullptr) {
            ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
                    , clientPid);
            return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                    "Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
                    cameraId.string(), clientName8.string(), clientPid);
        }

        // 这里主要进行一些校验,比如uid和pid的校验,权限的判断校验,以及camera hal是否加载成功、cameraid
        // 是否合法是否可用是否被占用等,代码比较简单,这里自行跟读代码
        // Enforce client permissions and do basic validity 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;
        // handleEvictionsLocked这个函数就是打开cameraid时的驱逐机制,这里我们重点介绍一下。驱逐的意思就是
        // 对于要open camera的client进行一些列条件判断,如果不符合打开camera的条件,就拒绝。这个函数的解读
        // 由于文章格式问题,我们把解读放在文章的后面,这里先理解其大意即可。
        if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
                IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, systemNativeClient,
                /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
            switch (err) {
                case -ENODEV:
                	// 对于要打开的cameraid,当前设备不可获取
                    return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                            "No camera device with ID \"%s\" currently available",
                            cameraId.string());
                case -EBUSY:
                	// 有更高优先级的client在使用这个cameraid,当前client优先级较低,无法打开
                    return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                            "Higher-priority client using camera, ID \"%s\" currently unavailable",
                            cameraId.string());
                case -EUSERS:
                	// 已经达到了打开camera的最大数量,不允许再打开camera
                    return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                            "Too many cameras already open, cannot open camera \"%s\"",
                            cameraId.string());
                default:
                	// 其他不可预知的错误
                    return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                            "Unexpected error %s (%d) opening camera \"%s\"",
                            strerror(-err), err, cameraId.string());
            }
        }

		// 这里省略一些不重要的代码
		...
		...
		...

		// 下面开始创建CameraDeviceClient对象
		// CameraDeviceClient是BasicClient的子类
        sp<BasicClient> tmp = nullptr;
        // 有15个参数,一个出参
        // 这里就不一一列举了,大家根据上下文自己理解每个参数的意义和值。
        // 同样的,makeClient的解读我们放到文章的后面。
        bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
                mPerfClassPrimaryCameraIds, cameraId.string(), targetSdkVersion);
        if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
                clientFeatureId, cameraId, api1CameraId, facing, orientation,
                clientPid, clientUid, getpid(),
                deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
                /*out*/&tmp)).isOk()) {
            return ret;
        }
        // 对于camera API2的情况,这里的tmp类型为CameraDeviceClient
        client = static_cast<CLIENT*>(tmp.get());

        LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                __FUNCTION__);

        String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
        // 这里调用CameraDeviceClient的initialize函数
        // 文章最后单独展开讲解
        err = client->initialize(mCameraProviderManager, monitorTags);
        // 下面是根据返回值来打印失败的原因,错误都是从HAL返回的。
        if (err != OK) {
            ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
            // Errors could be from the HAL module open call or from AppOpsManager
            switch(err) {
                case BAD_VALUE:
                    return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                            "Illegal argument to HAL module for camera \"%s\"", cameraId.string());
                case -EBUSY:
                    return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                            "Camera \"%s\" is already open", cameraId.string());
                case -EUSERS:
                    return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                            "Too many cameras already open, cannot open camera \"%s\"",
                            cameraId.string());
                case PERMISSION_DENIED:
                    return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                            "No permission to open camera \"%s\"", cameraId.string());
                case -EACCES:
                    return STATUS_ERROR_FMT(ERROR_DISABLED,
                            "Camera \"%s\" disabled by policy", cameraId.string());
                case -ENODEV:
                default:
                    return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                            "Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
                            strerror(-err), err);
            }
        }

	// 剩余代码省略
	...
	...
	...

    return ret;
}

// 在上面connetHelper流程中,我们有三个关键函数没有细说,这里展开一下
handleEvictionsLocked、makeClient和client->initialize

// handleEvictionsLocked,这个函数有203行,不重要的我们将略过
status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
        int oomScoreOffset, bool systemNativeClient,
        /*out*/
        sp<BasicClient>* client,
        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
    ATRACE_CALL();
    status_t ret = NO_ERROR;
    std::vector<DescriptorPtr> evictedClients;
    DescriptorPtr clientDescriptor;
    {
    	// API_1的情况我们就不说了,淘汰的老古董了
        if (effectiveApiLevel == API_1) {
			...
			...
			...
        }

        // Get current active client PIDs
        // 将clientPid添加到mActiveClientManager.getAllOwners()获取到的容器中
        // 由此可知,这里面保存的是所有访问该camera的client pid的集合
        // 当第一个client访问该camera时,ownerPids是一个空的容器,后面
        // 有新的client到来时,将会把clientPid放到该容器的最后面。
        std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
        ownerPids.push_back(clientPid);

		//定义每个clientPid的两个容器priorityScores和states,并通过getProcessStatesScoresFromPids
		// 给其赋值。
        std::vector<int> priorityScores(ownerPids.size());
        std::vector<int> states(ownerPids.size());

		// 这个函数是到系统中查询所有clientPid的score值和state值。
		// 这里通过binder最终调用到了Java服务中,在AMS中注册的服务“processinfo”
		// 最终调用的是AMS的getProcessStatesAndOomScoresForPIDs方法。
		// ServiceManager.addService("processinfo", new ProcessInfoService(this));
        // Get priority scores of all active PIDs
        // 这里从AMS返回的priorityScore是进程的ADJ值,state是进程的状态(前台,后台等状态
        // 具体可看ActivityManager.java中PROCESS_STATE_XXX)
        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
        // 将上面获取到的进程状态放到pidToPriorityMap的map中,key为进程pid,
        // value为ClientPriority(里面包含了priorityScore和state值)
        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],
                            /* isVendorClient won't get copied over*/ false,
                            /* oomScoreOffset won't get copied over*/ 0));
        }
        mActiveClientManager.updatePriorities(pidToPriorityMap);

        // Get state for the given cameraId
        // 这里的state和上面的state是不一样的,这里是从HAL获取。
        // 这里返回的是CameraService::CameraState类型,在
        // CameraServer进程开机启动的时候初始化完成了mCameraStates,
        // 这是一个map,key为cameraId, value为CameraState类型对象。
        // frameworks/av/services/camera/libcameraservice/CameraService.h
        // Mapping from camera ID -> state for each device, map is protected by mCameraStatesLock
    	// std::map<String8, std::shared_ptr<CameraState>> mCameraStates;

		// 接下来我们主要看下初始化时,每个cameraid设备对应的CameraState值是什么。
		// frameworks/av/services/camera/libcameraservice/CameraService.cpp
		// 由于HAL是厂商实现的,我们没有源码,所以本系列文章的Camera HAL都是基于Google的一个参考实现:
		// 基于V4l2实现的Camera HAL代码 camera.v4l2_test
		// cost.resourceCost默认为100
		// conflicting:empty
		// deviceKind:PUBLIC or SYSTEM_ONLY_CAMERA or HIDDEN_SECURE_CAMERA
		// physicalCameraIds: 逻辑cameraId对应的物理cameraId
		// mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
        //       conflicting, deviceKind, physicalCameraIds));
        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;
        }

        int32_t actualScore = priorityScores[priorityScores.size() - 1];
        int32_t actualState = states[states.size() - 1];

        // Make descriptor for incoming client. We store the oomScoreOffset
        // since we might need it later on new handleEvictionsLocked and
        // ProcessInfoService would not take that into account.
        // 将调用者的所有信息和要打开的设备信息都保存到了一个Descriptor对象中,后面的判断机制
        // 都是用这个对象来进行的。
        // 下面的几个构造参数已经不言而喻了
        clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
                sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
                state->getConflicting(), actualScore, clientPid, actualState,
                oomScoreOffset, systemNativeClient);

        resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();

        // Find clients that would be evicted
        // 下面这个wouldEvict是核心实现,最终调用到wouldEvictLocked
        auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
        // wouldEvictLocked start
        // frameworks/av/services/camera/libcameraservice/utils/ClientManager.h
        template<class KEY, class VALUE, class LISTENER>
		std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
		ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
		        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
		        bool returnIncompatibleClients) const {
		
			// 这里先创建了一个容器,最终添加到这里面的都是要被驱逐(evict)的
		    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> evictList;
		
		    // Disallow null clients, return input
		    if (client == nullptr) {
		        evictList.push_back(client);
		        return evictList;
		    }
		
		    const KEY& key = client->getKey();// cameraId
		    int32_t cost = client->getCost(); // resource cost (default=100)
		    ClientPriority priority = client->getPriority();
		    int32_t owner = client->getOwnerId(); // 调用者pid
		
			// getCurrentCostLocked() 所有调用openCamera的进程的cost总和
			// 由上我们知道,每一个进程的resource cost默认是100,所以当由两个进程
			// 都执行打开Camera的操作时,到这里totalCost就会是200。但是系统有一个
			// mMaxCost(默认也是100),所有当由两个进程打开Camera时totalCost就会超过
			// mMaxCost, 从而导致open Camera失败。后面会有这部分逻辑的介绍。
			// 当只有一个进程打开时,totalCost = 100(默认值)
		    int64_t totalCost = getCurrentCostLocked() + cost;
		
		    // Determine the MRU of the owners tied for having the highest priority
		    // 当有多个进程open Camera时,会进行优先级的比较,下面的比较是对oom_adj和 state进行
		    // 比较的,这两个值都是越小,优先级越高。当oom_adj值相等时,则再进行state的比较,否则
		    // 就只比较oom_adj的值来判定谁的优先级更高。
		    int32_t highestPriorityOwner = owner;
		    ClientPriority highestPriority = priority;
		    for (const auto& i : mClients) {
		        ClientPriority curPriority = i->getPriority();
		        if (curPriority <= highestPriority) {
		            highestPriority = curPriority;
		            highestPriorityOwner = i->getOwnerId();
		        }
		    }
		
		    if (highestPriority == priority) {
		        // Switch back owner if the incoming client has the highest priority, as it is MRU
		        highestPriorityOwner = owner;
		    }
		    // 到这里后,highestPriorityOwner就是所有client中优先级最高的进程。
		
		    // Build eviction list of clients to remove
		    for (const auto& i : mClients) {
		        const KEY& curKey = i->getKey();
		        int32_t curCost = i->getCost();
		        ClientPriority curPriority = i->getPriority();
		        int32_t curOwner = i->getOwnerId();
		
				// 这里的key指定是cameraId,这里冲突的判断二者满族其一即可。
				// 1. cameraId已经被其他进程打开
				// 2. HAL层定义了两个CameraId是冲突设备
		        bool conflicting = (curKey == key || i->isConflicting(key) ||
		                client->isConflicting(curKey));
		
				// returnIncompatibleClients默认参数为false
		        if (!returnIncompatibleClients) {
		            // Find evicted clients
					// 发生冲突,并且是同一个pid,也就是同一个进程
		            if (conflicting && owner == curOwner) {
		                // Pre-existing conflicting client with the same client owner exists
		                // Open the same device twice -> most recent open wins
		                // Otherwise let the existing client wins to avoid behaviors difference
		                // due to how HAL advertising conflicting devices (which is hidden from
		                // application)
		                // 如果cameraId相同,则将自己加入evictList。也就是说同一个进程第二次打开一个冲突的设备时,
		                // 将会把第一次打开的驱逐,第二次将会重新打开。
		                if (curKey == key) {
		                    evictList.push_back(i);
		                    totalCost -= curCost;
		                } else {
		                	// 如果cameraId不相同,则会即将第二次打开的进行驱逐。也就是第二次打开将会失败。
		                    evictList.clear();
		                    evictList.push_back(client);
		                    return evictList;
		                }
		            // 如果发生冲突,并且当前进程优先级更低,则将当前进程驱逐,也就是当前进程将会打开失败。
		            } else if (conflicting && curPriority < priority) {
		                // Pre-existing conflicting client with higher priority exists
		                evictList.clear();
		                evictList.push_back(client);
		                return evictList;
		            // 如果发生冲突,或者 resource cost超过最大值并且当前进程优先级更高,则将进行比较的已经存在的client
		            // 进行驱逐
		            } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
		                    (curPriority >= priority) &&
		                    !(highestPriorityOwner == owner && owner == curOwner))) {
		                // Add a pre-existing client to the eviction list if:
		                // - We are adding a client with higher priority that conflicts with this one.
		                // - The total cost including the incoming client's is more than the allowable
		                //   maximum, and the client has a non-zero cost, lower priority, and a different
		                //   owner than the incoming client when the incoming client has the
		                //   highest priority.
		                evictList.push_back(i);
		                totalCost -= curCost;
		            }
		        } else {
		            // Find clients preventing the incoming client from being added
					// 如果走到这里,则是 将优先级高的加入evictList
		            if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
		                // Pre-existing conflicting client with higher priority exists
		                evictList.push_back(i);
		            }
		        }
		    }
		
		    // Immediately return the incompatible clients if we are calculating these instead
		    // returnIncompatibleClients为true的话,是将已经存在的高优先级的client驱逐掉
		    // 这里的逻辑其实可以从其定义处看到,如下:
		     /**
		     * Return a vector of the ClientDescriptors that would be evicted by adding the given
		     * ClientDescriptor.  If returnIncompatibleClients is set to true, instead, return the
		     * vector of ClientDescriptors that are higher priority than the incoming client and
		     * either conflict with this client, or contribute to the resource cost if that would
		     * prevent the incoming client from being added.
		     *
		     * This may return the ClientDescriptor passed in.
		     */
		    // std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvictLocked(
		    //        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
		    //        bool returnIncompatibleClients = false) const;
		    
		    if (returnIncompatibleClients) {
		        return evictList;
		    }
		
		    // If the total cost is too high, return the input unless the input has the highest priority
		    // 如果totalCost大于mMaxCost并且当前进程不是最高优先级进程,则进行驱逐
		    if (totalCost > mMaxCost && highestPriorityOwner != owner) {
		        evictList.clear();
		        evictList.push_back(client);
		        return evictList;
		    }
		
			// 将evictList返回。
		    return evictList;
		
		}
        // wouldEvictLocked end

        // 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();
			// 这里调用的也是wouldEvictLocked函数,不过returnIncompatibleClients为true
			// 也就是返回在驱逐机制中,胜过了当前进程的client集合。
			// (看到这里终于知道了returnIncompatibleClients参数的妙用)
            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,
                    clientPriority.getScore(), clientPriority.getState());

            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);

            auto current = mActiveClientManager.get(cameraId);
            if (current != nullptr) {
            	// 找到了占用cameraId的进程,所以该cameraId设备正在被使用
                return -EBUSY; // CAMERA_IN_USE
            } else {
            	// 没有找到,说明达到了打开Camera的最大数量
                return -EUSERS; // MAX_CAMERAS_IN_USE
            }
        }

		// 遍历驱逐列表,进行日志信息打印
        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, clientPriority.getScore(),
                    clientPriority.getState()));

            // Notify the client of disconnection
            clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
                    CaptureResultExtras());
        }
    }

    // Do not hold mServiceLock while disconnecting clients, but retain the condition blocking
    // other clients from connecting in mServiceLockWrapper if held
    mServiceLock.unlock();

    // Clear caller identity temporarily so client disconnect PID checks work correctly
    int64_t token = CameraThreadState::clearCallingIdentity();

    // Destroy evicted clients
    for (auto& i : evictedClients) {
        // Disconnect is blocking, and should only have returned when HAL has cleaned up
        // 将驱逐列表中的lient从clients列表删除
        i->getValue()->disconnect(); // Clients will remove themselves from the active client list
    }

    CameraThreadState::restoreCallingIdentity(token);

    for (const auto& i : evictedClients) {
        ALOGV("%s: Waiting for disconnect to complete for client for device %s (PID %" PRId32 ")",
                __FUNCTION__, i->getKey().string(), i->getOwnerId());
        ret = mActiveClientManager.waitUntilRemoved(i, DEFAULT_DISCONNECT_TIMEOUT_NS);
        if (ret == TIMED_OUT) {
            ALOGE("%s: Timed out waiting for client for device %s to disconnect, "
                    "current clients:\n%s", __FUNCTION__, i->getKey().string(),
                    mActiveClientManager.toString().string());
            return -EBUSY;
        }
        if (ret != NO_ERROR) {
            ALOGE("%s: Received error waiting for client for device %s to disconnect: %s (%d), "
                    "current clients:\n%s", __FUNCTION__, i->getKey().string(), strerror(-ret),
                    ret, mActiveClientManager.toString().string());
            return ret;
        }
    }

    evictedClients.clear();

    // Once clients have been disconnected, relock
    mServiceLock.lock();

    // Check again if the device was unplugged or something while we weren't holding mServiceLock
    if ((ret = checkIfDeviceIsUsable(cameraId)) != NO_ERROR) {
        return ret;
    }

    *partial = clientDescriptor;
    return NO_ERROR;
}

上面就把handleEvictionsLocked的流程讲完了。
下面开始讲解makeClient流程:

// frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, bool systemNativeClient,
        const std::optional<String16>& featureId,  const String8& cameraId,
        int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
        int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
        apiLevel effectiveApiLevel, bool overrideForPerfClass, /*out*/sp<BasicClient>* client) {
    // For HIDL devices
    // 如果Camera HAL是通过HIDL实现的。(Android 8引入了HIDL机制,HAL层以HIDL接口实现。Android 11又引入了
    // AIDL方式实现的HAL,HIDL原则上被弃用。)
    if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
        // Create CameraClient based on device version reported by the HAL.
        int deviceVersion = deviceVersionAndTransport.first;
        // deviceVersion是CameraProvider中CameraDevice的版本号,目前最新的是3.7
        switch(deviceVersion) {
            case CAMERA_DEVICE_API_VERSION_1_0:
                ALOGE("Camera using old HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                        "Camera device \"%s\" HAL version %d no longer supported",
                        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:
            case CAMERA_DEVICE_API_VERSION_3_5:
            case CAMERA_DEVICE_API_VERSION_3_6:
            case CAMERA_DEVICE_API_VERSION_3_7:
                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);
        }
    }
    // camera api 1, 老古董了,这里就不分析了,其实也简单,就是创建Camera2Client对象
    if (effectiveApiLevel == API_1) { // Camera1 API route
        sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
        *client = new Camera2Client(cameraService, tmp, packageName, featureId,
                cameraId, api1CameraId, facing, sensorOrientation, clientPid, clientUid,
                servicePid, overrideForPerfClass);
    } else { // Camera2 API route
    	// Camera API 2, 创建CameraDeviceClient对象。
        sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
        *client = new CameraDeviceClient(cameraService, tmp, packageName,
                systemNativeClient, featureId, cameraId, facing, sensorOrientation,
                clientPid, clientUid, servicePid, overrideForPerfClass);
    }
    return Status::ok();
}

// 我们看下CameraDeviceClient的构造函数
// frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
        const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
        const String16& clientPackageName,
        bool systemNativeClient,
        const std::optional<String16>& clientFeatureId,
        const String8& cameraId,
        int cameraFacing,
        int sensorOrientation,
        int clientPid,
        uid_t clientUid,
        int servicePid,
        bool overrideForPerfClass) :
    // 调用父类的构造函数
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName, systemNativeClient,
                clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing, sensorOrientation,
                clientPid, clientUid, servicePid, overrideForPerfClass),
    mInputStream(),
    mStreamingRequestId(REQUEST_ID_NONE),
    mRequestIdCounter(0),
    mOverrideForPerfClass(overrideForPerfClass) {

    ATRACE_CALL();
    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}

// 上面主要就是执行父类的构造函数,其余均为变量赋值,我们看父类构造函数实现
// frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
// 其中TClientBase为CameraDeviceClientBase
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
        const sp<CameraService>& cameraService,
        const sp<TCamCallbacks>& remoteCallback,
        const String16& clientPackageName,
        bool systemNativeClient,
        const std::optional<String16>& clientFeatureId,
        const String8& cameraId,
        int api1CameraId,
        int cameraFacing,
        int sensorOrientation,
        int clientPid,
        uid_t clientUid,
        int servicePid,
        bool overrideForPerfClass,
        bool legacyClient):
        TClientBase(cameraService, remoteCallback, clientPackageName, systemNativeClient,
                clientFeatureId, cameraId, api1CameraId, cameraFacing, sensorOrientation, clientPid,
                clientUid, servicePid),
        mSharedCameraCallbacks(remoteCallback),
        mDeviceActive(false), mApi1CameraId(api1CameraId)
{
    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
            String8(clientPackageName).string(), clientPid, clientUid);

    mInitialClientPid = clientPid;
    mOverrideForPerfClass = overrideForPerfClass;
    mLegacyClient = legacyClient;
}
// 可以看到其中调用了泛型类的构造函数,其实看了一圈,最终调用到了CameraService::BasicClient的构造函数中,
// 主要做的事情就是成员变量初始化,看来这里没有什么特别重要的内容。下面我们直接看CameraDeviceClient的initialize
// 函数把。
// frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
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;

	// 又是调用父类的函数,这里比较重要。这里面创建了HidlCamera3Device对象,并且调用了其initialize函数
	// (如果是aidl HAL的话创建的就是AidlCamera3Device对象)
    res = Camera2ClientBase::initialize(providerPtr, monitorTags);
    if (res != OK) {
        return res;
    }

	//此处代码省略
	...
	...
	...
    return OK;
}

// frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
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;
    }
    IPCTransport providerTransport = IPCTransport::INVALID;
    res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr.string(),
            &providerTransport);
    if (res != OK) {
        return res;
    }
    switch (providerTransport) {
    	// 创建相应的Camera3Device对象
        case IPCTransport::HIDL:
            mDevice =
                    new HidlCamera3Device(TClientBase::mCameraIdStr, mOverrideForPerfClass,
                            mLegacyClient);
            break;
        case IPCTransport::AIDL:
            mDevice =
                    new AidlCamera3Device(TClientBase::mCameraIdStr, mOverrideForPerfClass,
                            mLegacyClient);
             break;
        default:
            ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
                    TClientBase::mCameraIdStr.string());
            return NO_INIT;
    }
    if (mDevice == NULL) {
        ALOGE("%s: Camera %s: No device connected",
                __FUNCTION__, TClientBase::mCameraIdStr.string());
        return NO_INIT;
    }
	
	// 调用Camera3Device的initialize函数
    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<NotificationListener> weakThis(this);
    res = mDevice->setNotifyCallback(weakThis);

    /** Start watchdog thread */
    mCameraServiceWatchdog = new CameraServiceWatchdog();
    mCameraServiceWatchdog->run("Camera2ClientBaseWatchdog");

    return OK;
}

// 我们以HidlCamera3Device为例进行介绍
// frameworks/av/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
  explicit HidlCamera3Device(const String8& id, bool overrideForPerfClass,
          bool legacyClient = false) : Camera3Device(id, overrideForPerfClass, legacyClient) { }
// HidlCamera3Device继承自Camera3Device类,这里调用了父类的构造函数
// 接下来看其initialize函数,又是个很长的函数,我们尽量把不重要的省略掉。
status_t HidlCamera3Device::initialize(sp<CameraProviderManager> manager,
        const String8& monitorTags) {
    ATRACE_CALL();
	// 省略代码
	...
    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    // 这里拿到了CameraProvider进程中的CameraDevice对象,并且调用了其open函数
    // start
    // frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
    // 这里的interface是CameraDevice的binder代理
    ret = interface->open(callback, [&status, &session]
        (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
            status = s;
            if (status == Status::OK) {
                *session = cameraSession;
            }
        });
	
	// hardware/interfaces/camera/device/3.2/default/CameraDevice.cpp
	// CameraDevice的open函数中调用了mModule->open
	// 这里的mModule是CameraModule类型,CameraModule是封装了rawModule(camera_module_t)
	// 的,所以这里的open最终会调用到库里面的camera_module_t的open函数。
	// mModule->common.methods->open(&mModule->common, id, device)
    res = mModule->open(mCameraId.c_str(),
           reinterpret_cast<hw_device_t**>(&device));
    // 我们看下mModule->common.methods->open在camera.v4l2_test.so里的实现
    // (这个函数是厂商必须实现的,我们目前以Google的参考HAL代码为例分析)
    //hardware/libhardware/modules/camera/3_4/v4l2_camera_hal.cpp
    static hw_module_methods_t v4l2_module_methods = {
    .open = v4l2_camera_hal::open_dev};
    // open函数指向了open_dev
    static int open_dev(const hw_module_t* module,
                    const char* name,
                    hw_device_t** device) {
  		return gCameraHAL.openDevice(module, name, device);
	}
	// 最终调用到下面的代码
	// hardware/libhardware/modules/camera/3_4/v4l2_wrapper.cpp
	  int fd = TEMP_FAILURE_RETRY(open(device_path_.c_str(), O_RDWR | O_NONBLOCK));
	  if (fd < 0) {
	    HAL_LOGE("failed to open %s (%s)", device_path_.c_str(), strerror(errno));
	    return -ENODEV;
	  }
	  // 主要就是打开对应的Camera设备节点,拿到其fd
    // end
    status_t res = manager->openHidlSession(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;
    }

	// 省略代码
	...
    return initializeCommonLocked();
}

到上面为止,open camera的流程就基本讲完了。我们再回到开始处,也就是CameraManager.java中

// connectDevice函数返回后,调用了
deviceImpl.setRemoteDevice(cameraUser);
// cameraUser是CameraDeviceClient对象的binder代理
// frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
    synchronized(mInterfaceLock) {
        // TODO: Move from decorator to direct binder-mediated exceptions
        // If setRemoteFailure already called, do nothing
        if (mInError) return;
		// 对ICameraDeviceUser进行包装,这个mRemoteDevice就是后面App进程跟
		// CameraServer进程沟通的桥梁之一。
        mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);

        IBinder remoteDeviceBinder = remoteDevice.asBinder();
        // For legacy camera device, remoteDevice is in the same process, and
        // asBinder returns NULL.
        if (remoteDeviceBinder != null) {
            try {
                remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
            } catch (RemoteException e) {
                CameraDeviceImpl.this.mDeviceExecutor.execute(mCallOnDisconnected);

                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "The camera device has encountered a serious error");
            }
        }
		// 执行回调函数,应用层收到onOpened回调
        mDeviceExecutor.execute(mCallOnOpened);
        mDeviceExecutor.execute(mCallOnUnconfigured);
    }
}

写了这么久,到现在终于写完了。刚开始想的是要把每一处细节都介绍清楚,结果发现内容实在太多,全部细节写完估计需要好几个月了。
而且自己其实理解的还不是很透彻,只是按照流程梳理了一遍。其中还有很多遗漏的地方,目前的想法时针对每一个细节的地方,每一个具体模块的地方,到最后分成一篇篇专项的文章再来介绍一遍。文章中有不足或者错误的地方还望大家指正,感谢!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
高通CamX与OpenCamera是两个不同的概念,CamX是高通公司的相机框架,而OpenCamera是一个开源的Android相机应用。因此,它们之间的代码流程是不同的。以下是OpenCamera的基本代码流程: 1. 初始化相机:OpenCamera会初始化相机设备,包括打开相机设备、配置相机参数(如分辨率、帧率、对焦模式等)。 2. 设置预览界面:OpenCamera会创建一个预览界面(SurfaceView或TextureView),用于显示相机预览画面。 3. 实现相机功能:OpenCamera实现了一系列的相机功能,如自动对焦、曝光调节、白平衡控制等。这些功能通过调用相机API来实现。 4. 拍照和录像:OpenCamera提供了拍照和录像功能。当用户点击拍照按钮时,OpenCamera会触发拍照操作,并保存照片到指定路径。而在录像模式下,OpenCamera会开始录制视频,并保存到指定路径。 5. 处理图像数据:OpenCamera在预览和拍照/录像过程中,会获取相机输出的图像数据,并进行处理。这可能包括图像增强、实时滤镜、人脸识别等操作。 6. 相机参数设置:OpenCamera还提供了一些相机参数的设置,如闪光灯模式、场景模式、ISO设置等。 7. 监听相机事件:OpenCamera会监听相机事件,如对焦完成、曝光完成等,以便在相应事件发生时作出相应的处理。 8. 释放相机资源:当不再需要使用相机时,OpenCamera会释放相机资源,包括关闭相机设备、释放预览界面等。 总的来说,OpenCamera的代码流程包括初始化相机、设置预览界面、实现相机功能、拍照和录像、处理图像数据、相机参数设置、监听相机事件和释放相机资源。这样就可以实现一个基本的相机应用程序。请注意,这只是一个简单的概述,实际的代码流程可能更加复杂和详细。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZH的Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值