Android 8.0系统源码分析--openCamera(HAL)启动过程源码分析(转载)

转载 Android 8.0系统源码分析–openCamera(HAL)启动过程源码分析

前面我们详细分析了从应用层调用CameraManager的openCamera的方法来打开相机的逻辑,上次的分析我们来到了CameraServer进程当中,但是还没有真正看到open操作设备节点来实现真正打开的逻辑,遗留的问题也就是从frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp文件中的status_t Camera3Device::initialize(sp manager)方法的status_t res = manager->openSession(mId.string(), this, /out/ &session);这句代码进去后进行的处理。

我们知道,Android的内核是Linux内核,Linux上所有的设备都被抽象成文件节点,对设备的操作都变成了对文件节点的操作,非常方便,我们openCamera的逻辑最终肯定也是通过open系统函数来打开camera的文件节点,而open系统调用的处理就是对应的camera驱动了。

好,我们回到正文,status_t res = manager->openSession(mId.string(), this, /out/ &session);这句逻辑中的manager是一个sp对象,那我们就来看一下frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.cpp文件中的openSession方法的实现,源码如下:

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

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

该方法中根据传入的最小和最大版本号调用findDeviceInfoLocked方法获取到一个DeviceInfo对象,其中的逻辑比较简单,源码如下:

CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
        const std::string& id,
        hardware::hidl_version minVersion, hardware::hidl_version maxVersion) const {
    for (auto& provider : mProviders) {
        for (auto& deviceInfo : provider->mDevices) {
            if (deviceInfo->mId == id &&
                    minVersion <= deviceInfo->mVersion && maxVersion >= deviceInfo->mVersion) {
                return deviceInfo.get();
            }
        }
    }
    return nullptr;
}

可以看到,该方法的逻辑就是对成员变量mProviders进行遍历,判断每个DeviceInfo的id值、最小版本、最大版本号是否符合传入的最小和最大版本,符合的话,就返回该对象,那我们就要问一下了,mProviders中的值是什么时候添加的呢?我们大概追究一下,它是在CameraService进行启动时,初始化CameraProviderManager对象的逻辑中,通过addProviderLocked方法生成具体的DeviceInfo对象,添加到mProviders成员变量中的。addProviderLocked方法的源码如下:

status_t CameraProviderManager::addProviderLocked(const std::string& newProvider, bool expected) {
    for (const auto& providerInfo : mProviders) {
        if (providerInfo->mProviderName == newProvider) {
            ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
                    newProvider.c_str());
            return ALREADY_EXISTS;
        }
    }

    sp<provider::V2_4::ICameraProvider> interface;
    interface = mServiceProxy->getService(newProvider);

    if (interface == nullptr) {
        if (expected) {
            ALOGE("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
                    newProvider.c_str());
            return BAD_VALUE;
        } else {
            return OK;
        }
    }

    sp<ProviderInfo> providerInfo =
            new ProviderInfo(newProvider, interface, this);
    status_t res = providerInfo->initialize();
    if (res != OK) {
        return res;
    }

    mProviders.push_back(providerInfo);

    return OK;
}

这个方法中有一个非常重要的对象,就是interface = mServiceProxy->getService(newProvider)逻辑返回的interface,它又是一个binder对象,获取camera属性、数量等实质性的方法都是通过它来完成的,获取成功后,以它为参数构造一个ProviderInfo对象,最后添加到mProviders成员变量当中。
getService(newProvider)是在头文件里定义的:CameraProviderManager.h

    // Standard use case - call into the normal generated static methods which invoke
    // the real hardware service manager
    struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
        virtual bool registerForNotifications(
                const std::string &serviceName,
                const sp<hidl::manager::V1_0::IServiceNotification>
                &notification) override {
            return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
                    serviceName, notification);
        }
        virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
                const std::string &serviceName) override {
            return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
        }
    };


    static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;

	 /**
     * Initialize the manager and give it a status listener; optionally accepts a service
     * interaction proxy.
     *
     * The default proxy communicates via the hardware service manager; alternate proxies can be
     * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
     */
    status_t initialize(wp<StatusListener> listener,
            ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
            

好了,我们回到openSession方法当中,找到deviceInfo对象之后,然后调用deviceInfo3->mInterface->open,而它的成员变量mInterface就是在前面我们说构造ProviderInfo时获取到的binder对象了,它实际上是hardware\interfaces\camera\device\3.2\default\CameraDevice.cpp对象了,来到这里,我们就进入了CameraDaemon进程当中,两个进程的通信是通过HIDL,其实还是binder进程间通信机制,只是它是用来提供给HAL层服务的,所以和AIDL类似,取了个HIDL的名字。这里需要说一下,为是什么是3.2下面的这个类呢?因为我们在调用openSession方法时,传入的第二个参数const sphardware::camera::device::V3_2::ICameraDeviceCallback& callback和第三个参数sphardware::camera::device::V3_2::ICameraDeviceSession *session就可以非常明显的看出来,当前调用的版本是V3_2。接下来,我们就来看一下CameraDevice.cpp类的open方法的实现,源码如下:

Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
    Status status = initStatus();
    sp<CameraDeviceSession> session = nullptr;

    if (callback == nullptr) {
        ALOGE("%s: cannot open camera %s. callback is null!",
                __FUNCTION__, mCameraId.c_str());
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    if (status != Status::OK) {
        // Provider will never pass initFailed device to client, so
        // this must be a disconnected camera
        ALOGE("%s: cannot open camera %s. camera is disconnected!",
                __FUNCTION__, mCameraId.c_str());
        _hidl_cb(Status::CAMERA_DISCONNECTED, nullptr);
        return Void();
    } else {
        mLock.lock();

        ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
        session = mSession.promote();
        if (session != nullptr && !session->isClosed()) {
            ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
            mLock.unlock();
            _hidl_cb(Status::CAMERA_IN_USE, nullptr);
            return Void();
        }

        /** Open HAL device */
        status_t res;
        camera3_device_t *device;

        ATRACE_BEGIN("camera3->open");
        res = mModule->open(mCameraId.c_str(),
                reinterpret_cast<hw_device_t**>(&device));
        ATRACE_END();

        if (res != OK) {
            ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
            mLock.unlock();
            _hidl_cb(getHidlStatus(res), nullptr);
            return Void();
        }

        /** Cross-check device version */
        if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
            ALOGE("%s: Could not open camera: "
                    "Camera device should be at least %x, reports %x instead",
                    __FUNCTION__,
                    CAMERA_DEVICE_API_VERSION_3_2,
                    device->common.version);
            device->common.close(&device->common);
            mLock.unlock();
            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
            return Void();
        }

        struct camera_info info;
        res = mModule->getCameraInfo(mCameraIdInt, &info);
        if (res != OK) {
            ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
            device->common.close(&device->common);
            mLock.unlock();
            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
            return Void();
        }

        session = createSession(
                device, info.static_camera_characteristics, callback);
        if (session == nullptr) {
            ALOGE("%s: camera device session allocation failed", __FUNCTION__);
            mLock.unlock();
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }
        if (session->isInitFailed()) {
            ALOGE("%s: camera device session init failed", __FUNCTION__);
            session = nullptr;
            mLock.unlock();
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }
        mSession = session;

        IF_ALOGV() {
            session->getInterface()->interfaceChain([](
                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
                    ALOGV("Session interface chain:");
                    for (auto iface : interfaceChain) {
                        ALOGV("  %s", iface.c_str());
                    }
                });
        }
        mLock.unlock();
    }
    _hidl_cb(status, session->getInterface());
    return Void();
}

