Camera2 CameraService 启动

参考链接:https://liuhongwei.blog.csdn.net/article/details/108684612

CameraService 的起点需要从 init.rc 说起。解析 init.rc 脚本是在 init.cpp 入口方法 main 中开始解析的。mediaserver 服务进程随即就会启动。
frameworks/av/media/mediaserver/mediaserver.rc

service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
    ioprio rt 4
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

经过分析可知,mediaserver 执行程序位于 main_mediaserver.cpp 中。调用 CameraService 类 instantiate() 启动了相机服务。

frameworks/av/media/mediaserver/main_mediaserver.cpp

using namespace android;

int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);

    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm(defaultServiceManager());
    ALOGI("ServiceManager: %p", sm.get());
    AIcu_initializeIcuOrDie();
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
    registerExtensions();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

再来看一下对应的 mk 文件,果然编译为 EXECUTABLE 类型。BUILD_EXECUTABLE 会生成可执行二进制文件到 /system/bin/ 下。

frameworks/av/media/mediaserver/Android.bp

cc_binary {
    name: "mediaserver",
    srcs: ["main_mediaserver.cpp"],
    shared_libs: [
        "libresourcemanagerservice",
        "liblog",
        "libmediaplayerservice",
        "libutils",
        "libbinder",
        "libandroidicu",
        "android.hardware.media.omx@1.0",
    ],
    static_libs: [
        "libregistermsext",
    ],
    include_dirs: [
        "frameworks/av/media/libmediaplayerservice",
        "frameworks/av/services/mediaresourcemanager",
    ],
    // back to 32-bit, b/126502613
    compile_multilib: "32",
    init_rc: ["mediaserver.rc"],
    cflags: [
        "-Werror",
        "-Wall",
    ],
    vintf_fragments: ["manifest_media_c2_software.xml"],
}

CameraService 类 instantiate() 实际继承自 BinderService。instantiate() 方法内部调用了 publish() 方法。这里将 CameraService 服务注册到了“总管” ServiceManager 中。对应的查询名称是通过 CameraService::getServiceName() 方法获取的,这个方法返回了 “media.camera”。我们从 Java 层查询的服务正是 Native 注册的相机服务。

frameworks/native/include/binder/BinderService.h

// ---------------------------------------------------------------------------
namespace android {

template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }
    ......
    static void instantiate() { publish(); }
    ......
};

}; // namespace android
// ---------------------------------------------------------------------------

再看 CameraService 类定义,就不难理解上面描述的内容了,BinderService 是一个模板类。这里其 SERVICE 对应的就是 CameraService。

frameworks/av/services/camera/libcameraservice/CameraService.h

class CameraService :
    public BinderService<CameraService>,
    public BnCameraService,
    public IBinder::DeathRecipient,
    public camera_module_callbacks_t
{
    friend class BinderService<CameraService>;
public:
    ......
    // Implementation of BinderService<T>
    static char const* getServiceName() { return "media.camera"; }
    ......
}

CameraService 构造函数中没干什么大事,初始化了一些成员变量。

frameworks/av/services/camera/libcameraservice/CameraService.cpp

static CameraService *gCameraService;

CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
        mSoundRef(0), mModule(0), mFlashlight(0) {
    ALOGI("CameraService started (pid=%d)", getpid());
    gCameraService = this;

    this->camera_device_status_change = android::camera_device_status_change;
    this->torch_mode_status_change = android::torch_mode_status_change;

    mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}

onFirstRef() 属于其父类 RefBase,该函数在强引用 sp 新增引用计数时调用。延迟加载相机 HAL 模块。

1.加载相机 HAL 模块
2.初始化相机 HAL 模块
3.获取 camera 个数
4.查找闪光灯
5.初始化每个相机设备的状态
6.将 CameraService 注册到 CameraDeviceFactory
7.ping CameraServiceProxy

CameraService.cpp–>onFirstRef()

frameworks/av/services/camera/libcameraservice/CameraService.cpp

