Android Camera 运行流程
一
首先既然Camera是利用binder通信,它肯定要将它的service注册到ServiceManager里面,以备后续Client引用,那么这一步是在哪里进行的呢?细心的人会发现,在frameworks\base\media\mediaserver\Main_MediaServer.cpp下有个main函数,可以用来注册媒体服务。没错就是在这里,CameraService完成了服务的注册,相关代码如下:
int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = 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<CameraService>, public BnCameraService { class Client; friend class BinderService<CameraService>; public: static char const* getServiceName() { return "media.camera"; } .....
.....
}
从以上定义可以看出CameraService 继承于BinderService,所以CameraService::instantiate(); 其实是调用BinderService中的instantiate
BinderService的定义在frameworks/base/include/binder/BinderService.h中
// --------------------------------------------------------------------------- namespace android {
template<typename SERVICE> class BinderService { public: static status_t publish() { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); }
static void publishAndJoinThreadPool() { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(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<typename SERVICE>
这表示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<Camera>(this), cameraId); } 好,终于来到JNI了
三 继续看camera的JNI文件:frameworks/base/core/jni# gedit android_hardware_Camera.cpp
由于前面Camera的构造函数里调用了native_setup(new WeakReference<Camera>(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<Camera>(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) { sp<Camera> camera = 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. sp<JNICameraContext> context = 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
sp<Camera> Camera::connect(int cameraId) { LOGV("connect"); sp<Camera> c = new Camera(); const sp<ICameraService>& 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<ICameraService>& cs =getCameraService();获取CameraService实例。
进入getCameraService()中
// establish binder interface to camera service const sp<ICameraService>& Camera::getCameraService() { Mutex::Autolock _l(mLock); if (mCameraService.get() == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; 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<ICameraService>(binder); } LOGE_IF(mCameraService==0, "no CameraService!?"); return mCameraService; } CameraService实例通过binder获取的,mCameraService即为CameraService的实例。 回到sp<Camera> Camera::connect(int cameraId)中 c->mCamera = cs->connect(c, cameraId); 即:执行server的connect()函数,并且返回ICamera对象,赋值给Camera的mCamera,服务端connect()返回的是他内部类的一个实例。 server的connect()函数定义在以下路径:frameworks/base/services/camera/libcameraservice/CameraService.cpp
sp<ICamera> CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId) { int callingPid = getCallingPid(); sp<CameraHardwareInterface> hardware = NULL;
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
if (!mModule) { LOGE("Camera HAL module not loaded"); return NULL; }
sp<Client> client; 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<CameraService>, 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