我们先来看一下该方法的参数,第一个是callback对象,它的使用方法和我们之前讲的应用层调用openCamera时在CameraManager中传入的binder类型的callback是一样的,Server端拿到这个callback之后,就可以针对需要的节点事件回调应用层,而这里是在CameraDaemon回调CameraServer,道理是一样的。这个callback参数最终赋值给HAL层中的CameraDeviceSession类的mResultBatcher成员变量了;第二个参数是open_cb类型,从它的命名中可以看出来,它也是一个回调函数,非常方便,就像一个函数指针一样,它在CameraProviderManager一侧中像一个结构体一样传了过来,当CameraDevice类中的open执行完成后,就会将session对象作为参数回传到CameraProviderManager这一侧,我们就拿到了session,后续对camera的操作都是通过这个sesson对象来进行中转完成的。CameraProviderManager这一侧传入的结构体如下:

    hardware::Return<void> ret;
    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
            (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                status = s;
                if (status == Status::OK) {
                    *session = cameraSession;
                }
            });

我们继续阅读代码,open方法中先判断status,正常的话,接着调用res = mModule->open(mCameraId.c_str(), reinterpret_cast<hw_device_t**>(&device))来执行相机的打开操作,mModule对象是CameraDevice类的成员变量,它是在CameraDevice的构造函数中传入的,而CameraDevice类的对象是在hardware\interfaces\camera\provider\2.4\default\CameraProvider.cpp文件中的getCameraDeviceInterface_V3_x方法中构造的,该方法也是CameraDaemon进程为CameraServer进程提供的,当添加相机设备时,CameraServer就需要查询和获取camera设备,也就会使用到这个接口,getCameraDeviceInterface_V3_x方法源码如下:
sp<CameraModule> mModule;

Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
        const hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb)  {
    std::string cameraId, deviceVersion;
    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
    if (!match) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    std::string deviceName(cameraDeviceName.c_str());
    ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
    if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
        Status status = Status::OK;
        ssize_t idx = mCameraIds.indexOf(cameraId);
        if (idx == NAME_NOT_FOUND) {
            ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
            status = Status::ILLEGAL_ARGUMENT;
        } else { // invalid version
            ALOGE("%s: camera device %s does not support version %s!",
                    __FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
            status = Status::OPERATION_NOT_SUPPORTED;
        }
        _hidl_cb(status, nullptr);
        return Void();
    }

    if (mCameraStatusMap.count(cameraId) == 0 ||
            mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    sp<android::hardware::camera::device::V3_2::ICameraDevice> device;
    if (deviceVersion == kHAL3_4) {
        ALOGV("Constructing v3.4 camera device");
        sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
            new android::hardware::camera::device::V3_4::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);
        if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
            ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
            device = nullptr;
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
        }

        device = deviceImpl;
        _hidl_cb (Status::OK, device);
        return Void();
    }

    // Since some Treble HAL revisions can map to the same legacy HAL version(s), we default
    // to the newest possible Treble HAL revision, but allow for override if needed via
    // system property.
    switch (mPreferredHal3MinorVersion) {
        case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2
            ALOGV("Constructing v3.2 camera device");
            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
                    new android::hardware::camera::device::V3_2::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);
            if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
                device = nullptr;
                _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                return Void();
            }
            device = deviceImpl;
            break;
        }
        case 3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3
            ALOGV("Constructing v3.3 camera device");
            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
                    new android::hardware::camera::device::V3_3::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);
            if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
                device = nullptr;
                _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                return Void();
            }
            device = deviceImpl;
            break;
        }
        default:
            ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
            device = nullptr;
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
    }
    _hidl_cb (Status::OK, device);
    return Void();
}

