系统:MTK Android4.4 日期:2015年10月10日 stamp&data setParameters Utils::Property::tryGet
一. 前述
之前对MTK的Camera的源码流程有过初步的了解,现在对以前了解的东西做一些梳理总结,但也仅是对源码流程一个贯穿,并不会对其进行深入分析,方便日后工作需求做一个铺垫。
此文分析的是Camera系统源码,即Frameworks层之后的,并不是APK的源码分析。
二. 分析思路
1. 先从Camera的初始化开始,以cameraID为线索,简单地从Frameworks开始贯穿到底层。主要任务Camera如何被打开的,完成源码的贯穿。 2. 然后再从startPreview开始去了解,Camera被打开之后,取出的数据流是什么,数据流经过了怎么的处理,然后又是怎么被送出到APK,显示出来的
三. 上层入口 针对于上面的两个分析点,从APK上层入口开始:
private Camera mCamera;
mCamera = Camera.open(cameraID);
mCamera.startPreview();
四. Camera 初始化化 Open
(1) 文件列表: Camera.java: frameworks/base/core/java/android/hardware android_hardware_Camera.cpp: frameworks/base/core/jni Camera.cpp:
frameworks/av/camera
CameraBase.cpp:
frameworks/av/camera
CameraService.cpp: frameworks/av/services/camera/libcameraservice
module.h: frameworks/hardware/mtkcam/module CamDeviceManagerBase.cpp mediatek/hardward/mtkcam/devicemgr CameraClient.cpp frameworks/av/services/camera/libcameraservice/api1
CameraHardwareInterface.h: frameworks/av/services/camera/libcameraservice/device
(2) Frameworks层 第一个被调用的是Camera.java文件里的open函数。然后调用的是Camera(int cameraId)的
native_setup(new WeakReference<Camera>(this), cameraId, packageName);
上面的函数对应的是
android_hardware_Camera.cpp里的android_hardware_Camera_native_setup()函数
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jstring clientPackageName)
{
//打开Camera,把回一个Camera设备
sp<Camera> camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);
}
我们开始从Camera::connect开始深入,connect函数在Camera.cpp:
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, int clientUid){
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
这里调用了CameraBaseT的connect CameraBaseT是CameraBase的类成员,
CameraBase是一个模板类,其定义如下:
template <typename TCam>
struct CameraTraits {
};
template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
class CameraBase : public IBinder::DeathRecipient
{
public:
typedef typename TCamTraits::TCamListener TCamListener;
typedef typename TCamTraits::TCamUser TCamUser;
typedef typename TCamTraits::TCamCallbacks TCamCallbacks;
typedef typename TCamTraits::TCamConnectService TCamConnectService;
static sp<TCam> connect(int cameraId, const String16& clientPackageName, int clientUid);
//...
protected:
CameraBase(int cameraId);
//...
typedef CameraBase<TCam> CameraBaseT;
};
}; // namespace android
Camera.cpp里的Camera类继承于CameraBase,同时初始化了CameraBase的模板
class Camera : public CameraBase<Camera>, public BnCameraClient
在Camera.h里也初始化了CameraTraits这个模板类:
template <>
struct CameraTraits<Camera>
{
typedef CameraListener TCamListener;
typedef ICamera TCamUser;
typedef ICameraClient TCamCallbacks;
typedef status_t (ICameraService::*TCamConnectService)(const sp<ICameraClient>&, int, const String16&, int,
/*out*/
sp<ICamera>&);
static TCamConnectService fnConnectService;
};
CameraBase这个模板中的TCamConnectService成员的类型为TCamTraits::TCamConnectService,
所以在这里被定义成一个
TCamConnectService类型的函数指针,其余的CameraBase成员依此类推。
我们继续回到connect函数里。Camera.cpp里调用了模板类里的connect函数,这个函数的实现在CameraBase.cpp里
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, const String16& clientPackageName, int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
//把所有的TCam替换成Camera,构造了一个Camera对象。这个构造函数只有初始化mCameraId的值
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
//获取ICameraService
const sp<ICameraService>& cs = getCameraService();
//fnConnectService在Camera.cpp里被定义为&ICameraService::connect
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
//调用CameraService里的connect函数
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera);
return c;
}
CameraService .cpp的CameraService::connect
status_t CameraService::connect(const sp<ICameraClient>& cameraClient, int cameraId,
const String16& clientPackageName, int clientUid, /*out*/ sp<ICamera>& device) {
int facing = -1;
//获得hardware层的版本是CAMERA_DEVICE_API_VERSION_1_0
int deviceVersion = getDeviceVersion(cameraId, &facing);
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
//CameraClient也在hardware层里定义了
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
//...
}
status_t status = connectFinishUnsafe(client, client->getRemote());
mClient[cameraId] = client;
// important: release the mutex here so the client can call back
// into the service from its destructor (can be at the end of the call)
device = client;
return OK;
}
//getDeviceVersion
int CameraService::getDeviceVersion(int cameraId, int* facing) {
struct camera_info info;
mModule->get_camera_info(cameraId, &info);
int deviceVersion;
if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = info.device_version;
} else {
//从hardware层的hw_module_t mModule里获得版本号
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
}
return deviceVersion;
}
//mModule的初始化在onFirstRef函数里
void CameraService::onFirstRef()
{
hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&mModule);
//......
}
CameraService里的onFirstRef函数通过CAMERA_HARDWARE_MODULE_ID获取了一个hw_module_t模块。这个模块是与hardware层对接的接口。这个模块在module.h里定义 再CameraService的getDeviceVersion()函数: 先是调用了mModule->get_camera_info(cameraId, &info),这里
get_camera_info()函数就是Modle.h里的
get_camera_info()函数。
static int get_camera_info(int cameraId, camera_info* info){
//CamDeviceManager继承于CamDeviceManagerBase
//这里相当于直接调用CamDeviceManagerBase的getDeviceInfo函数
return NSCam::getCamDeviceManager()->getDeviceInfo(cameraId, *info);
}
//CamDeviceManagerBase.cpp
CamDeviceManagerBase::
getDeviceInfo(int const deviceId, camera_info& rInfo){
//CameraService的getDeviceVersion()所需要的版本号
//mEumMap 在CamDeviceManagerImp.cpp 的 enumDeviceLocked() 函数里初始化
rInfo.device_version= mEnumMap.valueFor(deviceId)->uDeviceVersion;
rInfo.facing = mEnumMap.valueFor(deviceId)->iFacing;
rInfo.orientation = mEnumMap.valueFor(deviceId)->iWantedOrientation;
rInfo.static_camera_characteristics = mEnumMap.valueFor(deviceId)->pMetadata;
}
//CamDeviceManagerImp.cpp enumDeviceLocked()
enumDeviceLocked()
{
//增加ImageSensor的Sensor信息,后面会被get
DevMetaInfo::add(deviceId, camInfo, i4DevSetupOrientation, eDevId_ImgSensor, eHalSensorDev);
sp<EnumInfo> pInfo = new EnumInfo;
pInfo->uDeviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
pInfo->pMetadata = NULL;
pInfo->iFacing = camInfo.facing;
pInfo->iWantedOrientation = camInfo.orientation;
pInfo->iSetupOrientation = i4DevSetupOrientation;
mEnumMap.add(deviceId, pInfo);
i4DeviceNum++;
//...
}
connect最重要的是构造了CameraClient,这个
CameraClient又是什么,有什么用的呢?
先来看看CameraClient的构造函数,在CameraClient.cpp里,似乎没有什么重要动作
CameraClient::CameraClient(const sp<CameraService>& cameraService,
Client(cameraService, cameraClient, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
// Callback is disabled by default
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
//摄像头方向
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
//拍照声音
mPlayShutterSound = true;
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
connect里构造了
CameraClient后调用了connectFinishUnsafe()函数,这个函数里调用了
CameraClient的initialize函数
status_t CameraClient::initialize(camera_module_t *module) {
// Verify ops permissions
res = startCameraOps();
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
//在CameraHardwareInterface.cpp
mHardware = new CameraHardwareInterface(camera_device_name);
//打开hardware mModule
res = mHardware->initialize(&module->common);
mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId);
// Enable zoom, error, focus, and metadata messages by default
enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
// Enable MTK-extended messages by default
enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA);
}
CameraHardwareInterface.cpp initialize()函数
initialize()之后获得了Hardware对接的设备接口mDevice,上层的Frameworks正是通过
CameraHardwareInterface类,对Hardware层进行操作,然后Hardware层对硬件进行进一步的操作。
CameraHardwareInterface是上下层对接的接口。
status_t initialize(hw_module_t *module){
//调用了module.h open_device()
module->methods->open(module, mName.string(), (hw_device_t **)&mDevice);
//初始化预览窗口
initHalPreviewWindow();
}
(3) Hardware层
文件列表:
CamDeviceManagerBase.cpp mediatek/hardward/mtkcam/devicemgr
Cam1DeviceFactory.cpp mediatek/hardware/mtkcam/v1/device
DefaultCam1Device.cpp mediatek/mt8127/hardware/mtkcam/v1/device
Cam1DeviceBase.cpp mediatek/hardware/mtkcam/v1/device
Cam1Device.cpp mediatek/hardware/mtkcam/v1/device
Sensor_hal.cpp mediatek/platform/mt8127/hardware/mtkcam/core/drv/imgsensor
imgsensor_drv.cpp mediatek/platform/mt8127/hardware/mtkcam/core/drv/imgsensor
Camclient.cpp
mediatek
/hardware/mtkcam/v1/client/camclient PreviewClient.cpp
mediatek
/hardware/mtkcam/v1/client/camclient/previewcallback ImgBufQueue.cpp mediatek/hardware/mtkcam/v1/common/camutils
MtkDefaultCamAdapter.cpp mediatek/platform/mt8127/hardware/mtkcam/v1/hal/adapter/mtkdefault
BaseCamAdapter.cpp mediatek/platform/mt8127/hardware/mtkcam/v1/hal/adapter/ State.cpp mediatek/platform/mt8127/hardware/mtkcam/v1/hal/adapter/mtkdefault/state PreviewCmdQueThread.cpp
mediatek/platform/mt8127/hardware/mtkcam/v1/hal/adapter/mtkdefault/preview
PreviewBufMgr.cpp mediatek/platform/mt8127/hardware/mtkcam/v1/hal/adapter/mtkdefault/preview
CameraHardwareInterface.cpp initialize()调用了Module.h 的open_device()函数
open_device(hw_module_t const* module, const char* name, hw_device_t** device)
{
return NSCam::getCamDeviceManager()->open(module, name, device);
}
CamDeviceManagerImp 继承于 CamDeviceManagerBase。直接调用了CamDeviceManagerBase的open(),open()函数又只是调用了
CamDeviceManagerBase:: openDeviceLocked()。此函数在同文件夹下的
CamDeviceManagerBase.openDevice.cpp文件里。
在这里有点不明白,这个函数会获取一个属性值,这个值是从哪里来的,这个似乎要从开机流程里找了。先Mark一下,有空再看一下开机流程
CamDeviceManagerBase::
openDeviceLocked( hw_module_t const* module, char const* name, hw_device_t** device)
{
//获得AppMode,这个属性在哪里被初始化的呢?我们这里的s8ClientAppMode = APP_MODE_NAME_DEFAULT
String8 const s8ClientAppMode = queryClientAppMode();
//这个我们在之前已经看到了在哪里初始化,结果为CAMERA_DEVICE_API_VERSION_1_0
uint32_t const version = determineOpenDeviceVersionLocked(s8ClientAppMode, i4OpenId);
if ( version == CAMERA_DEVICE_API_VERSION_1_0 )
{ //获得Camera设备,并打开硬件和初始化。这里的设备并不是指硬件设备
//而是包含硬件设备,设备参数,设备操作(预览等)。的一个操作类
pDevice = pPlatform->createCam1Device(s8ClientAppMode.string(), i4OpenId);
}
}
上面的createCam1Device函数在Cam1DeviceFactory.cpp
NSCam::Cam1Device*
createCam1Device(String8 const s8ClientAppMode, int32_t const i4OpenId)
{
// if ( s8ClientAppMode == MtkCameraParameters::APP_MODE_NAME_DEFAULT )
{
String8 const s8CamDeviceInstFactory = String8::format("createCam1Device_Default");
void* pCreateInstance = ::dlsym(RTLD_DEFAULT, s8CamDeviceInstFactory.string());
MY_LOGF_IF(0==pCreateInstance, "Not exist: %s for %s", s8CamDeviceInstFactory.string(), s8ClientAppMode.string());
//这里相当于调用 createCam1Device_Default()函数
pdev = reinterpret_cast<NSCam::Cam1Device* (*)(String8 const&, int32_t const)>
(pCreateInstance)(s8ClientAppMode, i4OpenId);
}
if ( pdev )
{
//初始化硬件设备等
if ( OK != pdev->initialize() )
{
MY_LOGE("Cam1Device::initialize() device:%p", pdev);
// use ref. count to delete raw pointer.
pdev->incStrong(pdev);
pdev->decStrong(pdev);
pdev = NULL;
}
}
}
我们先来看看createCam1Device_Default()函数,再看看pdev->initialize()函数。
createCam1Device_Default()函数并没有干很多工作,只是调用了一些构造函数而已。更的工作在
pdev->initialize()。但
createCam1Device_Default()的构造顺序,可以帮助我们了解一下代码流程,但
createCam1Device_Default()的基础的父类Cam1Device每重要,这里列出了一些接口让上层调用,但是这些接口的实现,都是其子类里,这很里很之间的继承关系,让我晕了一阵子。等会看startPreview()的时候会再看到Cam1Device
createCam1Device_Default()在DefaultCam1Device.cpp里
NSCam::Cam1Device*
createCam1Device_Default( String8 const& rDevName, int32_t const i4OpenId)
{
return new DefaultCam1Device(rDevName, i4OpenId);
}
//DefaultCam1Device继承于Cam1DeviceBase
DefaultCam1Device::
DefaultCam1Device(String8 const& rDevName, int32_t const i4OpenId)
: Cam1DeviceBase(rDevName, i4OpenId)
{
}
//Cam1DeviceBase继承于Cam1Device
Cam1DeviceBase::
Cam1DeviceBase( String8 const& rDevName, int32_t const i4OpenId)
: Cam1Device()
{
}
我们把这个继承关系写下来:DefaultCam1Device继承Cam1DeviceBase继承于Cam1Device。这三个父子类之间的操作函数相互调用,让逻辑看起来特别头疼。后面我们需要找操作Camera操作,如startPreview()。就需要从子类开始一个一个地往上找
再来看看createCam1Device的pdev->initialize()。这里的
pdev是createCam1Device_Default返回来的指针,所以initialize()在
DefaultCam1Device类,或者在其父类里。沿着构造顺序一层层地住上找,在Cam1DeviceBase类里
Cam1DeviceBase::
initialize()
{
if ( ! onInit() )
{
return -ENODEV;
}
}
这里调用了onInit函数。
Cam1DeviceBase实现了onInit函数。如果接着往下看就会是一个深渊,因为其子类里也实现了onInit(),应该是调用了子类的onInit()函数。所以又要回到DefaultCam1Device的onInit()。这个函数非常重要,正是这里打开了硬件。终于接近了底层了~
DefaultCam1Device::onInit()
{
int const iHalSensorDevId = DevMetaInfo::queryHalSensorDev(getOpenId());
//Android的资源管理器
IResManager* pResManager = IResManager::getInstance();
if(!(pResManager->open("DefaultCam1Device"))){}
// (1) Open Sensor 下面的SensorHal包含了imageSensor和ISP
mpSensorHal = SensorHal::createInstance();
err = mpSensorHal->sendCommand((halSensorDev_e)iHalSensorDevId, SENSOR_CMD_SET_SENSOR_DEV);
err = mpSensorHal->init();
// (2) Open 3A
mp3AHal = NS3A::Hal3ABase::createInstance(iHalSensorDevId);
// (3) Init Base.
Cam1DeviceBase::onInit();
}
SensorHal在Sensor_hal.cpp,我们从SensorHal::createInstance();开始,此函数只是创建了ISP管理驱动,并没打开ImageSensor设备。ISP不是我们重点,先忽略
SensorHal* SensorHal::createInstance()
{
return SensorHalImp::getInstance();
}
SensorHal* SensorHalImp::getInstance()
{
static SensorHalImp singleton;
ret = singleton.createImp();
return &singleton;
}
MINT32 SensorHalImp::createImp()
{
mSensorDev = SENSOR_DEV_MAIN;
mIspSensorType[0] = SENSOR_TYPE_UNKNOWN;
mImageSensorType[0] = IMAGE_SENSOR_TYPE_UNKNOWN;
mIspSensorType[1] = SENSOR_TYPE_UNKNOWN;
mImageSensorType[1] = IMAGE_SENSOR_TYPE_UNKNOWN;
//创建ISP管理
pSeninfDrv = SeninfDrv::createInstance();
}
接下来是mpSensorHal->init();这里打开了两个设备,一个是ISP和ImageSensor
MINT32 SensorHalImp::init()
{
//这里直接调用的是ImgSensorDrv::getInstance()
//返回的是ImgSensorDrv(imgsensor_drv.cpp),也就是我们找的摄像头驱动管理
//构造函数只在做了简单的数据处理
pSensorDrv = SensorDrv::createInstance(mSensorDev);
//初始化ISP
ret = pSeninfDrv->init();
// Before searching sensor, need to turn on TG
ret = initSensor();
// Get sensor info before setting TG phase counter
ret = getSensorInfo(scenarioId);
ret = setTgPhase();
ret = setSensorIODrivingCurrent();
ret = initCSI2Peripheral(1); // if the interface is mipi, enable the csi2
ret = setCSI2Config(1); // enable and config CSI2.
#ifdef ATV_SUPPORT
#ifdef MTK_MATV_SERIAL_IF_SUPPORT
pSeninfDrv->initTg1Serial(MFALSE);
#endif
#endif
// Open sensor, try to open 3 time
for (int i =0; i < 3; i++)
ret = pSensorDrv->open();
}
MINT32 SensorHalImp::initSensor()
{
switch (mSensorDev)
{
case SENSOR_DEV_MAIN:
eSensorDev = SENSOR_MAIN;
if(!(mSearchSensorDev & SENSOR_DEV_MAIN)) {
LOG_ERR("initSensor fail,mSensorDev = 0x%x, mSearchSensorDev = 0x%x\n",mSensorDev,mSearchSensorDev);
return -1;
}
break;
case SENSOR_DEV_SUB:
//....
}
//imgsensor_drv.cpp ImgSensorDrv::init()函数
//在此打开底层的驱动文件,并获取一些信息
ret = pSensorDrv->init(mSensorDev);
// Get Sensor Resolution
pSensorResInfo[0] = &sensorResolution[0];
pSensorResInfo[1] = &sensorResolution[1];
ret = pSensorDrv->getResolution(pSensorResInfo);
if(eSensorDev == SENSOR_DEV_MAIN) {
if ( IMAGE_SENSOR_TYPE_RAW == pSensorDrv->getCurrentSensorType(eSensorDev) )
{
// Full Resolution
u4PaddedWidth = sensorResolution[0].SensorFullWidth + ISP_RAW_WIDTH_PADD;
u4PaddedHeight= sensorResolution[0].SensorFullHeight + ISP_RAW_HEIGHT_PADD;
if ( 0 != ((u4PaddedWidth * u4PaddedHeight) % 6) )
{
sensorResolution[0].SensorFullHeight -= (u4PaddedHeight % 6);
LOG_MSG(" Sensor resolution after fixing: Full: %d/%d\n", sensorResolution[0].SensorFullWidth, sensorResolution[0].SensorFullHeight);
}
}
}
if(eSensorDev == SENSOR_DEV_SUB) {
//...
}
}
MINT32 ImgSensorDrv::init(MINT32 sensorIdx)
{
//打开底层设备文件,至于是打开sensorlist哪个摄像头
//摄像头怎么匹配的就是靠CAMERA_HW_DEVNAME这个驱动了。
sprintf(cBuf,"/dev/%s",CAMERA_HW_DEVNAME);
m_fdSensor = ::open(cBuf, O_RDWR);
//set sensor driver
ret = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,sensorDrvInfo);
android_atomic_inc(&mUsers);
//init. resolution
pSensorResInfo[0] = &m_SenosrResInfo[0];
pSensorResInfo[1] = &m_SenosrResInfo[1];
ret = getResolution(pSensorResInfo);
}
基本上Camera从上到下的流程就是这样子了。基本上贯穿了我们整个Camera,目的已经达到,点到为止