第一部分 Camera概述
Android的Camera包含取景器(viewfinder)和拍攝照片的功能。目前Android發(fā)布版的Camera程序雖然功能比較簡單,但是其程序的架構(gòu)分成客戶端和服務(wù)器兩個部分,它們建立在Android的進(jìn)程間通訊Binder的結(jié)構(gòu)上。
以開源的Android為例,Camera的代碼主要在以下的目錄中:
Camera的JAVA程序的路徑:
packages/apps/Camera/src/com/android/camera/
在其中Camera.java是主要實現(xiàn)的文件
frameworks/base/core/java/android/hardware/Camera.java
這個類是和JNI中定義的類是一個,有些方法通過JNI的方式調(diào)用本地代碼得到,有些方法自己實現(xiàn)。
Camera的JAVA本地調(diào)用部分(JNI):
frameworks/base/core/jni/android_hardware_Camera.cpp
這部分內(nèi)容編譯成為目標(biāo)是libandroid_runtime.so。
主要的頭文件在以下的目錄中:
frameworks/base/include/ui/
Camera底層庫在以下的目錄中:
frameworks/base/libs/ui/
這部分的內(nèi)容被編譯成庫libui.so。
Camera服務(wù)部分:
frameworks/base/camera/libcameraservice/
這部分內(nèi)容被編譯成庫libcameraservice.so。
為了實現(xiàn)一個具體功能的Camera,在最底層還需要一個硬件相關(guān)的Camer庫(例如通過調(diào)用videofor linux驅(qū)動程序和Jpeg編碼程序?qū)崿F(xiàn))。這個庫將被Camera的服務(wù)庫libcameraservice.so調(diào)用。
第二部分 Camera的接口與架構(gòu)
2.1 Camera的整體框架圖Camera的各個庫之間的結(jié)構(gòu)可以用下圖的表示:
在Camera系統(tǒng)的各個庫中,libui.so位于核心的位置,它對上層的提供的接口主要是Camera類,類libandroid_runtime.so通過調(diào)用Camera類提供對JAVA的接口,并且實現(xiàn)了android.hardware.camera類。
libcameraservice.so是Camera的服務(wù)器程序,它通過繼承l(wèi)ibui.so的類實現(xiàn)服務(wù)器的功能,并且與libui.so中的另外一部分內(nèi)容則通過進(jìn)程間通訊(即Binder機制)的方式進(jìn)行通訊。
libandroid_runtime.so和libui.so兩個庫是公用的,其中除了Camera還有其他方面的功能。
Camera部分的頭文件在frameworks/base/include/ui/目錄中,這個目錄是和libmedia.so庫源文件的目錄frameworks/base/libs/ui/相對應(yīng)的。
Camera主要的頭文件有以下幾個:
ICameraClient.h
Camera.h
ICamera.h
ICameraService.h
CameraHardwareInterface.h
在這些頭文件Camera.h提供了對上層的接口,而其他的幾個頭文件都是提供一些接口類(即包含了純虛函數(shù)的類),這些接口類必須被實現(xiàn)類繼承才能夠使用。
整個Camera在運行的時候,可以大致上分成Client和Server兩個部分,它們分別在兩個進(jìn)程中運行,它們之間使用Binder機制實現(xiàn)進(jìn)程間通訊。這樣在客戶端調(diào)用接口,功能則在服務(wù)器中實現(xiàn),但是在客戶端中調(diào)用就好像直接調(diào)用服務(wù)器中的功能,進(jìn)程間通訊的部分對上層程序不可見。
從框架結(jié)構(gòu)上來看,ICameraService.h、ICameraClient.h和ICamera.h三個類定義了MeidaPlayer的接口和架構(gòu),ICameraService.cpp和Camera.cpp兩個文件用于Camera架構(gòu)的實現(xiàn),Camera的具體功能在下層調(diào)用硬件相關(guān)的接口來實現(xiàn)。
從Camera的整體結(jié)構(gòu)上,類Camera是整個系統(tǒng)核心,ICamera類提供了Camera主要功能的接口,在客戶端方面調(diào)用,CameraService是Camera服務(wù),它通過調(diào)用實際的Camera硬件接口來實現(xiàn)功能。事實上,圖中紅色虛線框的部分都是Camera程序的框架部分,它主要利用了Android的系統(tǒng)的Binder機制來完成通訊。藍(lán)色的部分通過調(diào)用Camera硬件相關(guān)的接口完成具體的Camera服務(wù)功能,其它的部分是為上層的JAVA程序提供JNI接口。在整體結(jié)構(gòu)上,左邊可以視為一個客戶端,右邊是一個可以視為服務(wù)器,二者通過Android的Bimder來實現(xiàn)進(jìn)程間的通訊。
2.2 頭文件ICameraClient.h
ICameraClient.h用于描述一個Camera客戶端的接口,定義如下所示:
classICameraClient: public IInterface
{
public:
DECLARE_META_INTERFACE(CameraClient);
virtual void shutterCallback() = 0;
virtual void rawCallback(const sp<IMemory>& picture) = 0;
virtual void jpegCallback(const sp<IMemory>& picture) = 0;
virtual void frameCallback(const sp<IMemory>& frame) = 0;
virtual void errorCallback(status_t error) = 0;
virtual void autoFocusCallback(bool focused) = 0;
};
class BnCameraClient: public BnInterface<ICameraClient>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
在定義中,ICameraClient 類繼承IInterface,并定義了一個Camera客戶端的接口,BnCameraClient繼承了BnInterface<ICameraClient>,這是為基于Android的基礎(chǔ)類Binder機制實現(xiàn)在進(jìn)程通訊而構(gòu)建的。根據(jù)BnInterface類模版的定義BnInterface<ICameraClient>類相當(dāng)于雙繼承了BnInterface和ICameraClient。
IcameraClient這個類的主要接口是幾個回調(diào)函數(shù)shutterCallback、rawCallback和jpegCallback等,它們在相應(yīng)動作發(fā)生的時候被調(diào)用。作為Camera的“客戶端”,需要自己實現(xiàn)幾個回調(diào)函數(shù),讓服務(wù)器程序去“間接地”調(diào)用它們。
2.3頭文件Camera.h
Camera.h是Camera對外的接口頭文件,它被實現(xiàn)CameraJNI的文件android_hardware_Camera.cpp所調(diào)用。Camera.h最主要是定義了一個Camera類:
class Camera : public BnCameraClient, public IBinder::DeathRecipient
{
public:
static sp<Camera> connect();
~Camera();
void disconnect();
status_t getStatus() { return mStatus; }
status_t setPreviewDisplay(const sp<Surface>&surface);
status_t startPreview();
void stopPreview();
status_t autoFocus();
status_t takePicture();
status_t setParameters(const String8& params);
String8 getParameters() const;
void setShutterCallback(shutter_callback cb, void*cookie);
void setRawCallback(frame_callback cb, void *cookie);
void setJpegCallback(frame_callback cb, void*cookie);
void setFrameCallback(frame_callback cb, void*cookie);
void setErrorCallback(error_callback cb, void*cookie);
void setAutoFocusCallback(autofocus_callback cb, void*cookie);
// ICameraClient interface
virtual void shutterCallback();
virtual void rawCallback(const sp<IMemory>&picture);
virtual void jpegCallback(const sp<IMemory>&picture);
virtual void frameCallback(const sp<IMemory>&frame);
virtual void errorCallback(status_t error);
virtual void autoFocusCallback(bool focused);
//……
}
從接口中可以看出Camera類剛好實現(xiàn)了一個Camera的基本操作,例如播放(startPreview)、停止(stopPreview)、暫停(takePicture)等。在Camera類中connect()是一個靜態(tài)函數(shù),它用于得到一個Camera的實例。在這個類中,具有設(shè)置回調(diào)函數(shù)的幾個函數(shù):setShutterCallback、setRawCallback和setJpegCallback等,這幾個函數(shù)是為了提供給上層使用,上層利用這幾個設(shè)置回調(diào)函數(shù),這些回調(diào)函數(shù)在相應(yīng)的回調(diào)函數(shù)中調(diào)用,例如使用setShutterCallback設(shè)置的回調(diào)函數(shù)指針被shutterCallback所調(diào)用。
在定義中,ICameraClient類雙繼承了IInterface和IBinder::DeathRecipient,并定義了一個Camera客戶端的接口,BnCameraClient繼承了BnInterface<ICameraClient>,這是為基于Android的基礎(chǔ)類Binder機制實現(xiàn)在進(jìn)程通訊而構(gòu)建的。事實上,根據(jù)BnInterface類模版的定義BnInterface<ICameraClient>類相當(dāng)于雙繼承了BnInterface和ICameraClient。這是Android一種常用的定義方式。
繼承了DeathNotifier類之后,這樣當(dāng)這個類作為IBinder使用的時候,當(dāng)這個Binder即將Died的時候被調(diào)用其中的binderDied函數(shù)。繼承這個類基本上實現(xiàn)了一個回調(diào)函數(shù)的功能。
2.4 頭文件ICamera.h
ICamera.h描述的內(nèi)容是一個實現(xiàn)Camera功能的接口,其定義如下所示:
class ICamera:public IInterface
{
public:
DECLARE_META_INTERFACE(Camera);
virtual void disconnect() = 0;
virtual status_t setPreviewDisplay(const sp<ISurface>&surface) = 0;
virtual void setHasFrameCallback(bool installed) = 0;
virtual status_t startPreview() = 0;
virtual void stopPreview() = 0;
virtual status_t autoFocus() = 0;
virtual status_t takePicture() = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual String8 getParameters() const = 0;
};
class BnCamera: public BnInterface<ICamera>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
ICamera.h描述的內(nèi)容是一個實現(xiàn)Camera功能的接口,其定義如下所示:
在camera類中,主要定義Camera的功能接口,這個類必須被繼承才能夠使用。值得注意的是,這些接口和Camera類的接口有些類似,但是它們并沒有直接的關(guān)系。事實上,在Camera類的各種實現(xiàn)中,一般都會通過調(diào)用ICamera類的實現(xiàn)類來完成。
2.5頭文件ICameraService .h
ICameraService.h用于描述一個Camera的服務(wù),定義方式如下所示:
class ICameraService: public IInterface
{
public:
DECLARE_META_INTERFACE(CameraService);
virtual sp<ICamera> connect(constsp<ICameraClient>& cameraClient) = 0;
};
class BnCameraService: public BnInterface<ICameraService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
由于具有純虛函數(shù), ICameraService以及BnCameraService必須被繼承實現(xiàn)才能夠使用,在ICameraService只定義了一個connect()接口,它的返回值的類型是sp<ICamera>,這個ICamera是提供實現(xiàn)功能的接口。注意,ICameraService只有連接函數(shù)connect(),沒有斷開函數(shù),斷開的功能由ICamera接口來提供。
2.6頭文件CameraHardwareInterface.h
CameraHardwareInterface.h定義的是一個Camera底層的接口,這個類的實現(xiàn)者是最終實現(xiàn)Camera的。
CameraHardwareInterface 定以Camera硬件的接口,如下所示:
classCameraHardwareInterface : public virtual RefBase {
public:
virtual ~CameraHardwareInterface() { }
virtual sp<IMemoryHeap> getPreviewHeap() const = 0;
virtual status_t startPreview(preview_callback cb, void* user) =0;
virtual void stopPreview() = 0;
virtual status_t autoFocus(autofocus_callback,
void* user) = 0;
virtual status_t takePicture(shutter_callback,
raw_callback,
jpeg_callback,
void* user) = 0;
virtual status_t cancelPicture(bool cancel_shutter,
bool cancel_raw,
bool cancel_jpeg) = 0;
virtual status_t setParameters(const CameraParameters& params)= 0;
virtual CameraParameters getParameters() const = 0;
virtual void release() = 0;
virtual status_t dump(int fd, const Vector<String16>&args) const = 0;
};
使用C語言的方式導(dǎo)出符號:
extern"C" sp<CameraHardwareInterface> openCameraHardware();
在程序的其他地方,使用openCameraHardware()就可以得到一個 CameraHardwareInterface,然后調(diào)用CameraHardwareInterface的接口完成Camera的功能。
第三部分 Camera的主要實現(xiàn)分析
3.1JAVA程序部分
在packages/apps/Camera/src/com/android/camera/目錄的Camera.java文件中,包含了對Camera的調(diào)用
在Camera.java中包含對包的引用:
importandroid.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
在這里定義的Camera類繼承了活動Activity類,在它的內(nèi)部,包含了一個android.hardware.Camera
public class Cameraextends Activity implements View.OnClickListener, SurfaceHolder.Callback{ android.hardware.Camera mCameraDevice;
}
對Camera功能的一些調(diào)用如下所示:
mCameraDevice.takePicture(mShutterCallback,mRawPictureCallback, mJpegPictureCallback);
mCameraDevice.startPreview();
mCameraDevice.stopPreview();
startPreview、stopPreview 和takePicture等接口就是通過JAVA本地調(diào)用(JNI)來實現(xiàn)的。
frameworks/base/core/java/android/hardware/目錄中的Camera.java文件提供了一個JAVA類:Camera。
public class Camera {
}
在這個類當(dāng)中,大部分代碼使用JNI調(diào)用下層得到,例如:
public void setParameters(Parameters params) {
Log.e(TAG,"setParameters()");
//params.dump();
native_setParameters(params.flatten());
}
再者,例如以下代碼:
public finalvoid setPreviewDisplay(SurfaceHolder holder) {
setPreviewDisplay(holder.getSurface());
}
private nativefinal void setPreviewDisplay(Surface surface);
兩個setPreviewDisplay參數(shù)不同,后一個是本地方法,參數(shù)為Surface類型,前一個通過調(diào)用后一個實現(xiàn),但自己的參數(shù)以SurfaceHolder為類型。
3.2 Camera的JAVA本地調(diào)用部分
Camera的JAVA本地調(diào)用(JNI)部分在frameworks/base/core/jni/目錄的android_hardware_Camera.cpp中的文件中實現(xiàn)。
android_hardware_Camera.cpp之中定義了一個JNINativeMethod(JAVA本地調(diào)用方法)類型的數(shù)組gMethods,如下所示:
staticJNINativeMethod camMethods[] = {
{"native_setup","(Ljava/lang/Object;)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 },
{"startPreview","()V",(void *)android_hardware_Camera_startPreview },
{"stopPreview", "()V", (void *)android_hardware_Camera_stopPreview },
{"setHasPreviewCallback","(Z)V",(void*)android_hardware_Camera_setHasPreviewCallback },
{"native_autoFocus","()V",(void *)android_hardware_Camera_autoFocus },
{"native_takePicture", "()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 }
};
JNINativeMethod的第一個成員是一個字符串,表示了JAVA本地調(diào)用方法的名稱,這個名稱是在JAVA程序中調(diào)用的名稱;第二個成員也是一個字符串,表示JAVA本地調(diào)用方法的參數(shù)和返回值;第三個成員是JAVA本地調(diào)用方法對應(yīng)的C語言函數(shù)。
register_android_hardware_Camera函數(shù)將gMethods注冊為的類"android/media/Camera",其主要的實現(xiàn)如下所示。
intregister_android_hardware_Camera(JNIEnv *env)
{
// Register native functions
return AndroidRuntime::registerNativeMethods(env,"android/hardware/Camera",
camMethods,NELEM(camMethods));
}
"android/hardware/Camera"對應(yīng)JAVA的類android.hardware.Camera。