可以看到,在构造CameraDevice对象时,传入的第一个参数mModule,它也是CameraProvider类的成员变量,它的定义在hardware\interfaces\camera\provider\2.4\default\CameraProvider.h头文件中,源码如下:

它是一个CameraModule对象,那么我们接下来就看看hardware\interfaces\camera\common\1.0\default\CameraModule.cpp类的open方法,来看看它是如何处理的。它的open方法源码如下:

int CameraModule::open(const char* id, struct hw_device_t** device) {
    int res;
    ATRACE_BEGIN("camera_module->open");
    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
    ATRACE_END();
    return res;
}

该方法非常简洁,就是调用mModule类的common.methods的open方法处理,它的mModule也是在CameraModule类的构造函数中传入的,而CameraModule的构造方法是在CameraProvider类的initialize()方法中调用的,源码如下:

bool CameraProvider::initialize() {
    camera_module_t *rawModule;
    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
            (const hw_module_t **)&rawModule);
    if (err < 0) {
        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
        return true;
    }

    mModule = new CameraModule(rawModule);
    err = mModule->init();
    if (err != OK) {
        ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }
    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());

    // Setup vendor tags here so HAL can setup vendor keys in camera characteristics
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
    if (!setUpVendorTags()) {
        ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__);
    }

    // Setup callback now because we are going to try openLegacy next
    err = mModule->setCallbacks(this);
    if (err != OK) {
        ALOGE("Could not set camera module callback: %d (%s)", err, strerror(-err));
        mModule.clear();
        return true;
    }

    mPreferredHal3MinorVersion =
        property_get_int32("ro.vendor.camera.wrapper.hal3TrebleMinorVersion", 3);
    ALOGV("Preferred HAL 3 minor version is %d", mPreferredHal3MinorVersion);
    switch(mPreferredHal3MinorVersion) {
        case 2:
        case 3:
            // OK
            break;
        default:
            ALOGW("Unknown minor camera device HAL version %d in property "
                    "'camera.wrapper.hal3TrebleMinorVersion', defaulting to 3",
                    mPreferredHal3MinorVersion);
            mPreferredHal3MinorVersion = 3;
    }

    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
        struct camera_info info;
        auto rc = mModule->getCameraInfo(i, &info);
        if (rc != NO_ERROR) {
            ALOGE("%s: Camera info query failed!", __func__);
            mModule.clear();
            return true;
        }

        if (checkCameraVersion(i, info) != OK) {
            ALOGE("%s: Camera version check failed!", __func__);
            mModule.clear();
            return true;
        }

        char cameraId[kMaxCameraIdLen];
        snprintf(cameraId, sizeof(cameraId), "%d", i);
        std::string cameraIdStr(cameraId);
        mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;

        addDeviceNames(i);
    }

    return false; // mInitFailed
}

======================================== V4l2 代替 ==========================================
这里构造CameraModule时传入的参数rawModule就是在该方法一开始时,通过调用int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&rawModule)获取到的,看到这里大家是不是觉得有些熟悉,CAMERA_HARDWARE_MODULE_ID就是HAL层定义的module,
v4l2_camera_hal.cpp :对应了此接口

static hw_module_methods_t v4l2_module_methods = {
    .open = v4l2_camera_hal::open_dev};

camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
    .common =
        {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
            .hal_api_version = HARDWARE_HAL_API_VERSION,
            .id = CAMERA_HARDWARE_MODULE_ID,
            .name = "V4L2 Camera HAL v3",
            .author = "The Android Open Source Project",
            .methods = &v4l2_module_methods,
            .dso = nullptr,
            .reserved = {0},
        },
    .get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras,
    .get_camera_info = v4l2_camera_hal::get_camera_info,
    .set_callbacks = v4l2_camera_hal::set_callbacks,
    .get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops,
    .open_legacy = v4l2_camera_hal::open_legacy,
    .set_torch_mode = v4l2_camera_hal::set_torch_mode,
    .init = nullptr,
    .reserved = {nullptr, nullptr, nullptr, nullptr, nullptr}};

接着打开camera

static int open_dev(const hw_module_t* module,
                    const char* name,
                    hw_device_t** device) {
  return gCameraHAL.openDevice(module, name, device);
}
int V4L2CameraHAL::openDevice(const hw_module_t* module,
                              const char* name,
                              hw_device_t** device) {
  HAL_LOG_ENTER();

  if (module != &HAL_MODULE_INFO_SYM.common) {
    HAL_LOGE(
        "Invalid module %p expected %p", module, &HAL_MODULE_INFO_SYM.common);
    return -EINVAL;
  }

  int id;
  if (!android::base::ParseInt(name, &id, 0, getNumberOfCameras() - 1)) {
      HAL_LOGV("opendevice returns error");
    return -EINVAL;
  }
  // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
  return mCameras[id]->openDevice(module, device);
}

最重要的是mCameras[id]->openDevice(module, device),而mCameras是V4L2CameraHAL构造的时候创建,opendir(“/dev”) 遍历node将设备放进去