void CameraService::onFirstRef()
{
    BnCameraService::onFirstRef();
    // 如果服务正在重启,则更新电池寿命跟踪
    BatteryNotifier& notifier(BatteryNotifier::getInstance());
    notifier.noteResetCamera();
    notifier.noteResetFlashlight();
    // 加载相机 HAL 模块
    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));
        logServiceError("Could not load camera HAL module", err);
        mNumberOfCameras = 0;
        return;
    }
    // 初始化相机 HAL 模块
    mModule = new CameraModule(rawModule);
    err = mModule->init();
    if (err != OK) {
        ALOGE("Could not initialize camera HAL module: %d (%s)", err,
            strerror(-err));
        logServiceError("Could not initialize camera HAL module", err);

        mNumberOfCameras = 0;
        delete mModule;
        mModule = nullptr;
        return;
    }
    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
    // 获取 camera 个数
    mNumberOfCameras = mModule->getNumberOfCameras();
    mNumberOfNormalCameras = mNumberOfCameras;

    // 在我们第一次调用 get_camera_info 之前设置供应商标签,
    // 因为 HAL 可能需要在 get_camera_info 中设置静态供应商密钥
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
        setUpVendorTags();
    }
    mFlashlight = new CameraFlashlight(*mModule, *this);
    // 查找闪光灯
    status_t res = mFlashlight->findFlashUnits();
    if (res) {
        // impossible because we haven't open any camera devices.
        ALOGE("Failed to find flash units.");
    }
    int latestStrangeCameraId = INT_MAX;
    for (int i = 0; i < mNumberOfCameras; i++) {
        String8 cameraId = String8::format("%d", i);

        // 获取相机信息,填充 camera_info 
        struct camera_info info;
        bool haveInfo = true;
        status_t rc = mModule->getCameraInfo(i, &info);
        if (rc != NO_ERROR) {
            ALOGE("%s: Received error loading camera info for device %d, cost and"
                    " conflicting devices fields set to defaults for this device.",
                    __FUNCTION__, i);
            haveInfo = false;
        }
        // 检查向后兼容性支持
        if (haveInfo) {
            if (checkCameraCapabilities(i, info, &latestStrangeCameraId) != OK) {
                delete mModule;
                mModule = nullptr;
                return;
            }
        }
        // Defaults to use for cost and conflicting devices
        int cost = 100;
        char** conflicting_devices = nullptr;
        size_t conflicting_devices_length = 0;
        // If using post-2.4 module version, query the cost + conflicting devices from the HAL
        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && haveInfo) {
            cost = info.resource_cost;
            conflicting_devices = info.conflicting_devices;
            conflicting_devices_length = info.conflicting_devices_length;
        }
        std::set<String8> conflicting;
        for (size_t i = 0; i < conflicting_devices_length; i++) {
            conflicting.emplace(String8(conflicting_devices[i]));
        }
        // 初始化每个相机设备的状态
        {
            Mutex::Autolock lock(mCameraStatesLock);
            mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost,
                    conflicting));
        }
        if (mFlashlight->hasFlashUnit(cameraId)) {
            mTorchStatusMap.add(cameraId,
                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
        }
    }
    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_1) {
        mModule->setCallbacks(this);
    }
    // 将 CameraService 注册到 CameraDeviceFactory
    CameraDeviceFactory::registerService(this);
    // ping  CameraServiceProxy
    CameraService::pingCameraServiceProxy();
}

先来了解一下 camera_module_t,注释的非常详细。

hardware/libhardware/include/hardware/camera_common.h

