Camera: SnapdragonCamera OpenCamera(二)

本文详细探讨了高通骁龙手机中,从Android Framework的openLegacy方法到CameraService的OpenCamera过程,涉及HAL层的通信机制,包括不同API接口的选择、CameraProvider管理和HIDL通信。重点剖析了CameraClient、CameraService和HAL之间的交互细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        高通骁龙相机从FrameWork、CameraService、HAL层去研究相关的OpenCamera相关用到的技术与流程。

1.FrameWork层 OpenCamera

        应用层采取method的方法调用FrameWork层的openLegacy方法openCamera,此时走的是Camera API1的接口。Framework层其实是定义了不需要必须走API1接口的方法的,下面会先介绍openLegacy的流程,然后再check另一个流程。

LA.UM.8.6.2/LINUX/android/frameworks/base/core/java/android/hardware/Camera.java

    public static Camera openLegacy(int cameraId, int halVersion) {
        if (halVersion < CAMERA_HAL_API_VERSION_1_0) {
            throw new IllegalArgumentException("Invalid HAL version " + halVersion);
        }

        return new Camera(cameraId, halVersion);
    }


    /**
     * Create a legacy camera object.
     *
     * @param cameraId The hardware camera to access, between 0 and
     * {@link #getNumberOfCameras()}-1.
     * @param halVersion The HAL API version this camera device to be opened as.
     */
    private Camera(int cameraId, int halVersion) {
        int err = cameraInitVersion(cameraId, halVersion);
        if (checkInitErrors(err)) {
            if (err == -EACCES) {
                throw new RuntimeException("Fail to connect to camera service");
            } else if (err == -ENODEV) {
                throw new RuntimeException("Camera initialization failed");
            } else if (err == -ENOSYS) {
                throw new RuntimeException("Camera initialization failed because some methods"
                        + " are not implemented");
            } else if (err == -EOPNOTSUPP) {
                throw new RuntimeException("Camera initialization failed because the hal"
                        + " version is not supported by this device");
            } else if (err == -EINVAL) {
                throw new RuntimeException("Camera initialization failed because the input"
                        + " arugments are invalid");
            } else if (err == -EBUSY) {
                throw new RuntimeException("Camera initialization failed because the camera"
                        + " device was already opened");
            } else if (err == -EUSERS) {
                throw new RuntimeException("Camera initialization failed because the max"
                        + " number of camera devices were already opened");
            }
            // Should never hit this.
            throw new RuntimeException("Unknown camera error");
        }
    }


    private int cameraInitVersion(int cameraId, int halVersion) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
        mPreviewCallback = null;
        mPostviewCallback = null;
        mUsingPreviewAllocation = false;
        mZoomListener = null;
        /* ### QC ADD-ONS: START */
        mCameraDataCallback = null;
        mCameraMetaDataCallback = null;
        /* ### QC ADD-ONS: END */

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
        }

        //这边可以获取应用层Activity的名称,作用与MTK一样,可区分出各种基于高通底层的各种三方Camera apk
        String packageName = ActivityThread.currentOpPackageName();

        //Force HAL1 if the package name falls in this bucket
        String packageList = SystemProperties.get("vendor.camera.hal1.packagelist", "");
        if (packageList.length() > 0) {
            TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
            splitter.setString(packageList);
            for (String str : splitter) {
                if (packageName.equals(str)) {
                    halVersion = CAMERA_HAL_API_VERSION_1_0;
                    break;
                }
            }
        }

        //这边使用了JNI技术调用了CameraService相关的接口
        return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
    }

LA.UM.8.6.2\LINUX\android\frameworks\base\core\jni\android_hardware_Camera.cpp

// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
    // Convert jstring to String16
    const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
        env->GetStringChars(clientPackageName, NULL));
    jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    String16 clientName(rawClientName, rawClientNameLen);
    env->ReleaseStringChars(clientPackageName,
                            reinterpret_cast<const jchar*>(rawClientName));

    sp<Camera> camera;
    if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
        // Default path: hal version is don't care, do normal camera connect.
        
        //这边根据HAL Camera API不同的版本走了不通的CameraService的绑定流程
        camera = Camera::connect(cameraId, clientName,
                Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
    } else {

        //这边根据HAL Camera API不同的版本走了不通的CameraService的绑定流程
        jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                Camera::USE_CALLING_UID, camera);
        if (status != NO_ERROR) {
            return status;
        }
    }

    if (camera == NULL) {
        return -EACCES;
    }

    // make sure camera hardware is alive
    if (camera->getStatus() != NO_ERROR) {
        return NO_INIT;
    }
    
    ...
}

       FrameWork 通过API1调用Camera流程上述已经结束,高通晓龙相机底层是支持通过其他API接口打开相机服务的,android_hardware_Camera.cpp会根据走的不同的API走不通的接口与CameraService建立联系。

    public static Camera open(int cameraId) {
        return new Camera(cameraId);
    }

    /**
     * Creates a new Camera object to access the first back-facing camera on the
     * device. If the device does not have a back-facing camera, this returns
     * null. Otherwise acts like the {@link #open(int)} call.
     *
     * @return a new Camera object for the first back-facing camera, or null if there is no
     *  backfacing camera
     * @see #open(int)
     */
    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                return new Camera(i);
            }
        }
        return null;
    }


    /** used by Camera#open, Camera#open(int) */
    Camera(int cameraId) {
        if(cameraId >= getNumberOfCameras()){
             throw new RuntimeException("Unknown camera ID");
        }
        int err = cameraInitNormal(cameraId);
        if (checkInitErrors(err)) {
            if (err == -EACCES) {
                throw new RuntimeException("Fail to connect to camera service");
            } else if (err == -ENODEV) {
                throw new RuntimeException("Camera initialization failed");
            }
            // Should never hit this.
            throw new RuntimeException("Unknown camera error");
        }
        initAppOps();
    }

    
    private static final int CAMERA_HAL_API_VERSION_NORMAL_CONNECT = -2;
    
    private int cameraInitNormal(int cameraId) {
        return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
    }

        

