android camera流程,Android Camera 运行流程

Android Camera 运行流程

首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有个main函数,可以用来注册媒体服务。没错就是在这里,CameraService完成了服务的注册,相关代码如下:

int main(int argc, char** argv)

{

spproc(ProcessState::self());

spsm = defaultServiceManager();

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() {

spsm(defaultServiceManager());

return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());

}

static void publishAndJoinThreadPool() {

spproc(ProcessState::self());

spsm(defaultServiceManager());

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(this), cameraId);

}

好,终于来到JNI了

继续看camera的JNI文件:frameworks/base/core/jni# gedit android_hardware_Camera.cpp

由于前面Camera的构造函数里调用了native_setup(new WeakReference(this), cameraId);

那么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(this), cameraId);这个调用即是对下面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)

{spcamera = Camera::connect(cameraId);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.spcontext = new JNICameraContext(env, weak_this, clazz, camera);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

spCamera::connect(int cameraId)

{

LOGV("connect");

spc = new Camera();

const sp& cs = getCameraService();

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& cs =getCameraService();获取CameraService实例。

进入getCameraService()中

// establish binder interface to camera service

const sp& Camera::getCameraService()

{

Mutex::Autolock _l(mLock);

if (mCameraService.get() == 0) {

spsm = defaultServiceManager();

spbinder;

do {

binder = sm->getService(String16("media.camera"));

if (binder != 0)

break;

LOGW("CameraService not published, waiting...");

usleep(500000); // 0.5 s

} while(true);

if (mDeathNotifier == NULL) {

mDeathNotifier = new DeathNotifier();

}

binder->linkToDeath(mDeathNotifier);

mCameraService = interface_cast(binder);

}

LOGE_IF(mCameraService==0, "no CameraService!?");

return mCameraService;

}

CameraService实例通过binder获取的,mCameraService即为CameraService的实例。

回到spCamera::connect(int cameraId)中

c->mCamera = cs->connect(c, cameraId);

即:执行server的connect()函数,并且返回ICamera对象,赋值给Camera的mCamera,服务端connect()返回的是他内部类的一个实例。

server的connect()函数定义在以下路径:frameworks/base/services/camera/libcameraservice/CameraService.cpp

spCameraService::connect(

const sp& cameraClient, int cameraId) {

int callingPid = getCallingPid();

sphardware = NULL;

LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);

if (!mModule) {

LOGE("Camera HAL module not loaded");

return NULL;

}

spclient;

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

{

class Client : public BnCamera

{

public:

......

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分享給大家,想看的可以看看,自己記錄的

f5eb4426879d9c4b4b2deb15679e0746.pngAndroid Camera Procedure.pptx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值