1. 前言
本文将分析Android系统源码,从frameworks层到hal层,暂不涉及app层和kernel层。由于某些函数比较复杂,在贴出代码时会适当对其进行简化。本文属于自己对源码的总结,仅仅是贯穿代码流程,不会深入分析各个细节。欢迎联系讨论,QQ:1026656828
2. app层
从apk开始,简单列出各个入口函数
-
private void initCamera()
-
{
-
Camera mCamera = Camera.open();
-
Camera.Parameters mParameters = mCamera.getParameters();
-
mParameters.setPictureFormat(PixelFormat.JPEG);
-
mCamera.setParameters(mParameters);
-
mCamera.setPreviewDisplay(mSurfaceHolder);
-
mCamera.startPreview();
-
mCamera.takePicture(null, null , mJpegCallback);
-
}
3. frameworks层
这里将重点介绍Camera.open函数,其余函数将在后续博文分析。先来看看Camera.open函数在frameworks层的实现,代码路径为: frameworks/base/core/java/android/hardware/Camera.java
-
public static Camera open() {
-
if (!isPermissionGranted()) {
-
return null;
-
}
-
int numberOfCameras = getNumberOfCameras();
-
CameraInfo cameraInfo = new CameraInfo();
-
for (int i = 0; i < numberOfCameras; i++) {
-
getCameraInfo(i, cameraInfo);
-
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
-
return new Camera(i);
-
}
-
}
-
return null;
-
}
第5行, 通过getNumberOfCameras函数来获取Camera的个数。从上一篇博文CameraService的启动流程可以看出,这个信息保存在CameraService中。第10行,需重点关注,构造一个Camera对象,并将它返回给app层。
3.1 getNumberOfCameras函数分析
getNumberOfCameras函数进入到CameraService获取Camera个数的流程如下:

Camera.Java调用的getNumberOfCameras函数是一个JNI接口,对应的函数是android_hardware_Camera.cpp里的android_hardware_Camera_getNumberOfCameras函数
-
static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
-
{
-
return Camera::getNumberOfCameras();
-
}
这里只是简单调用了Camera.cpp的getNumberOfCameras函数,Camera继承了CameraBase,该函数由它实现
-
template <typename TCam, typename TCamTraits>
-
int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
-
const sp<ICameraService> cs = getCameraService();
-
return cs->getNumberOfCameras();
-
}
第3行, getCameraService函数用来获取ICameraService的Bp端,代码实现如下
-
const char* kCameraServiceName = "media.camera";
-
-
template <typename TCam, typename TCamTraits>
-
const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
-
{
-
if (gCameraService.get() == 0) {
-
sp<IServiceManager> sm = defaultServiceManager();
-
sp<IBinder> binder;
-
binder = sm->getService(String16(kCameraServiceName));
-
gCameraService = interface_cast<ICameraService>(binder);
-
}
-
return gCameraService;
-
}
android的Binder通讯机制
第1行, 获取的ServiceName为"media.camera",结合上一篇博文CameraService的启动流程可以看出Bn端的实现在CameraService.cpp
回到之前的getNumberOfCameras函数,在获取到ICameraService的Bp端后,就可以开始和Bn端通讯了。在第4行,当调用cs->getNumberOfCameras函数时,将会进入CameraService.cpp的getNumberOfCameras函数
-
int32_t CameraService::getNumberOfCameras() {
-
return mNumberOfCameras;
-
}
代码很简单,返回上一篇博文讲到的,千辛万苦从hal层拿到的数据
3.2 Camera构造函数分析
回到最开始的Camera.open函数,在第10行,将会构造一个Camera对象
-
private int cameraInitVersion(int cameraId, int halVersion) {
-
......
-
Looper looper;
-
if ((looper = Looper.myLooper()) != null) {
-
mEventHandler = new EventHandler(this, looper);
-
} else if ((looper = Looper.getMainLooper()) != null) {
-
mEventHandler = new EventHandler(this, looper);
-
} else {
-
mEventHandler = null;
-
}
-
-
String packageName = ActivityThread.currentPackageName();
-
-
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
-
}
-
-
private int cameraInitNormal(int cameraId) {
-
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
-
}
-
-
Camera(int cameraId) {
-
int err = cameraInitNormal(cameraId);
-
......
-
}
第14行, native_setup同样是个JNI接口,对应android_hardware_Camera.cpp里的android_hardware_Camera_native_setup函数
-
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
-
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
-
{
-
camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID);
-
-
#if 1 // defined(MTK_CAMERA_BSP_SUPPORT)
-
sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);
-
#else
-
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
-
#endif
-
}
第4行, 调用了Camera.cpp的connect函数,同时返回一个Camera对象,保存在JNICameraContext当中
-
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
-
int clientUid)
-
{
-
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
-
}
先来看看Camera和CameraBase的类定义
-
/* ---------- Camera.h ---------- */
-
template <>
-
struct CameraTraits<Camera>
-
{
-
......
-
static TCamConnectService fnConnectService;
-
};
-
-
class Camera : public CameraBase<Camera>
-
{
-
......
-
}
-
/* -------- CameraBase.h -------- */
-
<pre name="code" class="cpp">template <typename TCam>
-
struct CameraTraits {
-
};
-
-
template <typename TCam, typename TCamTraits = CameraTraits<TCam>>
-
class CameraBase
-
{
-
......
-
typedef CameraBase<TCam> CameraBaseT;
-
}
这里使用了C++模版,其实就是调用CameraBase::connect函数
-
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService = &ICameraService::connect;
-
-
template <typename TCam, typename TCamTraits>
-
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
-
const String16& clientPackageName,
-
int clientUid)
-
{
-
sp<TCam> c = new TCam(cameraId);
-
sp<TCamCallbacks> cl = c;
-
-
const sp<ICameraService>& cs = getCameraService();
-
if (cs != 0) {
-
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
-
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
-
/*out*/ c->mCamera);
-
}
-
-
return c;
-
}
第1行, 将CameraTraits::fnConnectService赋为ICameraService::connect
第7行, 构造一个Camera对象
第10行, 获取ICameraService的Bp端
第13行, 从上面的解释可以看出,实际就是调用CameraService.cpp的connect函数
第17行, 将Camera对象返回给JNI层
-
status_t CameraService::connectHelperLocked(
-
/*out*/
-
sp<Client>& client,
-
/*in*/
-
const sp<ICameraClient>& cameraClient,
-
int cameraId,
-
const String16& clientPackageName,
-
int clientUid,
-
int callingPid,
-
int halVersion,
-
bool legacyMode) {
-
......
-
int deviceVersion = getDeviceVersion(cameraId, &facing);
-
-
switch(deviceVersion) {
-
case CAMERA_DEVICE_API_VERSION_1_0:
-
client = new CameraClient(this, cameraClient,
-
clientPackageName, cameraId,
-
facing, callingPid, clientUid, getpid(), legacyMode);
-
break;
-
case CAMERA_DEVICE_API_VERSION_2_0:
-
case CAMERA_DEVICE_API_VERSION_2_1:
-
case CAMERA_DEVICE_API_VERSION_3_0:
-
case CAMERA_DEVICE_API_VERSION_3_1:
-
case CAMERA_DEVICE_API_VERSION_3_2:
-
client = new Camera2Client(this, cameraClient,
-
clientPackageName, cameraId,
-
facing, callingPid, clientUid, getpid(), legacyMode);
-
break;
-
}
-
-
status_t status = connectFinishUnsafe(client, client->getRemote());
-
mClient[cameraId] = client;
-
}
-
-
status_t CameraService::connect(
-
const sp<ICameraClient>& cameraClient,
-
int cameraId,
-
const String16& clientPackageName,
-
int clientUid,
-
/*out*/
-
sp<ICamera>& device) {
-
......
-
sp<Client> client;
-
status = connectHelperLocked(/*out*/client,
-
cameraClient,
-
cameraId,
-
clientPackageName,
-
clientUid,
-
callingPid);
-
device = client;
-
return OK;
-
}
忽略细节之后connect函数就只是调用connectHelperLocked函数
第13行, 获取api版本信息,这个函数比较简单,不细说。这里的版本为CAMERA_DEVICE_API_VERSION_1_0
第15-30行, 根据不同的api版本选择构造CameraClient或Camera2Client,这里是CameraClient
第32行, 调用connectFinishUnsafe函数,实现如下
-
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
-
const sp<IBinder>& remoteCallback) {
-
status_t status = client->initialize(mModule);
-
}
这里的client就是上一个函数的CameraClient,mModule就是在上一篇博文CameraService的启动流程里提到的hal层的接口
-
status_t CameraClient::initialize(camera_module_t *module) {
-
mHardware = new CameraHardwareInterface(camera_device_name);
-
res = mHardware->initialize(&module->common);
-
mHardware->setCallbacks(notifyCallback,
-
dataCallback,
-
dataCallbackTimestamp,
-
(void *)(uintptr_t)mCameraId);
-
return OK;
-
}
构造一个CameraHardwareInterface对象,并调用它的initalize函数,直接看initalize函数
-
status_t initialize(hw_module_t *module)
-
{
-
module->methods->open(module, mName.string(), (hw_device_t **)&mDevice)
-
initHalPreviewWindow();
-
}
第4行, 从这里进入到了hal层,hal层主要对Camera硬件进行初始化,并将操作集保存在mDevice当中
4. hal层-基于MTK平台
hal层对Camera硬件进行初始化以及返回Device操作集的流程如下

