Thanks hanchao3c for sharing the article!java
Android的Camera包含取景器(viewfinder)和拍攝照片的功能。目前Android發佈版的Camera程序雖然功能比較簡單,可是其程序的架構分紅客戶端和服務器兩個部分,它們創建在Android的進程間通信Binder的結構上。linux
以開源的Android爲例,Camera的代碼主要在如下的目錄中:android
Camera的JAVA程序的路徑:
packages/apps/Camera/src/com/android/camera/
在其中Camera.java是主要實現的文件數組
Camera的JAVA本地調用部分(JNI):
frameworks/base/core/jni/android_hardware_Camera.cpp
這部份內容編譯成爲目標是libandroid_runtime.so服務器
主要的頭文件在如下的目錄中:
frameworks/base/include/ui/cookie
Camera底層庫在如下的目錄中:
frameworks/base/libs/ui/
這部分的內容被編譯成庫libui.so。架構
Camera服務部分:
frameworks/base/camera/libcameraservice/
這部份內容被編譯成庫libcameraservice.so。app
爲了實現一個具體功能的Camera,在最底層還須要一個硬件相關的Camera庫(例如經過調用video for linux驅動程序和Jpeg編碼程序實現)。這個庫將被Camera的服務庫libcameraservice.so調用。框架
在 Camera系統的各個庫中,libui.so位於核心的位置,它對上層的提供的接口主要是Camera類,類 libandroid_runtime.so經過調用Camera類提供對JAVA的接口,而且實現了android.hardware.camera 類。 libcameraservice.so是Camera的服務器程序,它經過繼承libui.so的類實現服務器的功能,而且與libui.so中的另外 一部份內容則經過進程間通信(即Binder機制)的方式進行通信。
libandroid_runtime.so和libui.so兩個庫是公用的,其中除了Camera還有其餘方面的功能。
Camera部分的頭文件在frameworks/base/include/ui/目錄中,這個目錄是和libmedia.so庫源文件的目錄frameworks/base/libs/ui/相對應的。
Camera主要的頭文件有如下幾個:
在這些頭文件中,Camera.h提供了對上層的接口,而其餘的幾個頭文件都是提供一些接口類(即包含了純虛函數的類),這些接口類必須被實現類繼承纔可以使用。
整個Camera在運行的時候,能夠大體上分紅Client和Server兩個部分,它們分別在兩個進程中運行,它們之間使用Binder機制實現 進程間通信。這樣在客戶端調用接口,功能則在服務器中實現,可是在客戶端中調用就好像直接調用服務器中的功能,進程間通信的部分對上層程序不可見。
從框架結構上來看,ICameraService.h、ICameraClient.h和ICamera.h三個類定義了MeidaPlayer的 接口和架構,ICameraService.cpp和Camera.cpp兩個文件用於Camera架構的實現,Camera的具體功能在下層調用硬件相 關的接口來實現。
從Camera的總體結構上,類Camera是整個系統核心,ICamera類提供了Camera主要功能的接口,在客戶端方面調 用,CameraService是Camera服務,它經過調用實際的Camera硬件接口來實現功能。事實上,圖中紅色虛線框的部分都是Camera程 序的框架部分,它主要利用了Android的系統的Binder機制來完成通信。藍色的部分經過調用Camera硬件相關的接口完成具體的Camera服 務功能,其它的部分是爲上層的JAVA程序提供JNI接口。在總體結構上,左邊能夠視爲一個客戶端,右邊是一個能夠視爲服務器,兩者經過Android的 Bimder來實現進程間的通信。
ICameraClient.h用於描述一個Camera客戶端的接口,定義以下所示:
class ICameraClient: 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的基礎類Binder機制實如今進程通信而構建的。 根據BnInterface類模版的定義BnInterface<ICameraClient>類至關於雙繼承了BnInterface和 ICameraClient。IcameraClient這個類的主要接口是幾個回調函數shutterCallback、rawCallback和 jpegCallback等,它們在相應動做發生的時候被調用。做爲Camera的「客戶端」,須要本身實現幾個回調函數,讓服務器程序去「間接地」調用 它們。
Camera.h是Camera對外的接口頭文件,它被實現Camera JNI的文件android_hardware_Camera.cpp所調用。Camera.h最主要是定義了一個Camera類:
class Camera : public BnCameraClient, public IBinder::DeathRecipient
{
public:
static sp connect();
~Camera();
void disconnect();
status_t getStatus() { return mStatus; }
status_t setPreviewDisplay(const sp& 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& picture);
virtual void jpegCallback(const sp& picture);
virtual void frameCallback(const sp& frame);
virtual void errorCallback(status_t error);
virtual void autoFocusCallback(bool focused);
//……
}
從接口中能夠看出Camera類恰好實現了一個Camera的基本操做,例如播放(startPreview)、中止(stopPreview)、 暫停(takePicture)等。在Camera類中connect()是一個靜態函數,它用於獲得一個Camera的實例。在這個類中,具備設置回調 函數的幾個函數:setShutterCallback、setRawCallback和setJpegCallback等,這幾個函數是爲了提供給上層 使用,上層利用這幾個設置回調函數,這些回調函數在相應的回調函數中調用,例如使用setShutterCallback設置的回調函數指針被 shutterCallback所調用。
在定義中,ICameraClient 類雙繼承了IInterface和IBinder:DeathRecipient,並定義了一個Camera客戶端的接口,BnCameraClient 繼承了BnInterface<ICameraClient>,這是爲基於Android的基礎類Binder機制實如今進程通信而構建的。 事實上,根據BnInterface類模版的定義BnInterface<ICameraClient>類至關於雙繼承了 BnInterface和ICameraClient。這是Android一種經常使用的定義方式。
繼承了DeathNotifier類以後,這樣當這個類做爲IBinder使用的時候,當這個Binder即將Died的時候被調用其中的binderDied函數。繼承這個類基本上實現了一個回調函數的功能。
ICamera.h描述的內容是一個實現Camera功能的接口,其定義以下所示:
class ICamera: public IInterface { public: DECLARE_META_INTERFACE(Camera); virtual void disconnect() = 0; virtual status_t setPreviewDisplay(const sp& 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 { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
在camera類中,主要定義Camera的功能接口,這個類必須被繼承纔可以使用。值得注意的是,這些接口和Camera類的接口有些相似,可是它們並無直接的關係。事實上,在Camera類的各類實現中,通常都會經過調用ICamera類的實現類來完成。
ICameraService.h用於描述一個Camera的服務,定義方式以下所示:
class ICameraService : public IInterface
{
public:
DECLARE_META_INTERFACE(CameraService);
virtual sp connect(const sp& cameraClient) = 0;
};
class BnCameraService: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
因爲具備純虛函數, ICameraService 以及BnCameraService必須被繼承實現纔可以使用,在ICameraService 只定義了一個connect()接口,它的返回值的類型是sp<ICamera>,這個ICamera 是提供實現功能的接口。注意,ICameraService只有鏈接函數connect(),沒有斷開函數,斷開的功能由ICamera接口來提供。
CameraHardwareInterface.h定義的是一個Camera底層的接口,這個類的實現者是最終實現Camera的。
CameraHardwareInterface 定以Camera硬件的接口,以下所示:
class CameraHardwareInterface : public virtual RefBase {
public:
virtual ~CameraHardwareInterface() { }
virtual sp<IMemoryHeap> getPreviewHeap() const = 0;
virtual status_t startPreview(preview_callback cb, void* user) = 0;
virtual voidstopPreview() = 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 CameraParametersgetParameters() const = 0;
virtual void release() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
};
使用C語言的方式導出符號:
extern "C" sp<CameraHardwareInterface> openCameraHardware();
在程序的其餘地方,使用openCameraHardware()就能夠獲得一個 CameraHardwareInterface,而後調用 CameraHardwareInterface的接口完成Camera的功能。
在packages/apps/Camera/src/com/android/camera/
目錄的Camera.java文件中,包含了對Camera的調用
在Camera.java中包含對包的引用:
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
在這裏定義的Camera類繼承了活動Activity類,在它的內部,包含了一個
android.hardware.Camera
public class Camera extends Activity implements View.OnClickListener, SurfaceHolder.Callback {
android.hardware.Camera mCameraDevice;
}
對Camera功能的一些調用以下所示:
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
mCameraDevice.startPreview();
mCameraDevice.stopPreview();
startPreview、stopPreview 和takePicture等接口就是經過JAVA本地調用(JNI)來實現的。
frameworks/base/core/java/android/hardware/目錄中的Camera.java文件提供了一個JAVA類:Camera。
public class Camera {
public void setParameters(Parameters params) {
Log.e(TAG, "setParameters()");
//params.dump();
native_setParameters(params.flatten());
}
}
在這個類當中,大部分代碼使用JNI調用下層獲得,例如:
再者,例如如下代碼:
public final void setPreviewDisplay(SurfaceHolder holder) {
setPreviewDisplay(holder.getSurface());
}
private native final void setPreviewDisplay(Surface surface);
兩個setPreviewDisplay參數不一樣,後一個是本地方法,參數爲Surface類型,前一個經過調用後一個實現,但本身的參數以SurfaceHolder爲類型。
Camera的JAVA本地調用(JNI)部分在frameworks/base/core/jni/目錄的android_hardware_Camera.cpp中的文件中實現。
android_hardware_Camera.cpp之中定義了一個JNINativeMethod(JAVA本地調用方法)類型的數組gMethods,以下所示:
static JNINativeMethod 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本地調用方法的名稱,這個名稱是在JAVA程序中調用的名稱;第二個成員也是一個字符串,表示JAVA本地調用方法的參數和返回值;第三個成員是JAVA本地調用方法對應的C語言函數。
register_android_hardware_Camera 函數將gMethods註冊爲的類」android/media/Camera」,其主要的實現以下所示。
int register_android_hardware_Camera(JNIEnv *env)
{
// Register native functions
return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",
camMethods, NELEM(camMethods));
}
「android/hardware/Camera」對應JAVA的類android.hardware.Camera。
3.3 Camera本地庫libui.so
frameworks/base/libs/ui/中的Camera.cpp文件用於實現Camera.h提供的接口,其中一個重要的片斷以下所示
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;
}
其中最重要的一點是binder = sm->getService(String16(「media.camera」));;這個調用用來獲得一個名稱爲」media.camera」 的服務,這個調用返回值的類型爲IBinder,根據實現將其轉換成類型ICameraService使用。
一個函數 connect的實現 以下所示:
sp<Camera> Camera::connect()
{
sp<Camera> c = new Camera();
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
c->mCamera = cs->connect(c);
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
}
return c;
}
connect經過調用getCameraService獲得一個 ICameraService,再經過 ICameraService的cs->connect(c)獲得一個 ICamera類型的指針。 調用connect將獲得一個 Camera的指針,正常狀況下Camera的成員 mCamera已經初始化完成。
一個具體的函數startPreview 以下所示:
status_t Camera::startPreview()
{
return mCamera->startPreview();
}
這些操做能夠直接對 mCamera來進行,它是ICamera類型的指針。
其餘一些函數的實現也與setDataSource相似。
libmedia.so中的其餘一些文件與頭文件的名稱相同,它們是:
frameworks/base/libs/ui/ICameraClient.cpp
frameworks/base/libs/ui/ICamera.cpp
frameworks/base/libs/ui/ICameraService.cpp
在此處,BnCameraClient和BnCameraService類雖然實現了onTransact()函數,可是因爲還有純虛函數沒有實現,所以這個類都是不能實例化的。
ICameraClient.cpp中的BnCameraClient在別的地方也沒有實現;而ICameraService.cpp中的BnCameraService類在別的地方被繼承並實現,繼承者實現了Camera服務的具體功能
frameworks/base/camera/libcameraservice/ 用於實現一個Camera的服務,這個服務是繼承ICameraService的具體實現。
在這裏的Android.mk文件中,使用宏USE_CAMERA_STUB決定是否使用真的Camera,若是宏爲真,則使用 CameraHardwareStub.cpp和FakeCamera.cpp構造一個假的Camera,若是爲假則使用 CameraService.cpp構造一個實際上的Camera服務。
CameraService.cpp是繼承BnCameraService 的實現,在這個類的內部又定義了類Client,CameraService::Client繼承了BnCamera。在運做的過程當中 CameraService::connect()函數用於獲得一個CameraService::Client,在使用過程當中,主要是經過調用這個類的 接口來實現完成Camera的功能,因爲CameraService::Client自己繼承了BnCamera類,而BnCamera類是繼承了 ICamera,所以這個類是能夠被當成ICamera來使用的。
CameraService和CameraService::Client兩個類的結果以下所示:
class CameraService : public BnCameraService
{
class Client : public BnCamera {};
wp<Client>mClient;
}
在CameraService中的一個靜態函數instantiate()用於初始化一個Camera服務,寒暑以下所示:
void CameraService::instantiate() {
defaultServiceManager()->addService(String16("media.camera"), new CameraService());
}
事實上,CameraService::instantiate()這個函數註冊了一個名稱爲」media.camera」的服務,這個服務和Camera.cpp中調用的名稱相對應。
Camera整個運做機制是:在Camera.cpp中能夠調用ICameraService的接口,這時實際上調用的是 BpCameraService,而BpCameraService又經過Binder機制和BnCameraService實現兩個進程的通信。而 BpCameraService的實現就是這裏的CameraService。所以,Camera.cpp雖然是在另一個進程中運行,可是調用 ICameraService的接口就像直接調用同樣,從connect()中能夠獲得一個ICamera類型的指針,真個指針的實現其實是 CameraService::Client。
而這些Camera功能的具體實現,就是CameraService::Client所實現的了,其構造函數以下所示:
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient) :
mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)
{
mHardware = openCameraHardware();
mHasFrameCallback = false;
}
構造函數中,調用openCameraHardware()獲得一個CameraHardwareInterface類型的指針,並做爲其成員mHardware。之後對實際的Camera的操做都經過對這個指針進行。這是一個簡單的直接調用關係。
事實上,真正的Camera功能己經過實現CameraHardwareInterface類來完成。在這個庫當中 CameraHardwareStub.h和CameraHardwareStub.cpp兩個文件定義了一個樁模塊的接口,在沒有Camera硬件的情 況下使用,例如在仿真器的狀況下使用的文件就是CameraHardwareStub.cpp和它依賴的文件FakeCamera.cpp。
CameraHardwareStub類的結構以下所示:
class CameraHardwareStub : public CameraHardwareInterface {
class PreviewThread : public Thread {
};
};
在類CameraHardwareStub當中,包含一個線程類PreviewThread,這個線程用於處理PreView,即負責刷新取景器的 內容。實際的Camera硬件接口一般能夠經過對v4l2 捕獲驅動的調用來實現,同時還須要一個JPEG編碼程序將從驅動中取出的數據編碼成JPEG文件。