// Default global camera hal.
static V4L2CameraHAL gCameraHAL;

V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) {
  HAL_LOG_ENTER();
  // Adds all available V4L2 devices.
  // List /dev nodes.
  DIR* dir = opendir("/dev");
  if (dir == NULL) {
    HAL_LOGE("Failed to open /dev");
    return;
  }
  // Find /dev/video* nodes.
  dirent* ent;
  std::vector<std::string> nodes;
  while ((ent = readdir(dir))) {
    std::string desired = "video";
    size_t len = desired.size();
    if (strncmp(desired.c_str(), ent->d_name, len) == 0) {
      if (strlen(ent->d_name) > len && isdigit(ent->d_name[len])) {
        // ent is a numbered video node.
        nodes.push_back(std::string("/dev/") + ent->d_name);
        HAL_LOGV("Found video node %s.", nodes.back().c_str());
      }
    }
  }
  std::sort(nodes.begin(),nodes.end());
  // Test each for V4L2 support and uniqueness.
  std::unordered_set<std::string> buses;
  std::string bus;
  v4l2_capability cap;
  int fd;
  int id = 0;
  for (const auto& node : nodes) {
      // Open the node.
      if (strcmp(node.c_str(), FRONT_CAMERA_NODE) == 0 || strcmp(node.c_str(), REAR_CAMERA_NODE) == 0)
      {
          fd = TEMP_FAILURE_RETRY(open(node.c_str(), O_RDWR));
          if (fd < 0) {
              HAL_LOGE("failed to open %s (%s).", node.c_str(), strerror(errno));
              continue;
          }
          HAL_LOGV("VIDIOC_QUERYCAP on video node %s",node.c_str());
          // Read V4L2 capabilities.
          if (TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_QUERYCAP, &cap)) != 0) {
              HAL_LOGE(
                      "VIDIOC_QUERYCAP on %s fail: %s.", node.c_str(), strerror(errno));
          } else if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
              HAL_LOGE("%s is not a V4L2 video capture device.", node.c_str());
          } else {
              // If the node is unique, add a camera for it.
              bus = reinterpret_cast<char*>(cap.bus_info);
              if (buses.insert(bus).second) {
                  HAL_LOGV("Found unique bus at %s.", node.c_str());
                  std::unique_ptr<V4L2Camera> cam(V4L2Camera::NewV4L2Camera(id++, node));
                  if (cam) {
                      mCameras.push_back(std::move(cam));
                  } else {
                      HAL_LOGE("Failed to initialize camera at %s.", node.c_str());
                  }
                  HAL_LOGE("device:%s create over", node.c_str());
              }
          }
          close(fd);
      }
      else
      {
          continue;
      }
  }
}

让我们看看openDevice(const hw_module_t *module, hw_device_t **device),两个参数一个是hw_module_t,另一个是hw_device_t
v4l2_camera.cpp:

int Camera::openDevice(const hw_module_t *module, hw_device_t **device)
{
    HAL_LOGV("Id:%d:Opening camera device", mId);
    ATRACE_CALL();
    android::Mutex::Autolock al(mDeviceLock);

    if (mBusy) {
        HAL_LOGE("Id:%d: Error! Camera device already opened", mId);
        return -EBUSY;
    }

    int connectResult = connect();
    if (connectResult != 0) {
      return connectResult;
    }
    mBusy = true;
    mDevice.common.module = const_cast<hw_module_t*>(module);
    *device = &mDevice.common;
    HAL_LOGV("---------------x Id:%d", mId);
    return 0;
}
int V4L2Camera::connect() {
  HAL_LOG_ENTER();

  if (connection_) {
    HAL_LOGE("Already connected. Please disconnect and try again.");
    return -EIO;
  }

  connection_.reset(new V4L2Wrapper::Connection(device_));
  if (connection_->status()) {
    HAL_LOGE("Failed to connect to device.");
    return connection_->status();
  }

  device_->Init();
  device_->StreamOn();
  // TODO(b/29185945): confirm this is a supported device.
  // This is checked by the HAL, but the device at |device_|'s path may
  // not be the same one that was there when the HAL was loaded.
  // (Alternatively, better hotplugging support may make this unecessary
  // by disabling cameras that get disconnected and checking newly connected
  // cameras, so connect() is never called on an unsupported camera)

  // TODO(b/29158098): Inform service of any flashes that are no longer
  // available because this camera is in use.
  HAL_LOG_EXIT();
  return 0;
}

======================================== 此处为原文 ==========================================
这里构造CameraModule时传入的参数rawModule就是在该方法一开始时,通过调用int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&rawModule)获取到的,看到这里大家是不是觉得有些熟悉,CAMERA_HARDWARE_MODULE_ID就是HAL层定义的module,从这里往下就和对应的设备厂商有密切关系了,当然具体的实现也就差别很大了,而不像我们前面到这里,不分厂商,所有设备,只要是android都是通用的。好了,我这里下载的8.0源码中提供了三个厂商的实现,分别命名为google、huawei、lge,截图如下:
在这里插入图片描述
google目录下具体的实现使用的是高通的设备,我们就来看看这个是怎么实现的。高通相机中的hw_module_t、camera_module_t两个结构体定义在device\google\marlin\camera\QCamera2\QCamera2Hal.cpp文件中,在CameraProvider类的initialize()方法中调用hw_get_module获取到的就是这里定义的camera_module_t,它也就是构造CameraModule时传入的参数,好了,回到CameraModule类的open方法中,继续调用它的common(这里就是camera_module_t结构体的第一个成员变量common了,它指向camera_common结构体)的methods(就是static hw_module_t camera_common结构体的倒数第三个属性methods了,它指向&qcamera::QCamera2Factory::mModuleMethods)的open方法,我们还是以goole目录下高通的实现为例,继续看一下QCamera2Factory类的mModuleMethods的定义,device\google\marlin\camera\QCamera2\QCamera2Factory.cpp文件中的mModuleMethods定义源码如下:

struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
    .open = QCamera2Factory::camera_device_open,
};
     这里的open又指向了QCamera2Factory类的camera_device_open方法,该方法的源码如下:

int QCamera2Factory::camera_device_open(
    const struct hw_module_t *module, const char *id,
    struct hw_device_t **hw_device)
{
    int rc = NO_ERROR;
    if (module != &HAL_MODULE_INFO_SYM.common) {
        LOGE("Invalid module. Trying to open %p, expect %p",
            module, &HAL_MODULE_INFO_SYM.common);
        return INVALID_OPERATION;
    }
    if (!id) {
        LOGE("Invalid camera id");
        return BAD_VALUE;
    }
 
    if(gQCameraMuxer)
        rc =  gQCameraMuxer->camera_device_open(module, id, hw_device);
    else
        rc = gQCamera2Factory->cameraDeviceOpen(atoi(id), hw_device);
 
    return rc;
}

这里先判断成员变量gQCameraMuxer是否为空,它是在QCamera2Factory类的构造函数中,判断如果当前为双摄(bDualCamera为true,它是通过配置项persist.camera.dual.camera获取的)的情况下获取的,这里我们假设它不为空,那么就调用rc = gQCameraMuxer->camera_device_open(module, id, hw_device)来继续打开camera,gQCameraMuxer的类型为QCameraMuxer,接下来看一下device\google\marlin\camera\QCamera2\HAL\QCameraMuxer.cpp类中的camera_device_open方法的实现,源码如下:

int QCameraMuxer::camera_device_open(
        __unused const struct hw_module_t *module, const char *id,
        struct hw_device_t **hw_device)
{
    int rc = NO_ERROR;
    LOGH("id= %d",atoi(id));
    if (!id) {
        LOGE("Invalid camera id");
        return BAD_VALUE;
    }
 
    rc =  gMuxer->cameraDeviceOpen(atoi(id), hw_device);
    LOGH("id= %d, rc: %d", atoi(id), rc);
    return rc;
}

该方法的逻辑也非常简洁,参数正确,就接着调用gMuxer变量的cameraDeviceOpen方法来处理,gMuxer就是当前类的实例,它的cameraDeviceOpen方法的源码如下:

int QCameraMuxer::cameraDeviceOpen(int camera_id,
        struct hw_device_t **hw_device)
{
    int rc = NO_ERROR;
    uint32_t phyId = 0;
    qcamera_logical_descriptor_t *cam = NULL;
 
    if (camera_id < 0 || camera_id >= m_nLogicalCameras) {
        LOGE("Camera id %d not found!", camera_id);
        return -ENODEV;
    }
 
    if ( NULL == m_pLogicalCamera) {
        LOGE("Hal descriptor table is not initialized!");
        return NO_INIT;
    }
 
    char prop[PROPERTY_VALUE_MAX];
    property_get("persist.camera.dc.frame.sync", prop, "1");
    m_bFrameSyncEnabled = atoi(prop);
 
    // Get logical camera
    cam = &m_pLogicalCamera[camera_id];
 
    if (m_pLogicalCamera[camera_id].device_version ==
            CAMERA_DEVICE_API_VERSION_1_0) {
        // HW Dev Holders
        hw_device_t *hw_dev[cam->numCameras];
 
        if (m_pPhyCamera[cam->pId[0]].type != CAM_TYPE_MAIN) {
            LOGE("Physical camera at index 0 is not main!");
            return UNKNOWN_ERROR;
        }
 
        // Open all physical cameras
        for (uint32_t i = 0; i < cam->numCameras; i++) {
            phyId = cam->pId[i];
            QCamera2HardwareInterface *hw =
                    new QCamera2HardwareInterface((uint32_t)phyId);
            if (!hw) {
                LOGE("Allocation of hardware interface failed");
                return NO_MEMORY;
            }
            hw_dev[i] = NULL;
 
            // Make Camera HWI aware of its mode
            cam_sync_related_sensors_event_info_t info;
            info.sync_control = CAM_SYNC_RELATED_SENSORS_ON;
            info.mode = m_pPhyCamera[phyId].mode;
            info.type = m_pPhyCamera[phyId].type;
            rc = hw->setRelatedCamSyncInfo(&info);
            hw->setFrameSyncEnabled(m_bFrameSyncEnabled);
            if (rc != NO_ERROR) {
                LOGE("setRelatedCamSyncInfo failed %d", rc);
                delete hw;
                return rc;
            }
 
            rc = hw->openCamera(&hw_dev[i]);
            if (rc != NO_ERROR) {
                delete hw;
                return rc;
            }
            hw->getCameraSessionId(&m_pPhyCamera[phyId].camera_server_id);
            m_pPhyCamera[phyId].dev = reinterpret_cast<camera_device_t*>(hw_dev[i]);
            m_pPhyCamera[phyId].hwi = hw;
            cam->sId[i] = m_pPhyCamera[phyId].camera_server_id;
            LOGH("camera id %d server id : %d hw device %x, hw %x",
                     phyId, cam->sId[i], hw_dev[i], hw);
        }
    } else {
        LOGE("Device version for camera id %d invalid %d",
                 camera_id, m_pLogicalCamera[camera_id].device_version);
        return BAD_VALUE;
    }
 
