一、在android中開發(fā)人員可以做那些工作?
應(yīng)用程序開發(fā):利用android提供的強(qiáng)大的sdk,開發(fā)出各種各樣新穎的應(yīng)用。
系統(tǒng)開發(fā):在android中Google實(shí)現(xiàn)了與硬件無關(guān)的所有代碼,但是與硬件密切相關(guān)的硬件抽象層卻沒有也無法提供,對(duì)于移動(dòng)設(shè)備不同的設(shè)備提供商 底層硬件是千變?nèi)f化的,不可能提供統(tǒng)一的硬件驅(qū)動(dòng)以及接口實(shí)現(xiàn),只能提供標(biāo)準(zhǔn)的接口,因此硬件提供商需要自個(gè)兒開發(fā)設(shè)備驅(qū)動(dòng),并去實(shí)現(xiàn)android框架提供的接口。
二、android框架中Camera系統(tǒng)源碼分析
在每個(gè)android手機(jī)中都有一個(gè)Camera應(yīng)用程序用來實(shí)現(xiàn)拍照功能,不同硬件提供商可能會(huì)對(duì)這個(gè)應(yīng)用程序進(jìn)行改變來適合自己的UI風(fēng)格,
這里僅僅分析android原生Camera應(yīng)用以及框架(Android 4.0)
原生Camera應(yīng)用代碼在Camera.java(android4.0\packages\apps\camera\src\com\android\camera),這個(gè)應(yīng)該算是Camera系統(tǒng)最上層,應(yīng)用層的實(shí)現(xiàn)。
(PS:^_^不錯(cuò)的Android學(xué)習(xí)交流群:314230976,驗(yàn)證:eec,有興趣的話可以加入進(jìn)來一起討論)
下面是Camera類部分代碼
- public class Camera extends ActivityBase implements FocusManager.Listener,
- View.OnTouchListener, ShutterButton.OnShutterButtonListener,
- SurfaceHolder.Callback, ModePicker.OnModeChangeListener,
- FaceDetectionListener, CameraPreference.OnPreferenceChangedListener,
- LocationManager.Listener, ShutterButton.OnShutterButtonLongPressListener
復(fù)制代碼 從上面可以看出,Camera在繼承了很多監(jiān)聽接口,用來監(jiān)聽各種事件(對(duì)焦事件、用戶觸摸事件等)。這個(gè)應(yīng)用時(shí)繼承ActivityBase,
可以重載OnCreate、OnResume等接口,在這些接口中完成相關(guān)初始化的工作,基本就是初始化各種監(jiān)聽對(duì)象,以及獲取相機(jī)參數(shù)等相關(guān)。
比較關(guān)鍵的在 doOnResume這個(gè)函數(shù)中:
- @Override
- protected void doOnResume() {
- if (mOpenCameraFail || mCameraDisabled) return;
- mPausing = false;
- mJpegPictureCallbackTime = 0;
- mZoomValue = 0;
- // Start the preview if it is not started.
- if (mCameraState == PREVIEW_STOPPED) {
- try {
- mCameraDevice = Util.openCamera(this, mCameraId);
- initializeCapabilities();
- resetExposureCompensation();
- startPreview();
- if (mFirstTimeInitialized) startFaceDetection();
- } catch (CameraHardwareException e) {
- Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
- return;
- } catch (CameraDisabledException e) {
- Util.showErrorAndFinish(this, R.string.camera_disabled);
- return;
- }
- }
- if (mSurfaceHolder != null) {
- // If first time initialization is not finished, put it in the
- // message queue.
- if (!mFirstTimeInitialized) {
- mHandler.sendEmptyMessage(FIRST_TIME_INIT);
- } else {
- initializeSecondTime();
- }
- }
- keepScreenOnAwhile();
- if (mCameraState == IDLE) {
- mOnResumeTime = SystemClock.uptimeMillis();
- mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
- }
- }
復(fù)制代碼 在這個(gè)函數(shù)中看到通過這個(gè)函數(shù)獲得Camera底層對(duì)象
mCameraDevice = Util.openCamera(this, mCameraId),這里使用Util這個(gè)類,這個(gè)類的實(shí)現(xiàn)在
Util.java (android4.0\packages\apps\camera\src\com\android\camera)中,找到OpenCamera這個(gè)函數(shù)實(shí)現(xiàn):
- 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;
- }
- }
- }
復(fù)制代碼 從這個(gè)函數(shù)可以看出,android系統(tǒng)中對(duì)下層Camera管理,是通過一個(gè)單例模式CameraHolder來管理的,
定位到這個(gè)類的實(shí)現(xiàn)CameraHolder.java (android4.0\packages\apps\camera\src\com\android\camera)通過調(diào)用open函數(shù)獲取一個(gè)Camera硬件設(shè)備對(duì)象,
因?yàn)镃amera設(shè)備是獨(dú)享設(shè)備,不能同時(shí)被兩個(gè)進(jìn)程占用,而整個(gè)android系統(tǒng)是一個(gè)多進(jìn)程環(huán)境,因此需要加入一些進(jìn)程間互斥同步的方法。
定位到這個(gè)類的open函數(shù):
- 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;
- }
復(fù)制代碼 通 過android.hardware.Camera.open(cameraId)調(diào)用進(jìn)入下一層封裝,JNI層,這一層是java代碼的最下層,對(duì)下層 CameraC++代碼進(jìn)行JNI封裝,封裝實(shí)現(xiàn)類在Camera.java (android4.0\frameworks\base\core\java\android\hardware) 下面是這個(gè)類的部分實(shí)現(xiàn),里面定義了不少回調(diào)函數(shù):
- public class Camera {
- private static final String TAG = "Camera";
- // These match the enums in frameworks/base/include/camera/Camera.h
- private static final int CAMERA_MSG_ERROR = 0x001;
- private static final int CAMERA_MSG_SHUTTER = 0x002;
- private static final int CAMERA_MSG_FOCUS = 0x004;
- private static final int CAMERA_MSG_ZOOM = 0x008;
- private static final int CAMERA_MSG_PREVIEW_FRAME = 0x010;
- private static final int CAMERA_MSG_VIDEO_FRAME = 0x020;
- private static final int CAMERA_MSG_POSTVIEW_FRAME = 0x040;
- private static final int CAMERA_MSG_RAW_IMAGE = 0x080;
- private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
- private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200;
- private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400;
- private static final int CAMERA_MSG_ALL_MSGS = 0x4FF;
- private int mNativeContext; // accessed by native methods
- private EventHandler mEventHandler;
- private ShutterCallback mShutterCallback;
- private PictureCallback mRawImageCallback;
- private PictureCallback mJpegCallback;
- private PreviewCallback mPreviewCallback;
- private PictureCallback mPostviewCallback;
- private AutoFocusCallback mAutoFocusCallback;
- private OnZoomChangeListener mZoomListener;
- private FaceDetectionListener mFaceListener;
- private ErrorCallback mErrorCallback;
復(fù)制代碼 定位到Open函數(shù):
- public static Camera open(int cameraId) {
- return new Camera(cameraId);
- }
復(fù)制代碼
Open函數(shù)是一個(gè)靜態(tài)方法,構(gòu)造一個(gè)Camera對(duì)象:
- 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);
- }
復(fù)制代碼 在構(gòu)造函數(shù)中調(diào)用native_setup方法,此方法對(duì)應(yīng)于C++代碼的android_hardware_Camera_native_setup方法,
實(shí)現(xiàn)在android_hardware_Camera.cpp (android4.0\frameworks\base\core\jni),具體代碼如下:
- static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jint cameraId)
- {
- sp 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 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());
- }
復(fù)制代碼
在android_hardware_Camera_native_setup方法中調(diào)用了Camera對(duì)象的connect方法,這個(gè)Camera類的 聲明在Camera.h (android4.0\frameworks\base\include\camera)
定位到connect方法:
- sp Camera::connect(int cameraId)
- {
- LOGV("connect");
- sp c = 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;
- }
復(fù)制代碼
這里以下的代碼就比較關(guān)鍵了,涉及到Camera框架的實(shí)現(xiàn)機(jī)制,Camera系統(tǒng)使用的是Server-Client機(jī)制,Service和Client位于不同的進(jìn)程中,進(jìn)程間使用Binder機(jī)制進(jìn)行通信,
Service端實(shí)際實(shí)現(xiàn)相機(jī)相關(guān)的操作,Client端通過Binder接口調(diào)用Service對(duì)應(yīng)的操作。
繼續(xù)分析代碼,上面函數(shù)調(diào)用getCameraService方法,獲得CameraService的引用,ICameraService有兩個(gè)子類,BnCameraService和BpCameraService,這兩個(gè)子類同時(shí)也
繼承了IBinder接口,這兩個(gè)子類分別實(shí)現(xiàn)了Binder通信的兩端,Bnxxx實(shí)現(xiàn)ICameraService的具體功能,Bpxxx利用Binder的通信功能封裝ICameraService方法,具體如下:
- class ICameraService : public IInterface
- {
- public:
- enum {
- GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
- GET_CAMERA_INFO,
- CONNECT
- };
復(fù)制代碼
- public:
- DECLARE_META_INTERFACE(CameraService);
- virtual int32_t getNumberOfCameras() = 0;
- virtual status_t getCameraInfo(int cameraId,
- struct CameraInfo* cameraInfo) = 0;
- virtual sp connect(const sp& cameraClient,
- int cameraId) = 0;
- };
- // ----------------------------------------------------------------------------
- class BnCameraService: public BnInterface
- {
- public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
- };
- }; // na
- class BpCameraService: public BpInterface
- {
- public:
- BpCameraService(const sp& impl)
- : BpInterface(impl)
- {
- }
- // get number of cameras available
- virtual int32_t getNumberOfCameras()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
- return reply.readInt32();
- }
- // get information about a camera
- virtual status_t getCameraInfo(int cameraId,
- struct CameraInfo* cameraInfo) {
- Parcel data, reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
- cameraInfo->facing = reply.readInt32();
- cameraInfo->orientation = reply.readInt32();
- return reply.readInt32();
- }
- // connect to camera service
- virtual sp connect(const sp& cameraClient, int cameraId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(cameraClient->asBinder());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::CONNECT, data, &reply);
- return interface_cast(reply.readStrongBinder());
- }
- };
- IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
- // ----------------------------------------------------------------------
- status_t BnCameraService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- case GET_NUMBER_OF_CAMERAS: {
- CHECK_INTERFACE(ICameraService, data, reply);
- reply->writeInt32(getNumberOfCameras());
- return NO_ERROR;
- } break;
- case GET_CAMERA_INFO: {
- CHECK_INTERFACE(ICameraService, data, reply);
- CameraInfo cameraInfo;
- memset(&cameraInfo, 0, sizeof(cameraInfo));
- status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
- reply->writeInt32(cameraInfo.facing);
- reply->writeInt32(cameraInfo.orientation);
- reply->writeInt32(result);
- return NO_ERROR;
- } break;
- case CONNECT: {
- CHECK_INTERFACE(ICameraService, data, reply);
- sp cameraClient = interface_cast(data.readStrongBinder());
- sp camera = connect(cameraClient, data.readInt32());
- reply->writeStrongBinder(camera->asBinder());
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
- }
- // ----------------------------------------------------------------------------
- }; // namespace android
復(fù)制代碼 下面繼續(xù)分析sp Camera::connect(int cameraId)這個(gè)方法,,定位到getCameraService這個(gè)方法
- const sp& Camera::getCameraService()
- {
- Mutex::Autolock _l(mLock);
- if (mCameraService.get() == 0) {
- sp sm = defaultServiceManager();
- sp 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(binder);
- }
- LOGE_IF(mCameraService==0, "no CameraService!?");
- return mCameraService;
- }
復(fù)制代碼
定位到mCameraService = interface_cast(binder); mCameraService是一個(gè)ICamerService類型,更加具體具體一點(diǎn)來講應(yīng)該是BpCameraService,
因?yàn)樵谶@個(gè)類中實(shí)現(xiàn)了ICameraService的方法。
總結(jié)上面Binder機(jī)制,僅僅考慮分析Binder用法,對(duì)底層實(shí)現(xiàn)不進(jìn)行深究,基本步驟如下:
1.定義進(jìn)程間通信的接口比如這里的ICameraService;
2.在BnCameraService和BpCamaraService實(shí)現(xiàn)這個(gè)接口,這兩個(gè)接口也分別繼承于BnInterface和BpInterface;
3.服務(wù)端向ServiceManager注冊(cè)Binder,客戶端向ServiceManager獲得Binder;
4.然后就可以實(shí)現(xiàn)雙向進(jìn)程間通信了;
通過getCameraService得到ICameraService引用后,調(diào)用ICameraService的connect方法獲得ICamera引用,
c->mCamera = cs->connect(c, cameraId);
進(jìn)一步跟進(jìn)connect方法,這里就是BpCameraService類中connect方法的具體實(shí)現(xiàn)。
- virtual sp connect(const sp& cameraClient, int cameraId)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
- data.writeStrongBinder(cameraClient->asBinder());
- data.writeInt32(cameraId);
- remote()->transact(BnCameraService::CONNECT, data, &reply);
- return interface_cast(reply.readStrongBinder());
- }
復(fù)制代碼 在這里返回的ICamera對(duì)象,實(shí)際上應(yīng)該是BpCamera對(duì)象,這里使用的是匿名Binder,前面獲取CameraService的 使用的有名Binder,有名Binder需要借助于ServiceManager獲取Binder,而匿名Binder可以通過已經(jīng)建立后的通信通道 (有名Binder)獲得。以上是實(shí)現(xiàn)Camera框架部分,具體的實(shí)現(xiàn)Camera相關(guān)的方法是在ICamera相關(guān)的接口,下面是給接口的定義:
- class ICamera: public IInterface
- {
- public:
- DECLARE_META_INTERFACE(Camera);
- virtual void disconnect() = 0;
- // connect new client with existing camera remote
- virtual status_t connect(const sp& client) = 0;
- // prevent other processes from using this ICamera interface
- virtual status_t lock() = 0;
- // allow other processes to use this ICamera interface
- virtual status_t unlock() = 0;
- // pass the buffered Surface to the camera service
- virtual status_t setPreviewDisplay(const sp& surface) = 0;
- // pass the buffered ISurfaceTexture to the camera service
- virtual status_t setPreviewTexture(
- const sp& surfaceTexture) = 0;
- // set the preview callback flag to affect how the received frames from
- // preview are handled.
- virtual void setPreviewCallbackFlag(int flag) = 0;
- // start preview mode, must call setPreviewDisplay first
- virtual status_t startPreview() = 0;
- // stop preview mode
- virtual void stopPreview() = 0;
- // get preview state
- virtual bool previewEnabled() = 0;
- // start recording mode
- virtual status_t startRecording() = 0;
- // stop recording mode
- virtual void stopRecording() = 0;
- // get recording state
- virtual bool recordingEnabled() = 0;
- // release a recording frame
- virtual void releaseRecordingFrame(const sp& mem) = 0;
- // auto focus
- virtual status_t autoFocus() = 0;
- // cancel auto focus
- virtual status_t cancelAutoFocus() = 0;
- virtual status_t takePicture(int msgType) = 0;
- // set preview/capture parameters - key/value pairs
- virtual status_t setParameters(const String8& params) = 0;
- // get preview/capture parameters - key/value pairs
- virtual String8 getParameters() const = 0;
- // send command to camera driver
- virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
- // tell the camera hal to store meta data or real YUV data in video buffers.
- virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
- };
復(fù)制代碼 ICamera接口有兩個(gè)子類BnCamera和BpCamera,是Binder通信的兩端,BpCamera提供客戶端調(diào)用 接口,BnCamera封裝具體的實(shí)現(xiàn),BnCamera也并沒有真正實(shí)現(xiàn)ICamera相關(guān)接口而是在BnCamera子類 CameraService::Client中進(jìn)行實(shí)現(xiàn)。而在CameraService::Client類中會(huì)繼續(xù)調(diào)用硬件抽象層中相關(guān)方法來具體實(shí)現(xiàn)Camera功能。
|