记录一次获取车载摄像头数量为0同时打开摄像头黑屏的问题分析(基于Android M)

在一次实车测试车载倒车过程中,出现了倒车打开车载摄像头黑屏的现象。分析收集的log,发现初始化Camera前会获取摄像头数量来确定车载摄像头是否连接,当获取的摄像头数量大于0时则认为接入了摄像头。于是跟踪Camera的源码,追查原因。
首先从app层的代码入手,获取的摄像头的代码如下:

private static final int CAMERA_TYPE_BACKWARD_COMPATIBLE = 0;
private static final int CAMERA_TYPE_ALL = 1;

private ICameraService mCameraService

public int cameraServiceDetect() {
        int numCameras = false;
        int numCameras;
        synchronized(this.mLock) {
            this.mCameraService = Stub.asInterface(ServiceManager.getService("media.camera"));
            if (this.mCameraService == null) {
                return 0;
            }

            try {
                numCameras = this.mCameraService.getNumberOfCameras(CAMERA_TYPE_ALL);
            } catch (RemoteException var5) {
                Log.e("CameraServiceDetector", "[cameraServiceDetect] unexpected RemoteException happened");
                numCameras = 0;
            }
        }

        if (numCameras > 0) {
        }

        return numCameras;
    }

其中ICameraService为framwork中AIDL接口,通过AIDL与框架层的CameraService绑定。
CameraService源码如下:
源码路径:frameworks/av/services/camera/libcameraservice/CameraService.cpp
源码:

//frameworks/av/services/camera/libcameraservice/CameraService.cpp
int32_t CameraService::getNumberOfCameras(int type) {
    ATRACE_CALL();
    switch (type) {
        case CAMERA_TYPE_BACKWARD_COMPATIBLE:
            return mNumberOfNormalCameras;
        case CAMERA_TYPE_ALL:
            return mNumberOfCameras;
        default:
            ALOGW("%s: Unknown camera type %d, returning 0",
                    __FUNCTION__, type);
            return 0;
    }
}

其中CAMERA_TYPE_BACKWARD_COMPATIBLE和CAMERA_TYPE_ALL常量定义在
frameworks/av/include/camera/ICameraService.h路径下。

    //frameworks/av/include/camera/ICameraService.h
    enum {
        CAMERA_TYPE_BACKWARD_COMPATIBLE = 0,
        CAMERA_TYPE_ALL = 1,
    };

CameraService同AMS(AcitivityManagerService)类似,在系统服务main_mediaserver(源码路径:frameworks/av/media/mediaserver/main_mediaserver.cpp)中初始化。

//frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char** argv)
{
		...此处省略代码
		//相机服务开始初始化并注册
        CameraService::instantiate();
        ...
}

CameraModule的初始化过程过程中绑定了HAL层的CameraModule。

//CameraService.cpp
void CameraService::onFirstRef()
{
    ...此处省略代码
     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;
    }

    mModule = new CameraModule(rawModule);
    err = mModule->init();
    ...
    mNumberOfCameras = mModule->getNumberOfCameras();
    mNumberOfNormalCameras = mNumberOfCameras;
    ...
}

其中mModule为camera_module_t类型的参数,定义在hal层定义,路径为hardware/libhardware/include/hardware/camera_common.h

//hardware/libhardware/include/hardware/camera_common.h
typedef struct camera_module {
    ...此处省略代码
    hw_module_t common;

    /**
     * get_number_of_cameras:
     *
     * Returns the number of camera devices accessible through the camera
     * module.  The camera devices are numbered 0 through N-1, where N is the
     * value returned by this call. The name of the camera device for open() is
     * simply the number converted to a string. That is, "0" for camera ID 0,
     * "1" for camera ID 1.
     *
     * Version information (based on camera_module_t.common.module_api_version):
     *
     * CAMERA_MODULE_API_VERSION_2_3 or lower:
     *
     *   The value here must be static, and cannot change after the first call
     *   to this method.
     *
     * CAMERA_MODULE_API_VERSION_2_4 or higher:
     *
     *   The value here must be static, and must count only built-in cameras,
     *   which have CAMERA_FACING_BACK or CAMERA_FACING_FRONT camera facing values
     *   (camera_info.facing). The HAL must not include the external cameras
     *   (camera_info.facing == CAMERA_FACING_EXTERNAL) into the return value
     *   of this call. Frameworks will use camera_device_status_change callback
     *   to manage number of external cameras.
     */
    int (*get_number_of_cameras)(void);
    ...此处省略代码
} camera_module_t;

前面从framework调用到了hal层。CameraHAL 相当于一个CameraModule,在framework层调到此处。

static int get_number_of_cameras()
{
    return gCameraHAL.getNumberOfCameras();
}

hal层会通过ioctl去访问硬件驱动,同时检测Camera的Sensor Id是否有效,有效数目便是支返回的camera个数。具体细节不做过多描述。
后面驱动确定了摄像头未能正确识别导致获取不到正确的摄像头数量,摄像头不能识别的问题在实车确认了摄像头的更换导致制式错误,重新标定摄像头后即可正确识别,获取的数量大于0了,打开摄像头也能正常显示。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

言并肃

感谢大哥支持!您的鼓励是我动力

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

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

打赏作者

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

抵扣说明:

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

余额充值