小鱼儿游啊游啊。。。。
全部博文(338)
分类: Android平台
2013-07-02 18:01:37
原文地址:Android Camera 运行流程 作者:xinyuwuxian
Android Camera 运行流程
一
首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有个main函数,可以用来注册媒体服务。没错就是在这里,CameraService完成了服务的注册,相关代码如下:
int main(int argc, char** argv)
{
sp
sp
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
可是我们到CameraService文件里面却找不到instantiate()这个函数,它在哪?继续追到它的一个父类BinderService,
CameraService的定义在frameworks/base/services/camera/libcameraservice/CameraService.h中
class CameraService :
public BinderService
public BnCameraService
{
class Client;
friend class BinderService
public:
static char const* getServiceName() { return "media.camera"; }
.....
.....
}
从以上定义可以看出CameraService 继承于BinderService,所以CameraService::instantiate(); 其实是调用BinderService中的instantiate
BinderService的定义在frameworks/base/include/binder/BinderService.h中
// ---------------------------------------------------------------------------
namespace android {
template
class BinderService
{
public:
static status_t publish() {
sp
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void publishAndJoinThreadPool() {
sp
sp
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() {
return NO_ERROR;
}
};
}; // namespace android
// ---------------------------------------------------------------------------
可以发现在publish()函数中,CameraService完成服务的注册 。这里面有个SERVICE,源码中有说明
template
这表示SERVICE是个模板,这里是注册CameraService,所以可以用CameraService代替
return sm->addService(String16(CameraService::getServiceName()), new CameraService());
好了这样,Camera就在ServiceManager完成服务注册,提供给client随时使用。
Main_MediaServer主函数由init.rc在启动是调用,所以在设备开机的时候Camera就会注册一个服务,用作binder通信。
二
Binder服务已注册,那接下来就看看client如何连上server端,并打开camera模块。咱们先从camera app的源码入手。在onCreate()函数中专门有一个open Camera的线程
camera app的源码文件在以下目录packages/apps/OMAPCamera/src/com/ti/omap4/android/camera/camera.java
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getPreferredCameraId();
String[] defaultFocusModes = getResources().getStringArray(
R.array.pref_camera_focusmode_default_array);
mFocusManager = new FocusManager(mPreferences, defaultFocusModes);
/*
* To reduce startup time, we start the camera open and preview threads.
* We make sure the preview is started at the end of onCreate.
*/
mCameraOpenThread.start();
PreferenceInflater inflater = new PreferenceInflater(this);
PreferenceGroup group =
(PreferenceGroup) inflater.inflate(R.xml.camera_preferences);
ListPreference gbce = group.findPreference(CameraSettings.KEY_GBCE);
if (gbce != null) {
mGBCEOff = gbce.findEntryValueByEntry(getString(R.string.pref_camera_gbce_entry_off));
if (mGBCEOff == null) {
mGBCEOff = "";
}
}
ListPreference autoConvergencePreference = group.findPreference(CameraSettings.KEY_AUTO_CONVERGENCE);
if (autoConvergencePreference != null) {
mTouchConvergence = autoConvergencePreference.findEntryValueByEntry(getString(R.string.pref_camera_autoconvergence_entry_mode_touch));
if (mTouchConvergence == null) {
mTouchConvergence = "";
}
mManualConvergence = autoConvergencePreference.findEntryValueByEntry(getString(R.string.pref_camera_autoconvergence_entry_mode_manual));
if (mManualConvergence == null) {
mManualConvergence = "";
}
}
ListPreference exposure = group.findPreference(CameraSettings.KEY_EXPOSURE_MODE_MENU);
if (exposure != null) {
mManualExposure = exposure.findEntryValueByEntry(getString(R.string.pref_camera_exposuremode_entry_manual));
if (mManualExposure == null) {
mManualExposure = "";
}
}
ListPreference temp = group.findPreference(CameraSettings.KEY_MODE_MENU);
if (temp != null) {
mTemporalBracketing = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_temporal_bracketing));
if (mTemporalBracketing == null) {
mTemporalBracketing = "";
}
mExposureBracketing = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_exp_bracketing));
if (mExposureBracketing == null) {
mExposureBracketing = "";
}
mZoomBracketing = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_zoom_bracketing));
if (mZoomBracketing == null) {
mZoomBracketing = "";
}
mHighPerformance = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_hs));
if (mHighPerformance == null) {
mHighPerformance = "";
}
mHighQuality = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_hq));
if (mHighQuality == null) {
mHighQuality = "";
}
mHighQualityZsl = temp.findEntryValueByEntry(getString(R.string.pref_camera_mode_entry_zsl));
if (mHighQualityZsl == null) {
mHighQualityZsl = "";
}
}
getPreferredCameraId();
mFocusManager = new FocusManager(mPreferences,
defaultFocusModes);
mTouchManager = new TouchManager();
mIsImageCaptureIntent = isImageCaptureIntent();
setContentView(R.layout.camera);
if (mIsImageCaptureIntent) {
mReviewDoneButton = (Rotatable) findViewById(R.id.btn_done);
mReviewCancelButton = (Rotatable) findViewById(R.id.btn_cancel);
findViewById(R.id.btn_cancel).setVisibility(View.VISIBLE);
} else {
mThumbnailView = (RotateImageView) findViewById(R.id.thumbnail);
mThumbnailView.enableFilter(false);
mThumbnailView.setVisibility(View.VISIBLE);
}
mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog);
mCaptureLayout = getString(R.string.pref_camera_capture_layout_default);
mPreferences.setLocalId(this, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
mQuickCapture = getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
// we need to reset exposure for the preview
resetExposureCompensation();
Util.enterLightsOutMode(getWindow());
// don't set mSurfaceHolder here. We have it set ONLY within
// surfaceChanged / surfaceDestroyed, other parts of the code
// assume that when it is set, the surface is also set.
SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview);
SurfaceHolder holder = preview.getHolder();
holder.addCallback(this);
s3dView = new S3DViewWrapper(holder);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// Make sure camera device is opened.
try {
mCameraOpenThread.join();
mCameraOpenThread = null;
if (mOpenCameraFail) {
Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
return;
} else if (mCameraDisabled) {
Util.showErrorAndFinish(this, R.string.camera_disabled);
return;
}
} catch (InterruptedException ex) {
// ignore
}
mCameraPreviewThread.start();
if (mIsImageCaptureIntent) {
setupCaptureParams();
} else {
mModePicker = (ModePicker) findViewById(R.id.mode_picker);
mModePicker.setVisibility(View.VISIBLE);
mModePicker.setOnModeChangeListener(this);
mModePicker.setCurrentMode(ModePicker.MODE_CAMERA);
}
mZoomControl = (ZoomControl) findViewById(R.id.zoom_control);
mOnScreenIndicators = (Rotatable) findViewById(R.id.on_screen_indicators);
mLocationManager = new LocationManager(this, this);
// Wait until the camera settings are retrieved.
synchronized (mCameraPreviewThread) {
try {
mCameraPreviewThread.wait();
} catch (InterruptedException ex) {
// ignore
}
}
// Do this after starting preview because it depends on camera
// parameters.
initializeIndicatorControl();
mCameraSound = new CameraSound();
// Make sure preview is started.
try {
mCameraPreviewThread.join();
} catch (InterruptedException ex) {
// ignore
}
mCameraPreviewThread = null;
}
再看看mCameraOpenThread
Thread mCameraOpenThread = new Thread(new Runnable() {
public void run() {
try {
mCameraDevice = Util.openCamera(Camera.this, mCameraId);
} catch (CameraHardwareException e) {
mOpenCameraFail = true;
} catch (CameraDisabledException e) {
mCameraDisabled = true;
}
}
});
继续追Util.openCamera ,Util类的定义在以下目录:packages/apps/OMAPCamera/src/com/ti/omap4/android/camera/Util.java
public static android.hardware.Camera openCamera(Activity activity, int cameraId)
throws CameraHardwareException, CameraDisabledException {
// Check if device policy has disabled the camera.
DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm.getCameraDisabled(null)) {
throw new CameraDisabledException();
}
try {
return CameraHolder.instance().open(cameraId);
} catch (CameraHardwareException e) {
// In eng build, we throw the exception so that test tool
// can detect it and report it
if ("eng".equals(Build.TYPE)) {
throw new RuntimeException("openCamera failed", e);
} else {
throw e;
}
}
}
又来了个CameraHolder,该类用一个实例openCamera
CameraHolder的定义在以下目录:packages/apps/OMAPCamera/src/com/ti/omap4/android/camera/CameraHolder.java
public synchronized android.hardware.Camera open(int cameraId)
throws CameraHardwareException {
Assert(mUsers == 0);
if (mCameraDevice != null && mCameraId != cameraId) {
mCameraDevice.release();
mCameraDevice = null;
mCameraId = -1;
}
if (mCameraDevice == null) {
try {
Log.v(TAG, "open camera " + cameraId);
mCameraDevice = android.hardware.Camera.open(cameraId);
mCameraId = cameraId;
} catch (RuntimeException e) {
Log.e(TAG, "fail to connect Camera", e);
throw new CameraHardwareException(e);
}
mParameters = mCameraDevice.getParameters();
} else {
try {
mCameraDevice.reconnect();
} catch (IOException e) {
Log.e(TAG, "reconnect failed.");
throw new CameraHardwareException(e);
}
mCameraDevice.setParameters(mParameters);
}
++mUsers;
mHandler.removeMessages(RELEASE_CAMERA);
mKeepBeforeTime = 0;
return mCameraDevice;
}
在这里就开始进入framework层了,调用frameworks\base\core\java\android\hardware\Camera.java类的open方法 。
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
这里调用了Camera的构造函数,在看看构造函数
Camera(int cameraId) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mZoomListener = null;
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;
}
native_setup(new WeakReference
}
好,终于来到JNI了
三
继续看camera的JNI文件:frameworks/base/core/jni# gedit android_hardware_Camera.cpp
由于前面Camera的构造函数里调用了native_setup(new WeakReference
那么native_setup()的定义在那里呢
通过我的查看,在frameworks/base/core/jni# gedit android_hardware_Camera.cpp中有这样一个定义,
我认为通过这个定义,使得native_setup和android_hardware_Camera_native_setup 关联起来
static JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
{ "getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "native_setup",
"(Ljava/lang/Object;I)V",
(void*)android_hardware_Camera_native_setup },
{ "native_release",
"()V",
(void*)android_hardware_Camera_release },
{ "setPreviewDisplay",
"(Landroid/view/Surface;)V",
(void *)android_hardware_Camera_setPreviewDisplay },
{ "setPreviewTexture",
"(Landroid/graphics/SurfaceTexture;)V",
(void *)android_hardware_Camera_setPreviewTexture },
{ "startPreview",
"()V",
(void *)android_hardware_Camera_startPreview },
{ "_stopPreview",
"()V",
(void *)android_hardware_Camera_stopPreview },
{ "previewEnabled",
"()Z",
(void *)android_hardware_Camera_previewEnabled },
{ "setHasPreviewCallback",
"(ZZ)V",
(void *)android_hardware_Camera_setHasPreviewCallback },
{ "_addCallbackBuffer",
"([BI)V",
(void *)android_hardware_Camera_addCallbackBuffer },
{ "native_autoFocus",
"()V",
(void *)android_hardware_Camera_autoFocus },
{ "native_cancelAutoFocus",
"()V",
(void *)android_hardware_Camera_cancelAutoFocus },
{ "native_takePicture",
"(I)V",
(void *)android_hardware_Camera_takePicture },
{ "native_setParameters",
"(Ljava/lang/String;)V",
(void *)android_hardware_Camera_setParameters },
{ "native_getParameters",
"()Ljava/lang/String;",
(void *)android_hardware_Camera_getParameters },
{ "reconnect",
"()V",
(void*)android_hardware_Camera_reconnect },
{ "lock",
"()V",
(void*)android_hardware_Camera_lock },
{ "unlock",
"()V",
(void*)android_hardware_Camera_unlock },
{ "startSmoothZoom",
"(I)V",
(void *)android_hardware_Camera_startSmoothZoom },
{ "stopSmoothZoom",
"()V",
(void *)android_hardware_Camera_stopSmoothZoom },
{ "setDisplayOrientation",
"(I)V",
(void *)android_hardware_Camera_setDisplayOrientation },
{ "_startFaceDetection",
"(I)V",
(void *)android_hardware_Camera_startFaceDetection },
{ "_stopFaceDetection",
"()V",
(void *)android_hardware_Camera_stopFaceDetection},
};
所以,native_setup(new WeakReference
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp
if (camera == NULL) {
jniThrowRuntimeException(env, "Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
jniThrowRuntimeException(env, "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
JNI函数里面,我们找到Camera C/S架构的客户端了,它调用connect函数向服务器发送连接请求。JNICameraContext这个类是一个监听类,用于处理底层Camera回调函数传来的数据和消息
看看客户端的connect函数有什么,connect定义在以下路径frameworks/base/libs/camera/camera.cpp
sp
{
LOGV("connect");
sp
const sp
if (cs != 0) {
c->mCamera = cs->connect(c, cameraId);
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
const sp
进入getCameraService()中
// establish binder interface to camera service
sp
const sp
int callingPid = getCallingPid();
sp
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
if (!mModule) {
LOGE("Camera HAL module not loaded");
return NULL;
}
sp
if (cameraId < 0 || cameraId >= mNumberOfCameras) {
LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
callingPid, cameraId);
return NULL;
}
char value[PROPERTY_VALUE_MAX];
property_get("sys.secpolicy.camera.disabled", value, "0");
if (strcmp(value, "1") == 0) {
// Camera is disabled by DevicePolicyManager.
LOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
return NULL;
}
Mutex::Autolock lock(mServiceLock);
if (mClient[cameraId] != 0) {
client = mClient[cameraId].promote();
if (client != 0) {
if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
LOG1("CameraService::connect X (pid %d) (the same client)",
callingPid);
return client;
} else {
LOGW("CameraService::connect X (pid %d) rejected (existing client).",
callingPid);
return NULL;
}
}
mClient[cameraId].clear();
}
if (mBusy[cameraId]) {
LOGW("CameraService::connect X (pid %d) rejected"
" (camera %d is still busy).", callingPid, cameraId);
return NULL;
}
struct camera_info info;
if (mModule->get_camera_info(cameraId, &info) != OK) {
LOGE("Invalid camera id %d", cameraId);
return NULL;
}
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
hardware = new CameraHardwareInterface(camera_device_name);
if (hardware->initialize(&mModule->common) != OK) {
hardware.clear();
return NULL;
}
client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
}
实例化Camera Hal接口 hardware,hardware调用initialize()进入HAL层打开Camear驱动。
CameraHardwareInterface中initialize()定义在以下路径:frameworks/base/services/camera/libcameraservice/CameraHardwareInterface.h
代码如下:
status_t initialize(hw_module_t *module)
{
LOGI("Opening camera %s", mName.string());
int rc = module->methods->open(module, mName.string(),
(hw_device_t **)&mDevice);
if (rc != OK) {
LOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
#ifdef OMAP_ENHANCEMENT_CPCAM
initHalPreviewWindow(&mHalPreviewWindow);
initHalPreviewWindow(&mHalTapin);
initHalPreviewWindow(&mHalTapout);
#else
initHalPreviewWindow();
#endif
return rc;
}
此处通过module->method->open()方法真正打开Camera设备,
其中module的定义在以下路径:
class CameraService :
public BinderService
public BnCameraService
{
private:
.....
};
camera_module_t *mModule;
};
此处还必须找到camera_module_t 的定义,以更好的理解整个运行流程,通过追根溯源找到了camera_module_t 定义,
camera_module_t的定义在以下路径:hardware/libhardware/include/hardware/camera.h中,定义如下
typedef struct camera_module {
hw_module_t common;
int (*get_number_of_cameras)(void);
int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;
其中包含get_number_of_cameras方法和get_camera_info方法用于获取camera info
另外hw_module_t common;这个选项十分重要,此处应重点关注,因为是使用hw_module_t结构体中的open()方法打开设备文件的
继续找到hw_module_t 结构体的定义.在以下路径:hardware/libhardware/include/hardware/hardware.h,代码如下:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
/** major version number for the module */
uint16_t version_major;
/** minor version number of the module */
uint16_t version_minor;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_t;
同样,找到hw_module_methods_t这个结构体的定义,代码如下:
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
hw_module_methods_t 结构体中只有open()一个方法,用于打开camera driver,实现与硬件层的交互
到此为止,很容易看出:
Android中Camera的调用流程可分为以下几个层次:
Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver
一併把我自己總結的ppt分享給大家,想看的可以看看,自己記錄的
Android Camera Procedure.pptx