Android 源码 Camera2 CameraService 启动

828 阅读8分钟

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

system/core/rootdir/init.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

经过分析可知,mediaserver 执行程序位于 main_mediaserver.cpp 中。调用 CameraService 类 instantiate() 启动了相机服务。
在这里插入图片描述

frameworks/av/media/mediaserver/main_mediaserver.cpp

using namespace android;

int main(int argc __unused, char** argv)
{
    signal(SIGPIPE, SIG_IGN);
    char value[PROPERTY_VALUE_MAX];
    bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
    pid_t childPid;
    
    if (doLog && (childPid = fork()) != 0) {
        ......
    } else {
        // all other services
        ......
        CameraService::instantiate();
        ......
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    }
}

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

frameworks/av/media/mediaserver/Android.mk

LOCAL_PATH:= $(call my-dir)
......
LOCAL_SRC_FILES:= \
	main_mediaserver.cpp
......
LOCAL_MODULE:= mediaserver
LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)

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

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

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");

    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 类的主要作用是给相机服务提供控制闪光灯的一个接口。

  1. 获取相机个数
  2. 创建 ModuleFlashControl 对象
  3. 调用 ModuleFlashControl 类 hasFlashUnit(…) 方法检查闪光灯组件是否存在
  4. 将 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;
}
  1. 获取 camera_info
  2. 从 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 干了什么?

  1. 调用 getCameraServiceProxy() 获取 ICameraServiceProxy 代理对象
  2. 调用 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 结构体中的函数指针。我们以 moto Nexus 6 device/moto/shamu/camera/QCamera2/ 为例进行分析。