typedef struct camera_module {
    /**
     * 摄像头模块的常用方法。 *必须*是 camera_module 的第一个成员
     */
    hw_module_t common;

    /**
     * 返回通过相机模块可访问的相机设备的数量。
     * 摄像机设备的编号从 0 到 N-1,其中 N 是这个调用返回的值。
     * open() 的相机设备名称只是转换成字符串的数字。
     */
    int (*get_number_of_cameras)(void);

    /**
     * 返回给定相机设备的静态相机信息。
     */
    int (*get_camera_info)(int camera_id, struct camera_info *info);

    /**
     * 提供指向 HAL 模块的回调函数指针,以通知框架异步相机模块事件。 
     */
    int (*set_callbacks)(const camera_module_callbacks_t *callbacks);

    /**
     * 获取查询供应商扩展元数据标签信息的方法。
     * HAL 应该填写所有供应商标签操作方法,
     * 或者如果未定义供应商标签,则保持 ops 不变。
     *
     * 这里使用的 vendor_tag_ops 结构定义在:
     * system/media/camera/include/system/vendor_tags.h
     */
    void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);

    /**
     * 如果此摄像机 HAL 模块支持多个设备 HAL API 版本,则打开特定的旧摄像机 HAL 设备。
     * 例如,如果相机模块同时支持 CAMERA_DEVICE_API_VERSION_1_0 和 CAMERA_DEVICE_API_VERSION_3_2 设备 API,
     * 则框架可以调用此函数以将相机设备作为 CAMERA_DEVICE_API_VERSION_1_0 设备打开。
     */
    int (*open_legacy)(const struct hw_module_t* module, const char* id,
            uint32_t halVersion, struct hw_device_t** device);

    /**
     * 打开或关闭与给定相机 ID 相关联的闪光灯的手电筒模式。
     * 如果操作成功,则 HAL 必须通过使用新状态调用 camera_module_callbacks.torch_mode_status_change() 来通知框架闪光灯状态。
     *
     */
    int (*set_torch_mode)(const char* camera_id, bool enabled);

    /**
     * 在成功调用相机 HAL 库之后,相机服务将在调用任何其他方法之前调用此方法。 
     * 如果不需要初始化,则 HAL 模块可以将其保留为 NULL。
     *
     */
    int (*init)();

    /* 留作将来使用 */
    void* reserved[5];
} camera_module_t;

加载相机 HAL 模块调用了标准方法 hw_get_module(…),入参是 CAMERA_HARDWARE_MODULE_ID,代表相机 HAL 模块 ID。这样就能获取到 hw_module_t 结构,由于 hw_module_t 是 camera_module_t 第一个成员,变相的我们就得到了 camera_module_t 结构。接着是初始化相机 HAL 模块的过程。首先将 camera_module_t 作为入参封装为 CameraModule,接着调用 CameraModule 类 init() 方法进行初始化。

为什么需要 CameraModule?从这个类的注释我们得到了答案。

CameraModule 是 HAL 相机模块的包装器类。此类包装从 HAL 返回的 camera_module_t,以提供包装的 get_camera_info 实现,CameraService 会生成一些在较旧的 HAL 上以较新的 HAL 版本定义的照相机特性的键。

CameraModule 类 init() 方法最终会调用 camera_module_t 结构中的 init() 方法进行初始化。

frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp

CameraModule::CameraModule(camera_module_t *module) {
    if (module == NULL) {
        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
        assert(0);
    }
    mModule = module;
}

int CameraModule::init() {
    ATRACE_CALL();
    int res = OK;
    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
            mModule->init != NULL) {
        ATRACE_BEGIN("camera_module->init");
        res = mModule->init();
        ATRACE_END();
    }
    mCameraInfoMap.setCapacity(getNumberOfCameras());
    return res;
}

获取摄像头个数,实际上也是调用 CameraModule 类 getNumberOfCameras() 方法。不出意外调用 HAL camera_module_t 结构体中的 get_number_of_cameras() 方法实现。

frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp

int CameraModule::getNumberOfCameras() {
    int numCameras;
    ATRACE_BEGIN("camera_module->get_number_of_cameras");
    numCameras = mModule->get_number_of_cameras();
    ATRACE_END();
    return numCameras;
}

再来看查找闪光灯的实现。主要是调用 CameraFlashlight 类 findFlashUnits() 查找闪光灯。 CameraFlashlight 类的主要作用是给相机服务提供控制闪光灯的一个接口。

获取相机个数
创建 ModuleFlashControl 对象
调用 ModuleFlashControl 类 hasFlashUnit(…) 方法检查闪光灯组件是否存在
将 Camera 对应的闪光灯组件是否存在一起添加到 HasFlashlightMap 中

frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp

CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
        const camera_module_callbacks_t& callbacks) :
        mCameraModule(&cameraModule),
        mCallbacks(&callbacks),
        mFlashlightMapInitialized(false) {
}

status_t CameraFlashlight::findFlashUnits() {
    Mutex::Autolock l(mLock);
    status_t res;
    // 1.获取相机个数
    int32_t numCameras = mCameraModule->getNumberOfCameras();

    mHasFlashlightMap.clear();
    mFlashlightMapInitialized = false;

    for (int32_t i = 0; i < numCameras; i++) {
        bool hasFlash = false;
        String8 id = String8::format("%d", i);
        // 2.创建 ModuleFlashControl 对象
        res = createFlashlightControl(id);
        if (res) {
            ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
                    id.string());
        } else {
            res = mFlashControl->hasFlashUnit(id, &hasFlash);
            if (res == -EUSERS || res == -EBUSY) {
                ALOGE("%s: failed to check if camera %s has a flash unit. Some "
                        "camera devices may be opened", __FUNCTION__,
                        id.string());
                return res;
            } else if (res) {
                ALOGE("%s: failed to check if camera %s has a flash unit. %s"
                        " (%d)", __FUNCTION__, id.string(), strerror(-res),
                        res);
            }

            mFlashControl.clear();
        }
        // 3.添加到 HasFlashlightMap 中
        mHasFlashlightMap.add(id, hasFlash);
    }

    mFlashlightMapInitialized = true;
    return OK;
}

createFlashlightControl(…) 方法中主要创建了 ModuleFlashControl 对象。

frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp

status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
    ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
            cameraId.string());
    if (mFlashControl != NULL) {
        return INVALID_OPERATION;
    }

    status_t res = OK;

    if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
        mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
        if (mFlashControl == NULL) {
            ALOGV("%s: cannot create flash control for module api v2.4+",
                     __FUNCTION__);
            return NO_MEMORY;
        }
    } else {
        ......
    }

    return OK;
}

获取 camera_info
从 CameraMetadata 中查找是否存在闪光灯组件

frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp

status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
    if (!hasFlash) {
        return BAD_VALUE;
    }

    *hasFlash = false;
    Mutex::Autolock l(mLock);

    camera_info info;
    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
            &info);
    if (res != 0) {
        return res;
    }

    CameraMetadata metadata;
    metadata = info.static_camera_characteristics;
    camera_metadata_entry flashAvailable =
            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
        *hasFlash = true;
    }

    return OK;
}

现在是时候分析获取相机信息了,实际为填充 camera_info 结构。主要调用了 HAL camera_module_t 结构体中的 get_camera_info(…) 方法实现。

frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp

int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
    ATRACE_CALL();
    Mutex::Autolock lock(mCameraInfoLock);
    if (cameraId < 0) {
        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
        return -EINVAL;
    }

    // 仅为 API2 设备覆盖 static_camera_characteristics
    int apiVersion = mModule->common.module_api_version;
    if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
        int ret;
        ATRACE_BEGIN("camera_module->get_camera_info");
        ret = mModule->get_camera_info(cameraId, info);
        ATRACE_END();
        return ret;
    }

    ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
    if (index == NAME_NOT_FOUND) {
        // 从 raw 模块获取相机信息并缓存它
        camera_info rawInfo, cameraInfo;
        ATRACE_BEGIN("camera_module->get_camera_info");
        int ret = mModule->get_camera_info(cameraId, &rawInfo);
        ATRACE_END();
        if (ret != 0) {
            return ret;
        }
        int deviceVersion = rawInfo.device_version;
        if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
            // static_camera_characteristics is invalid
            *info = rawInfo;
            return ret;
        }
        CameraMetadata m;
        m = rawInfo.static_camera_characteristics;
        deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
        cameraInfo = rawInfo;
        cameraInfo.static_camera_characteristics = m.release();
        index = mCameraInfoMap.add(cameraId, cameraInfo);
    }

    assert(index != NAME_NOT_FOUND);
    // return the cached camera info
    *info = mCameraInfoMap[index];
    return OK;
}