    cam->dev.common.tag = HARDWARE_DEVICE_TAG;
    cam->dev.common.version = HARDWARE_DEVICE_API_VERSION(1, 0);
    cam->dev.common.close = close_camera_device;
    cam->dev.ops = &mCameraMuxerOps;
    cam->dev.priv = (void*)cam;
    *hw_device = &cam->dev.common;
    return rc;
}

该方法中最重要的就是中间的for循环了,先构造QCamera2HardwareInterface对象,然后调用它的openCamera方法打开camera,接下来就看一下device\google\marlin\camera\QCamera2\HAL3\QCamera3HWI.cpp类的openCamera方法的实现,源码如下:

int QCamera3HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
    int rc = 0;
    if (mState != CLOSED) {
        *hw_device = NULL;
        return PERMISSION_DENIED;
    }
 
    m_perfLock.lock_acq();
    LOGI("[KPI Perf]: E PROFILE_OPEN_CAMERA camera id %d",
             mCameraId);
 
    rc = openCamera();
    if (rc == 0) {
        *hw_device = &mCameraDevice.common;
    } else
        *hw_device = NULL;
 
    m_perfLock.lock_rel();
    LOGI("[KPI Perf]: X PROFILE_OPEN_CAMERA camera id %d, rc: %d",
             mCameraId, rc);
 
    if (rc == NO_ERROR) {
        mState = OPENED;
    }
    return rc;
}

它又是转调另一个openCamera方法来处理的,源码如下:

int QCamera3HardwareInterface::openCamera()
{
    int rc = 0;
    char value[PROPERTY_VALUE_MAX];
 
    KPI_ATRACE_CALL();
    if (mCameraHandle) {
        LOGE("Failure: Camera already opened");
        return ALREADY_EXISTS;
    }
 
    rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId);
    if (rc < 0) {
        LOGE("Failed to reserve flash for camera id: %d",
                mCameraId);
        return UNKNOWN_ERROR;
    }
 
    rc = camera_open((uint8_t)mCameraId, &mCameraHandle);
    if (rc) {
        LOGE("camera_open failed. rc = %d, mCameraHandle = %p", rc, mCameraHandle);
        return rc;
    }
 
    if (!mCameraHandle) {
        LOGE("camera_open failed. mCameraHandle = %p", mCameraHandle);
        return -ENODEV;
    }
 
    rc = mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
            camEvtHandle, (void *)this);
 
    if (rc < 0) {
        LOGE("Error, failed to register event callback");
        /* Not closing camera here since it is already handled in destructor */
        return FAILED_TRANSACTION;
    }
 
    mExifParams.debug_params =
            (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
    if (mExifParams.debug_params) {
        memset(mExifParams.debug_params, 0, sizeof(mm_jpeg_debug_exif_params_t));
    } else {
        LOGE("Out of Memory. Allocation failed for 3A debug exif params");
        return NO_MEMORY;
    }
    mFirstConfiguration = true;
 
    //Notify display HAL that a camera session is active.
    //But avoid calling the same during bootup because camera service might open/close
    //cameras at boot time during its initialization and display service will also internally
    //wait for camera service to initialize first while calling this display API, resulting in a
    //deadlock situation. Since boot time camera open/close calls are made only to fetch
    //capabilities, no need of this display bw optimization.
    //Use "service.bootanim.exit" property to know boot status.
    property_get("service.bootanim.exit", value, "0");
    if (atoi(value) == 1) {
        pthread_mutex_lock(&gCamLock);
        if (gNumCameraSessions++ == 0) {
            setCameraLaunchStatus(true);
        }
        pthread_mutex_unlock(&gCamLock);
    }
 
    //fill the session id needed while linking dual cam
    pthread_mutex_lock(&gCamLock);
    rc = mCameraHandle->ops->get_session_id(mCameraHandle->camera_handle,
        &sessionId[mCameraId]);
    pthread_mutex_unlock(&gCamLock);
 
    if (rc < 0) {
        LOGE("Error, failed to get sessiion id");
        return UNKNOWN_ERROR;
    } else {
        //Allocate related cam sync buffer
        //this is needed for the payload that goes along with bundling cmd for related
        //camera use cases
        m_pRelCamSyncHeap = new QCamera3HeapMemory(1);
        rc = m_pRelCamSyncHeap->allocate(sizeof(cam_sync_related_sensors_event_info_t));
        if(rc != OK) {
            rc = NO_MEMORY;
            LOGE("Dualcam: Failed to allocate Related cam sync Heap memory");
            return NO_MEMORY;
        }
 
        //Map memory for related cam sync buffer
        rc = mCameraHandle->ops->map_buf(mCameraHandle->camera_handle,
                CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF,
                m_pRelCamSyncHeap->getFd(0),
                sizeof(cam_sync_related_sensors_event_info_t),
                m_pRelCamSyncHeap->getPtr(0));
        if(rc < 0) {
            LOGE("Dualcam: failed to map Related cam sync buffer");
            rc = FAILED_TRANSACTION;
            return NO_MEMORY;
        }
        m_pRelCamSyncBuf =
                (cam_sync_related_sensors_event_info_t*) DATA_PTR(m_pRelCamSyncHeap,0);
    }
 
    LOGH("mCameraId=%d",mCameraId);
 
    return NO_ERROR;
}

