在一次实车测试车载倒车过程中,出现了倒车打开车载摄像头黑屏的现象。分析收集的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了,打开摄像头也能正常显示。