最后来分析一下 将 CameraService 注册到 CameraDeviceFactory 和 ping CameraServiceProxy。CameraService 注册到 CameraDeviceFactory 中仅仅是做了一个赋值动作。

frameworks/av/services/camera/libcameraservice/CameraDeviceFactory.cpp

namespace android {

wp<CameraService> CameraDeviceFactory::sService;
......
void CameraDeviceFactory::registerService(wp<CameraService> service) {
    ALOGV("%s: Registered service %p", __FUNCTION__,
          service.promote().get());

    sService = service;
}

}; // namespace android

最后来看 ping CameraServiceProxy 干了什么?

调用 getCameraServiceProxy() 获取 ICameraServiceProxy 代理对象
调用 ICameraServiceProxy.Stub.Proxy 类 pingForUserUpdate() 方法,实际由远端 CameraService Java 类中的成员 mCameraServiceProxy 中的 pingForUserUpdate() 方法实现

frameworks/av/services/camera/libcameraservice/CameraService.cpp

sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.camera.proxy"));
    if (binder == nullptr) {
        return nullptr;
    }
    sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder);
    return proxyBinder;
}

void CameraService::pingCameraServiceProxy() {
    sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
    if (proxyBinder == nullptr) return;
    proxyBinder->pingForUserUpdate();
}

pingForUserUpdate() 内部又调用了 CameraService 类 notifySwitchWithRetries(…) 方法。主要是为了完成将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。

frameworks/base/services/core/java/com/android/server/camera/CameraService.java

public class CameraService extends SystemService {
    ......
    private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
        @Override
        public void pingForUserUpdate() {
            notifySwitchWithRetries(30);
        }
        ......
    };
    ......
    private void notifySwitchWithRetries(int retries) {
        synchronized(mLock) {
            if (mEnabledCameraUsers == null) {
                return;
            }
            // 将用户切换事件转发到在 mediaserver 进程中运行的本地相机服务。
            if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
                retries = 0;
            }
        }
        if (retries <= 0) {
            return;
        }
        Slog.i(TAG, "Could not notify camera service of user switch, retrying...");
        // 无法通知相机服务的用户切换,30ms 后重试...
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null),
                RETRY_DELAY_TIME);
    }
    ......
}

handleMessage(…) 方法中再次调用 notifySwitchWithRetries(…) 进行了重试。

frameworks/base/services/core/java/com/android/server/camera/CameraService.java

public class CameraService extends SystemService {
    ......
    @Override
    public boolean handleMessage(Message msg) {
        switch(msg.what) {
            case MSG_SWITCH_USER: {
                notifySwitchWithRetries(msg.arg1);
            } break;
            default: {
                Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
            } break;
        }
        return true;
    }
    ......
}

后面继续分析 Camera HAL 中如何实现 camera_module_t 结构体中的函数指针。
QCamera2Hal.cpp 中给 hw_module_t 结构体 camera_common 进行了赋值,然后又给 camera_module_t 结构体 HAL_MODULE_INFO_SYM 赋值,HAL_MODULE_INFO_SYM 名字是固定的,这样 hw_get_module(…) 函数才能正常工作。

hardware/qcom/camera/QCamera2/QCamera2Hal.cpp

#include "QCamera2Factory.h"
#include "HAL3/QCamera3VendorTags.h"

static hw_module_t camera_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: "QCamera Module",
    author: "Qualcomm Innovation Center Inc",
    methods: &qcamera::QCamera2Factory::mModuleMethods,
    dso: NULL,
    reserved:  {0},
};

camera_module_t HAL_MODULE_INFO_SYM = {
    common: camera_common,
    get_number_of_cameras: qcamera::QCamera2Factory::get_number_of_cameras,
    get_camera_info: qcamera::QCamera2Factory::get_camera_info,
    set_callbacks: qcamera::QCamera2Factory::set_callbacks,
    get_vendor_tag_ops: qcamera::QCamera3VendorTags::get_vendor_tag_ops,
    open_legacy: qcamera::QCamera2Factory::open_legacy,
    set_torch_mode: qcamera::QCamera2Factory::set_torch_mode,
    init: NULL,
    reserved: {0}
};