这里又转调camera_open方法来处理,camera_open方法的实现是在device\google\marlin\camera\QCamera2\stack\mm-camera-interface\src\mm_camera_interface.c文件中,源码如下:

int32_t camera_open(uint8_t camera_idx, mm_camera_vtbl_t **camera_vtbl)
{
    int32_t rc = 0;
    mm_camera_obj_t *cam_obj = NULL;
 
#ifdef QCAMERA_REDEFINE_LOG
    mm_camera_set_dbg_log_properties();
#endif
 
    LOGD("E camera_idx = %d\n", camera_idx);
    if (camera_idx >= g_cam_ctrl.num_cam) {
        LOGE("Invalid camera_idx (%d)", camera_idx);
        return -EINVAL;
    }
 
    pthread_mutex_lock(&g_intf_lock);
    /* opened already */
    if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
        /* Add reference */
        g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
        pthread_mutex_unlock(&g_intf_lock);
        LOGD("opened alreadyn");
        *camera_vtbl = &g_cam_ctrl.cam_obj[camera_idx]->vtbl;
        return rc;
    }
 
    cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
    if(NULL == cam_obj) {
        pthread_mutex_unlock(&g_intf_lock);
        LOGE("no mem");
        return -EINVAL;
    }
 
    /* initialize camera obj */
    memset(cam_obj, 0, sizeof(mm_camera_obj_t));
    cam_obj->ctrl_fd = -1;
    cam_obj->ds_fd = -1;
    cam_obj->ref_count++;
    cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
    cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
    cam_obj->vtbl.ops = &mm_camera_ops;
    pthread_mutex_init(&cam_obj->cam_lock, NULL);
    /* unlock global interface lock, if not, in dual camera use case,
      * current open will block operation of another opened camera obj*/
    pthread_mutex_lock(&cam_obj->cam_lock);
    pthread_mutex_unlock(&g_intf_lock);
 
    rc = mm_camera_open(cam_obj);
 
    pthread_mutex_lock(&g_intf_lock);
    if (rc != 0) {
        LOGE("mm_camera_open err = %d", rc);
        pthread_mutex_destroy(&cam_obj->cam_lock);
        g_cam_ctrl.cam_obj[camera_idx] = NULL;
        free(cam_obj);
        cam_obj = NULL;
        pthread_mutex_unlock(&g_intf_lock);
        *camera_vtbl = NULL;
        return rc;
    } else {
        LOGD("Open succeded\n");
        g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
        pthread_mutex_unlock(&g_intf_lock);
        *camera_vtbl = &cam_obj->vtbl;
        return 0;
    }
}

这里调用malloc给方法变量分配内存,memset初始化,然后接着调用mm_camera_open继续处理,mm_camera_open方法的实现在device\google\marlin\camera\QCamera2\stack\mm-camera-interface\src\mm_camera_interface.c文件中,源码如下:

int32_t mm_camera_open(mm_camera_obj_t *my_obj)
{
    char dev_name[MM_CAMERA_DEV_NAME_LEN];
    int32_t rc = 0;
    int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
    uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
    int cam_idx = 0;
    const char *dev_name_value = NULL;
    int l_errno = 0;
 
    LOGD("begin\n");
 
    if (NULL == my_obj) {
        goto on_error;
    }
    dev_name_value = mm_camera_util_get_dev_name(my_obj->my_hdl);
    if (NULL == dev_name_value) {
        goto on_error;
    }
    snprintf(dev_name, sizeof(dev_name), "/dev/%s",
             dev_name_value);
    sscanf(dev_name, "/dev/video%d", &cam_idx);
    LOGD("dev name = %s, cam_idx = %d", dev_name, cam_idx);
 
    do{
        n_try--;
        errno = 0;
        my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
        l_errno = errno;
        LOGD("ctrl_fd = %d, errno == %d", my_obj->ctrl_fd, l_errno);
        if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 )) {
            break;
        }
        LOGE("Failed with %s error, retrying after %d milli-seconds",
              strerror(errno), sleep_msec);
        usleep(sleep_msec * 1000U);
    }while (n_try > 0);
 
    if (my_obj->ctrl_fd < 0) {
        LOGE("cannot open control fd of '%s' (%s)\n",
                  dev_name, strerror(l_errno));
        if (l_errno == EBUSY)
            rc = -EUSERS;
        else
            rc = -1;
        goto on_error;
    } else {
        mm_camera_get_session_id(my_obj, &my_obj->sessionid);
        LOGH("Camera Opened id = %d sessionid = %d", cam_idx, my_obj->sessionid);
    }
 
#ifdef DAEMON_PRESENT
    /* open domain socket*/
    n_try = MM_CAMERA_DEV_OPEN_TRIES;
    do {
        n_try--;
        my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
        l_errno = errno;
        LOGD("ds_fd = %d, errno = %d", my_obj->ds_fd, l_errno);
        if((my_obj->ds_fd >= 0) || (n_try <= 0 )) {
            LOGD("opened, break out while loop");
            break;
        }
        LOGD("failed with I/O error retrying after %d milli-seconds",
              sleep_msec);
        usleep(sleep_msec * 1000U);
    } while (n_try > 0);
 
    if (my_obj->ds_fd < 0) {
        LOGE("cannot open domain socket fd of '%s'(%s)\n",
                  dev_name, strerror(l_errno));
        rc = -1;
        goto on_error;
    }