4.1 open函数分析
这里再看一次module的定义
-
static
-
hw_module_methods_t*
-
get_module_methods()
-
{
-
static
-
hw_module_methods_t
-
_methods =
-
{
-
open: open_device
-
};
-
-
return &_methods;
-
}
-
-
static
-
camera_module
-
get_camera_module()
-
{
-
camera_module module = {
-
common:{
-
tag : HARDWARE_MODULE_TAG,
-
#if (PLATFORM_SDK_VERSION >= 21)
-
module_api_version : CAMERA_MODULE_API_VERSION_2_3,
-
#else
-
module_api_version : CAMERA_DEVICE_API_VERSION_1_0,
-
#endif
-
hal_api_version : HARDWARE_HAL_API_VERSION,
-
id : CAMERA_HARDWARE_MODULE_ID,
-
name : "MediaTek Camera Module",
-
author : "MediaTek",
-
methods : get_module_methods(),
-
dso : NULL,
-
reserved : {0},
-
},
-
get_number_of_cameras : get_number_of_cameras,
-
get_camera_info : get_camera_info,
-
set_callbacks : set_callbacks,
-
get_vendor_tag_ops : get_vendor_tag_ops,
-
#if (PLATFORM_SDK_VERSION >= 21)
-
open_legacy : open_legacy,
-
#endif
-
reserved : {0},
-
};
-
return module;
-
};
通过module->methods获取到的函数为open_device,
-
static
-
int
-
open_device(hw_module_t const* module, const char* name, hw_device_t** device)
-
{
-
return NSCam::getCamDeviceManager()->open(device, module, name);
-
}
CamDeviceManagerImp 继承了 CamDeviceManagerBase。这里直接调用了CamDeviceManagerBase的open()
-
status_t
-
CamDeviceManagerBase::
-
openDeviceLocked(
-
hw_device_t** device,
-
hw_module_t const* module,
-
int32_t const i4OpenId,
-
uint32_t device_version
-
)
-
{
-
// [2] get platform
-
IPlatform*const pPlatform = getPlatform();
-
pDevice = pPlatform->createCam1Device(s8ClientAppMode.string(), i4OpenId);
-
*device = const_cast<hw_device_t*>(pDevice->get_hw_device());
-
}
-
-
status_t
-
CamDeviceManagerBase::
-
open(
-
hw_device_t** device,
-
hw_module_t const* module,
-
char const* name,
-
uint32_t device_version
-
)
-
{
-
return openDeviceLocked(device, module, i4OpenId, device_version);
-
}
第11行, getPlatform函数用来加载libcam_platform.so,并获取PlatformEntry接口
第12行, 构造一个Cam1Device对象,并调用它的init函数
第13行, 获取camera device的操作集
4.2 getPlatform函数分析
-
static PlatformEntry g_PlatformEntry;
-
-
IPlatform*
-
getHandleToPlatform()
-
{
-
return &g_PlatformEntry;
-
}
-
-
IPlatform*
-
CamDeviceManagerBase::
-
getPlatform()
-
{
-
char const szModulePath[] = "libcam_platform.so";
-
char const szEntrySymbol[] = "getHandleToPlatform";
-
void* pfnEntry = NULL;
-
IPlatform* pIPlatform = NULL;
-
-
mpLibPlatform = ::dlopen(szModulePath, RTLD_NOW);
-
pfnEntry = ::dlsym(mpLibPlatform, szEntrySymbol);
-
pIPlatform = reinterpret_cast<IPlatform*(*)()>(pfnEntry)();
-
gIPlatform = pIPlatform;
-
-
return gIPlatform;
-
}
第18行, 加载libcam_platform.so
第19 20行, 获取getHandleToPlatform函数入口,并调用,最后返回PlatformEntry接口
4.3 pPlatform->createCam1Device函数分析
-
NSCam::Cam1Device*
-
createCam1Device(
-
String8 const s8ClientAppMode,
-
int32_t const i4OpenId
-
)
-
{
-
NSCam::Cam1Device* pdev = NULL;
-
-
String8 const s8LibPath = String8::format("libcam.device1.so");
-
void *handle = ::dlopen(s8LibPath.string(), RTLD_GLOBAL);
-
-
String8 const s8CamDeviceInstFactory = String8::format("createCam1Device_Default");
-
void* pCreateInstance = ::dlsym(handle, s8CamDeviceInstFactory.string());
-
pdev = reinterpret_cast<NSCam::Cam1Device* (*)(String8 const&, int32_t const)>
-
(pCreateInstance)(s8ClientAppMode, i4OpenId);
-
-
pdev->initialize();
-
}
-
-
ICamDevice*
-
PlatformEntry::
-
createCam1Device(
-
char const* szClientAppMode,
-
int32_t const i4OpenId
-
)
-
{
-
return ::createCam1Device(String8(szClientAppMode), i4OpenId);
-
}
pPlatform->createCam1Device函数调用的是Cam1DeviceFactory.cpp里的createCam1Device函数
第10行, 加载libcam.device1.so
第12-15行, 获取createCam1Device_Default函数入口并调用
第17行, Cam1Device初始化
先来看createCam1Device_Default函数,以及类的继承关系
-
class Cam1DeviceBase : public Cam1Device
-
{
-
}
-
-
class DefaultCam1Device : public Cam1DeviceBase
-
{
-
}
-
-
NSCam::Cam1Device*
-
createCam1Device_Default(
-
String8 const& rDevName,
-
int32_t const i4OpenId
-
)
-
{
-
return new DefaultCam1Device(rDevName, i4OpenId);
-
}
接着看DefaultCam1Device的构造函数
-
Cam1Device::
-
Cam1Device()
-
{
-
::memset(&mDevice, 0, sizeof(mDevice));
-
mDevice.priv = this;
-
mDevice.common = gHwDevice;
-
mDevice.ops = (camera_device_ops*)&mDeviceOps;
-
mDeviceOps = gCameraDevOps;
-
}
-
-
Cam1DeviceBase::
-
Cam1DeviceBase(
-
String8 const& rDevName,
-
int32_t const i4OpenId
-
)
-
: Cam1Device()
-
, mDevName(rDevName)
-
, mi4OpenId(i4OpenId)
-
{
-
MY_LOGD("");
-
}
-
-
DefaultCam1Device::
-
DefaultCam1Device(
-
String8 const& rDevName,
-
int32_t const i4OpenId
-
)
-
: Cam1DeviceBase(rDevName, i4OpenId)
-
{
-
}
删除了一些暂不关注的代码,DefaultCam1Device的构造函数会不断调用父类的构造函数,需要关注的是它的父类Cam1Device的构造函数。其中的gCameraDevOps结构体很重要,是Camera Device的操作集,预览、拍照、录像都是通过它来操作,来看下它的定义
-
static mtk_camera_device_ops const
-
gCameraDevOps =
-
{
-
#define OPS(name) name: camera_##name
-
-
{
-
OPS(set_preview_window),
-
OPS(set_callbacks),
-
OPS(enable_msg_type),
-
OPS(disable_msg_type),
-
OPS(msg_type_enabled),
-
OPS(start_preview),
-
OPS(stop_preview),
-
OPS(preview_enabled),
-
OPS(store_meta_data_in_buffers),
-
OPS(start_recording),
-
OPS(stop_recording),
-
OPS(recording_enabled),
-
OPS(release_recording_frame),
-
OPS(auto_focus),
-
OPS(cancel_auto_focus),
-
OPS(take_picture),
-
OPS(cancel_picture),
-
OPS(set_parameters),
-
OPS(get_parameters),
-
OPS(put_parameters),
-
OPS(send_command),
-
OPS(release),
-
OPS(dump)
-
},
-
OPS(mtk_set_callbacks),
-
-
#undef OPS
-
};
回到createCam1Device函数,最后调用了pdev->initialize函数,这个函数过程比较复杂,在它的父类Cam1DeviceBase中实现
-
bool
-
DefaultCam1Device::
-
onInit()
-
{
-
// (1) power on sensor
-
if( pthread_create(&mThreadHandle, NULL, doThreadInit, this) != 0 )
-
{
-
goto lbExit;
-
}
-
-
// (2) Open 3A
-
mpHal3a = NS3A::IHal3A::createInstance(
-
NS3A::IHal3A::E_Camera_1,
-
getOpenId(),
-
LOG_TAG);
-
-
// (3) Init Base.
-
if ( ! Cam1DeviceBase::onInit() )
-
{
-
goto lbExit;
-
}
-
}
-
-
status_t
-
Cam1DeviceBase::
-
initialize()
-
{
-
onInit();
-
return OK;
-
}
initialize函数只是简单的回调了onInit函数,如注释所示,主要做了3件事情。其中(2)和(3)主要是初始化3A和CamClient,这两个这里暂时不会关注,所以暂时不进行分析。重点关注(1),也就是doThreadInit函数
-
bool
-
DefaultCam1Device::
-
powerOnSensor()
-
{
-
IHalSensorList* pHalSensorList = IHalSensorList::get();
-
mpHalSensor = pHalSensorList->createSensor(USER_NAME, getOpenId());
-
sensorIdx = getOpenId();
-
if( !mpHalSensor->powerOn(USER_NAME, 1, &sensorIdx) )
-
{
-
MY_LOGE("sensor power on failed: %d", sensorIdx);
-
goto lbExit;
-
}
-
......
-
}
-
-
void*
-
DefaultCam1Device::
-
doThreadInit(void* arg)
-
{
-
DefaultCam1Device* pSelf = reinterpret_cast<DefaultCam1Device*>(arg);
-
pSelf->mRet = pSelf->powerOnSensor();
-
pthread_exit(NULL);
-
return NULL;
-
}
doThreadInit函数只是回调自身的了powerOnSensor函数,而powerOnSensor函数先调用pHalSensorList->createSensor函数创建一个HalSensor实例,然后再调用它的PowerOn函数来开始相关的硬件操作,来看powerOn的实现
-
MBOOL
-
HalSensor::
-
powerOn(
-
char const* szCallerName,
-
MUINT const uCountOfIndex,
-
MUINT const*pArrayOfIndex
-
)
-
{
-
......
-
ret = mpSeninfDrv->init();
-
ret = mpSensorDrv->init(sensorDev);
-
ret = setTgPhase(sensorDev, pcEn);
-
ret = setSensorIODrivingCurrent(sensorDev);
-
ret = mpSensorDrv->open(sensorDev);
-
......
-
}
powerOn函数比较长,这里暂时只关注SensorDrv的init和open函数
-
MINT32
-
ImgSensorDrv::init(MINT32 sensorIdx)
-
{
-
m_fdSensor = ::open("dev/kd_camera_hw", O_RDWR);
-
-
//set driver
-
ret = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,sensorDrvInit);
-
-
//init resolution
-
pSensorResInfo[0] = &m_SenosrResInfo[0];
-
pSensorResInfo[1] = &m_SenosrResInfo[1];
-
ret = getResolution(pSensorResInfo);
-
-
if(SENSOR_MAIN & sensorIdx ) {
-
sensorDevId = SENSOR_MAIN;
-
-
FeatureParaLen = sizeof(MUINTPTR);
-
ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ, (MUINT8*)&FeaturePara32,(MUINT32*)&FeatureParaLen);
-
-
FeatureParaLen = sizeof(pFeaturePara16);
-
ret = featureControl((CAMERA_DUAL_CAMERA_SENSOR_ENUM)sensorDevId, SENSOR_FEATURE_GET_PERIOD, (MUINT8*)pFeaturePara16,(MUINT32*)&FeatureParaLen);
-
}
-
......
-
}
-
-
MINT32
-
ImgSensorDrv::open(MINT32 sensorIdx)
-
{
-
MINT32 err = SENSOR_NO_ERROR;
-
-
......
-
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_CURRENT_SENSOR, &sensorIdx);
-
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_OPEN);
-
-
return err;
-
}
这两个函数逻辑比较简单,就是通过ioctl进入到kernel层来对sensor硬件进行初始化和获取硬件相关的信息。kernel层的代码暂不分析
4.4 get_hw_device函数分析
回到4.1的openDeviceLocked函数,最后调用了pDevice->get_hw_device函数,并将它的返回值赋给*device
-
class Cam1Device : public ICamDevice
-
{
-
virtual hw_device_t const* get_hw_device() const { return &mDevice.common; }
-
}
这个函数很简单,就是获取4.3里面提到的mDevice,这个mDevice最终将被保存在frameworks层的CameraHardwareInterface.h的mDevice变量当中,以便日后访问
5. 总结
Camera打开流程的重点工作在4.3和4.4章节,也就是对Camera硬件进行初始化和将gCameraDevOps操作集返回给frameworks层。