get_number_of_cameras 函数指针具体指向了 qcamera::QCamera2Factory::get_number_of_cameras。

如果 gQCamera2Factory 为空,则先 new 一个对象出来,然后调用其 getNumberOfCameras() 方法。

hardware/qcom/camera/QCamera2/QCamera2Factory.cpp

namespace qcamera {
......
int QCamera2Factory::get_number_of_cameras()
{
    if (!gQCamera2Factory) {
        gQCamera2Factory = new QCamera2Factory();
        if (!gQCamera2Factory) {
            ALOGE("%s: Failed to allocate Camera2Factory object", __func__);
            return 0;
        }
    }
    return gQCamera2Factory->getNumberOfCameras();
}
......
}

先来分析 new 一个对象做了哪些工作?

获取 camera 个数
分配 HAL 描述符表
获取每个 camera camera_info

hardware/qcom/camera/QCamera2/QCamera2Factory.cpp

namespace qcamera {
......
QCamera2Factory::QCamera2Factory()
{
    camera_info info;
    int i = 0;
    mHalDescriptors = NULL;
    mCallbacks = NULL;
    // 获取 camera 个数
    mNumOfCameras = get_num_of_cameras();
    char prop[PROPERTY_VALUE_MAX];
    property_get("persist.camera.HAL3.enabled", prop, "0");
    int isHAL3Enabled = atoi(prop);

    if ((mNumOfCameras > 0) && (mNumOfCameras <= MM_CAMERA_MAX_NUM_SENSORS)) {
        // 分配 HAL 描述符表
        mHalDescriptors = new hal_desc[mNumOfCameras];
        if ( NULL != mHalDescriptors) {
            uint32_t cameraId = 0;

            for (; i < mNumOfCameras ; i++, cameraId++) {
                mHalDescriptors[i].cameraId = cameraId;
                if (isHAL3Enabled) {
                    mHalDescriptors[i].device_version = CAMERA_DEVICE_API_VERSION_3_0;
                } else {
                    mHalDescriptors[i].device_version = CAMERA_DEVICE_API_VERSION_1_0;
                }
                //在此时查询 camera,以避免在随后调用 'getCameraInfo()' 时出现任何延迟
                getCameraInfo(i, &info);
            }
        } else {
            ALOGE("%s: Not enough resources to allocate HAL descriptor table!",
                  __func__);
        }
    } else {
        ALOGE("%s: %d camera devices detected!", __func__, mNumOfCameras);
    }
}
......
}

打开设备节点 /dev/media ~ /dev/mediaN
向 camera 驱动发送命令 MEDIA_IOC_DEVICE_INFO,获取 media_device_info
向 camera 驱动发送命令 MEDIA_IOC_ENUM_ENTITIES,获取 media_entity_desc
打开 sensor_init subdev

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c