#else /* DAEMON_PRESENT */
    cam_status_t cam_status;
    cam_status = mm_camera_module_open_session(my_obj->sessionid,
            mm_camera_module_event_handler);
    if (cam_status < 0) {
        LOGE("Failed to open session");
        if (cam_status == CAM_STATUS_BUSY) {
            rc = -EUSERS;
        } else {
            rc = -1;
        }
        goto on_error;
    }
#endif /* DAEMON_PRESENT */
 
    pthread_mutex_init(&my_obj->msg_lock, NULL);
    pthread_mutex_init(&my_obj->cb_lock, NULL);
    pthread_mutex_init(&my_obj->evt_lock, NULL);
    PTHREAD_COND_INIT(&my_obj->evt_cond);
 
    LOGD("Launch evt Thread in Cam Open");
    snprintf(my_obj->evt_thread.threadName, THREAD_NAME_SIZE, "CAM_Dispatch");
    mm_camera_cmd_thread_launch(&my_obj->evt_thread,
                                mm_camera_dispatch_app_event,
                                (void *)my_obj);
 
    /* launch event poll thread
     * we will add evt fd into event poll thread upon user first register for evt */
    LOGD("Launch evt Poll Thread in Cam Open");
    snprintf(my_obj->evt_poll_thread.threadName, THREAD_NAME_SIZE, "CAM_evntPoll");
    mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
                                 MM_CAMERA_POLL_TYPE_EVT);
    mm_camera_evt_sub(my_obj, TRUE);
 
    /* unlock cam_lock, we need release global intf_lock in camera_open(),
     * in order not block operation of other Camera in dual camera use case.*/
    pthread_mutex_unlock(&my_obj->cam_lock);
    LOGD("end (rc = %d)\n", rc);
    return rc;
 
on_error:
 
    if (NULL == dev_name_value) {
        LOGE("Invalid device name\n");
        rc = -1;
    }
 
    if (NULL == my_obj) {
        LOGE("Invalid camera object\n");
        rc = -1;
    } else {
        if (my_obj->ctrl_fd >= 0) {
            close(my_obj->ctrl_fd);
            my_obj->ctrl_fd = -1;
        }
#ifdef DAEMON_PRESENT
        if (my_obj->ds_fd >= 0) {
            mm_camera_socket_close(my_obj->ds_fd);
            my_obj->ds_fd = -1;
        }
#endif
    }
 
    /* unlock cam_lock, we need release global intf_lock in camera_open(),
     * in order not block operation of other Camera in dual camera use case.*/
    pthread_mutex_unlock(&my_obj->cam_lock);
    return rc;
}

到这里,终于看到了open的系统调用,HAL端也就是从这里进入内核,调用驱动来处理的,这里大家可以看到,是通过do/while循环来处理的,有一个重试机制,重试次数n_try不断的减小,当它等于0时,相机设备还未正常打开,就退出do/while循环了,它的初值为MM_CAMERA_DEV_OPEN_TRIES,该宏定义的值为20,在do判断中,只要if((my_obj->ctrl_fd >= 0) || (errno != EIO && errno != ETIMEDOUT) || (n_try <= 0 ))条件中有一个成立,就跳出循环,(my_obj->ctrl_fd >= 0)的意思是就camera打开成功,返回的FD有效;(errno != EIO && errno != ETIMEDOUT)的意思是未出现IO或者超时错误;(n_try <= 0 )意思是重试次数已用完,打开成功后,还要进行一些其他初始化的操作。

到这里,openCamera才算完成了,大家可以看到,中间的过程真是复杂,当然我们所分析的部分还没有包含驱动部分,想要搞清楚整个逻辑,还是要花费很大的气力的,也希望我们搞技术的同事,能够认认真真的静下心来专心搞技术,以此来提升我们的能力。

好了,今天就到这里,休息一下!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Camera HAL的启动流程主要分为以下几个步骤。 首先,上层应用通过调用CameraManager的openCamera方法来请求打开相机。这个方法会调用CameraManagerService中的openCamera方法,并传递相应的参数。 接着,CameraManagerService会查找相应的硬件相机模块,使用hw_get_module函数来获取相机模块的实例。这个函数会根据设备配置文件中的相机模块信息来加载相应的动态库,并返回相机模块的实例。 然后,CameraManagerService会通过getCameraInfo方法获取相机的详细信息,包括相机的ID、方向和镜像设置等。 接下来,CameraManagerService会调用相机模块的open方法来打开相机设备。相机模块会根据具体硬件实现来进行相机设备的初始化工作。 在相机设备打开成功后,CameraManagerService会创建一个CameraDevice实例,并将其返回给上层应用。 最后,上层应用可以通过CameraDevice实例来进行相机的操作,例如拍照、录像等。 总之,Camera HAL的启动流程包括应用调用CameraManager的openCamera方法、CameraManagerService查找相机模块、相机模块的初始化和相机设备的打开。通过这些步骤,上层应用可以获取到一个可用的相机设备,并进行相关的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Camera打开流程](https://download.csdn.net/download/sinat_21855227/9483107)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Android 13 Camera HAL启动流程(1)](https://blog.csdn.net/weixin_41678668/article/details/130958729)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Android 13 Camera HAL启动流程(2)](https://blog.csdn.net/weixin_41678668/article/details/130997399)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值