2.CameraService OpenCamera

        CameraService针对不同的API使用,也有不同的接口与之相匹配。connectLegacy对接API1。

LA.UM.8.6.2/LINUX/android/frameworks/av/services/camera/libcameraservice/CameraService.cpp

Status CameraService::connectLegacy(
        const sp<ICameraClient>& cameraClient,
        int api1CameraId, int halVersion,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<ICamera>* device) {

    ATRACE_CALL();
    String8 id = cameraIdIntToStr(api1CameraId);

    Status ret = Status::ok();
    sp<Client> client = nullptr;
    ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
            clientPackageName, clientUid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ false,
            /*out*/client);

    if(!ret.isOk()) {
        logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
                ret.toString8());
        return ret;
    }

    *device = client;
    return ret;
}
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 shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();

    String8 clientName8(clientPackageName);

    int originalClientPid = 0;

    ...

        sp<BasicClient> tmp = nullptr;

        //makeClient调用的是API1的接口,API2会走其他的接口
        if(!(ret = makeClient(this, cameraCb, clientPackageName,
                cameraId, api1CameraId, facing,
                clientPid, clientUid, getpid(),
                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__);

        
        //makeClient仅仅是初始化类成员函数,initialize会拿到HAL成的interface接口去做init工作
        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) {
                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);
            }
        }

    ...

CameraService里面的makeClient会根据HAl Camera API的不同,走不同的HAL version接口,cameraClient  ->  frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp

camera2Client -> frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

CameraDeviceClien -> av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp

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,
        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());
            } 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:
          case CAMERA_DEVICE_API_VERSION_3_5:
            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);
            } 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);
        } 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();
}

LA.UM.8.6.2/LINUX/android/frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp

status_t CameraClient::initialize(sp<CameraProviderManager> manager,
        const String8& /*monitorTags*/) {
    int callingPid = CameraThreadState::getCallingPid();
    status_t res;

    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

    // Verify ops permissions
    res = startCameraOps();
    if (res != OK) {
        return res;
    }

    char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

    //获得HAL的interface实例
    mHardware = new CameraHardwareInterface(camera_device_name);
    
    //开始HAL init
    res = mHardware->initialize(manager);
    if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mHardware.clear();
        return res;
    }

    //这边的callback设置可以check对应的device变化
    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            handleCallbackTimestampBatch,
            (void *)(uintptr_t)mCameraId);

    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}

LA.UM.8.6.2/LINUX/android/frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp

status_t CameraHardwareInterface::initialize(sp<CameraProviderManager> manager) {
    ALOGI("Opening camera %s", mName.string());

    status_t ret = manager->openSession(mName.string(), this, &mHidlDevice);
    if (ret != OK) {
        ALOGE("%s: openSession failed! %s (%d)", __FUNCTION__, strerror(-ret), ret);
    }
    return ret;
}

LA.UM.8.6.2/LINUX/android/frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp

status_t CameraProviderManager::openSession(const std::string &id,
        const sp<device::V1_0::ICameraDeviceCallback>& callback,
        /*out*/
        sp<device::V1_0::ICameraDevice> *session) {

    std::lock_guard<std::mutex> lock(mInterfaceMutex);

    auto deviceInfo = findDeviceInfoLocked(id,
            /*minVersion*/ {1,0}, /*maxVersion*/ {2,0});
    if (deviceInfo == nullptr) return NAME_NOT_FOUND;

    auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
    const sp<provider::V2_4::ICameraProvider> provider =
            deviceInfo->mParentProvider->startProviderInterface();
    if (provider == nullptr) {
        return DEAD_OBJECT;
    }
    saveRef(DeviceMode::CAMERA, id, provider);

    auto interface = deviceInfo1->startDeviceInterface<
            CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT>();
    if (interface == nullptr) {
        return DEAD_OBJECT;
    }
    hardware::Return<Status> status = interface->open(callback);
    if (!status.isOk()) {
        removeRef(DeviceMode::CAMERA, id);
        ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                __FUNCTION__, id.c_str(), status.description().c_str());
        return DEAD_OBJECT;
    }
    if (status == Status::OK) {
        *session = interface;
    }
    return mapToStatusT(status);
}

小结:

        本篇从FrameWork层到CamerService,CameraService最主要的一个模块就是CameraProvider的获取与管理,涉及到CameraServer与Camera HAl的HIDL通信机制,之前的MTK项目过程中就有很多没弄明白的,在新的项目中,乘着熟悉新框架的契机,把这一部分全部拎出来在下一篇认真分析一下。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值