uint8_t get_num_of_cameras()
{
    int rc = 0;
    int dev_fd = 0;
    struct media_device_info mdev_info;
    int num_media_devices = 0;
    uint8_t num_cameras = 0;
    char subdev_name[32];
    int32_t sd_fd = 0;
    struct sensor_init_cfg_data cfg;
    char prop[PROPERTY_VALUE_MAX];

    property_get("persist.camera.logs", prop, "0");
    gMmCameraIntfLogLevel = atoi(prop);

    CDBG("%s : E", __func__);

    int decrypt = property_get("vold.decrypt", prop, NULL);
    if (0 < decrypt) {
        if(strncmp(prop, "trigger_restart_min_framework", decrypt) == 0) {
            return 0;
        }
    }

    /* lock the mutex */
    pthread_mutex_lock(&g_intf_lock);

    while (1) {
        int32_t num_entities = 1;
        char dev_name[32];
        // 打开设备节点 /dev/media ~ /dev/mediaN
        snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
        dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
        if (dev_fd < 0) {
            CDBG("Done discovering media devices\n");
            break;
        }
        num_media_devices++;
        // 向 camera 驱动发送命令 MEDIA_IOC_DEVICE_INFO,获取 media_device_info
        rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
        if (rc < 0) {
            CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
            close(dev_fd);
            dev_fd = -1;
            break;
        }

        if (strncmp(mdev_info.model, MSM_CONFIGURATION_NAME,
          sizeof(mdev_info.model)) != 0) {
            close(dev_fd);
            dev_fd = -1;
            continue;
        }

        while (1) {
            struct media_entity_desc entity;
            memset(&entity, 0, sizeof(entity));
            entity.id = num_entities++;
            CDBG_ERROR("entity id %d", entity.id);
            // 向 camera 驱动发送命令 MEDIA_IOC_ENUM_ENTITIES,获取 media_entity_desc
            rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
            if (rc < 0) {
                CDBG_ERROR("Done enumerating media entities");
                rc = 0;
                break;
            }
            CDBG_ERROR("entity name %s type %d group id %d",
                entity.name, entity.type, entity.group_id);
            if (entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&
                entity.group_id == MSM_CAMERA_SUBDEV_SENSOR_INIT) {
                snprintf(subdev_name, sizeof(dev_name), "/dev/%s", entity.name);
                break;
            }
        }
        close(dev_fd);
        dev_fd = -1;
    }

    /* 打开 sensor_init subdev */
    sd_fd = open(subdev_name, O_RDWR);
    if (sd_fd < 0) {
        CDBG_ERROR("Open sensor_init subdev failed");
        return FALSE;
    }

    cfg.cfgtype = CFG_SINIT_PROBE_WAIT_DONE;
    cfg.cfg.setting = NULL;
    if (ioctl(sd_fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg) < 0) {
        CDBG_ERROR("failed");
    }
    close(sd_fd);
    dev_fd = -1;
    ......
    g_cam_ctrl.num_cam = num_cameras;

    get_sensor_info();
    /* unlock the mutex */
    pthread_mutex_unlock(&g_intf_lock);
    CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
    return g_cam_ctrl.num_cam;
}

mm_camera_interface.c–>get_sensor_info()

get_sensor_info() 中获取了 camera 的 facing(前置或后置) 和 orientation。

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c

// 获取面向(后/前)和安装角度的传感器信息
void get_sensor_info()
{
    ......
    while (1) {
        ......
        while (1) {
            struct media_entity_desc entity;
            unsigned long temp;
            unsigned int mount_angle;
            unsigned int facing;

            memset(&entity, 0, sizeof(entity));
            entity.id = num_entities++;
            rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
            if (rc < 0) {
                CDBG("Done enumerating media entities\n");
                rc = 0;
                break;
            }
            if(entity.type == MEDIA_ENT_T_V4L2_SUBDEV &&
                entity.group_id == MSM_CAMERA_SUBDEV_SENSOR) {
                temp = entity.flags >> 8;
                mount_angle = (temp & 0xFF) * 90;
                facing = (temp >> 8);
                ALOGD("index = %d flag = %x mount_angle = %d facing = %d\n"
                    , num_cameras, (unsigned int)temp, (unsigned int)mount_angle,
                    (unsigned int)facing);
                g_cam_ctrl.info[num_cameras].facing = facing;
                g_cam_ctrl.info[num_cameras].orientation = mount_angle;
                num_cameras++;
                continue;
            }
        }

        CDBG("%s: dev_info[id=%d,name='%s']\n",
            __func__, num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);

        close(dev_fd);
        dev_fd = -1;
    }

    CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
    return;
}

QCamera2Factory.cpp–>getNumberOfCameras()

hardware/qcom/camera/QCamera2/QCamera2Factory.cpp
QCamera2Factory 类的 getNumberOfCameras() 方法只是简单的将 QCamera2Factory 构造器中赋值的 mNumOfCameras 成员变量返回。

// 查询检测到的摄像机数量
int QCamera2Factory::getNumberOfCameras()
{
    return mNumOfCameras;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值