在前一篇文章Camera Client/Server的binder IPC機制中闡述了Android進程間通訊binder IPC機制基礎,Android Camera基於這個基礎設計了Camera Framework Client/Server架構,文中給出了其類圖設計。本文從Android 4.4 版本源碼入手,分析Camera App向Camera Service請求服務與返回的過程。服務請求的過程從上到下依次要通過三個大的過程:1. Camera App調用Framework Camera類Java API;2. Camera類Java API經過JNI調用JNI層的C++接口函數;3. 基於binder通訊設計的Camera IPC通訊過程。下面結合代碼分析整個服務請求過程。html
Camera應用調用Framework Camera類APIjava
在Android Kitkat原生Camera2應用(packages/apps/Camera2/)的PhotoModule, VideoModule, WideAnglePanoramaModule類中用CameraUtil.open()方法來打開Camera。而後依次調用:CameraHolder的open()方法,AndroidCameraManagerImpl的cameraOpen()方法,CameraHandler的handleMessage()【message爲OPEN_CAMERA】,直到調用Framework Camera類(frameworks/base/core/java/android/hardware/Camera.java)的open()方法。在這裏,Camera2應用程序暫不作分析,咱們着重看程序向下調用的服務請求過程。android
mCameraDevice = CameraUtil.openCamera( mActivity, mCameraId, mHandler, mActivity.getCameraOpenErrorCallback()); // (1)
public class CameraUtil { public static CameraManager.CameraProxy openCamera( Activity activity, final int cameraId, Handler handler, final CameraManager.CameraOpenErrorCallback cb) { try { throwIfCameraDisabled(activity); return CameraHolder.instance().open(handler, cameraId, cb); // (2) } catch (CameraDisabledException ex) { handler.post(new Runnable() { @Override public void run() { cb.onCameraDisabled(cameraId); } }); } return null; } }
public class CameraHolder { public synchronized CameraProxy open( Handler handler, int cameraId, CameraManager.CameraOpenErrorCallback cb) { ………… if (mCameraDevice == null) { Log.v(TAG, "open camera " + cameraId); if (mMockCameraInfo == null) { mCameraDevice = CameraManagerFactory .getAndroidCameraManager().cameraOpen(handler, cameraId, cb); // (3) ………… } else { ………… } mCameraOpened = true; mHandler.removeMessages(RELEASE_CAMERA); ………… return mCameraDevice; } }
class AndroidCameraManagerImpl implements CameraManager { public CameraManager.CameraProxy cameraOpen( Handler handler, int cameraId, CameraOpenErrorCallback callback) { mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0, CameraOpenErrorCallbackForward.getNewInstance( handler, callback)).sendToTarget(); // (4) ………… } }
private class CameraHandler extends Handler { @Override public void handleMessage(final Message msg) { try { switch (msg.what) { case OPEN_CAMERA: mCamera = android.hardware.Camera.open(msg.arg1); // (5) ………… return; } } } }
public class Camera { public static Camera open(int cameraId) { return new Camera(cameraId); } Camera(int cameraId) { ………… String packageName = ActivityThread.currentPackageName(); native_setup(new WeakReference<Camera>(this), cameraId, packageName); } }
JNI層註冊native_setup方法架構
static JNINativeMethod camMethods[] = { { "native_setup", "(Ljava/lang/Object;ILjava/lang/String;)V", (void*)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, jstring clientPackageName) { ………… sp<Camera> camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID); ………… }
CameraService服務鏈接(IPC通訊)app
JNI調用Camera::connect()請求CameraService服務。Camera類繼承模板類CameraBase<Camera>和BnCameraClient。首先調用模板類的connect()函數,在函數中向ServiceManager獲取Camera服務信息,並生成CameraService服務代理BpCameraService(/frameworks/av/camera/ICameraService.cpp),而後經過Binder通訊發送CONNECT命令,當BnCameraService收到CONNECT命令後調用CameraService的connect()成員函數來作相應的處理。ide
template <typename TCam, typename TCamTraits> sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, const String16& clientPackageName, int clientUid) { sp<TCam> c = new TCam(cameraId); // BnCameraClient sp<TCamCallbacks> cl = c; status_t status = NO_ERROR; const sp<ICameraService>& cs = getCameraService(); // return BpCameraService if (cs != 0) { TCamConnectService fnConnectService = TCamTraits::fnConnectService; status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); } if (status == OK && c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { ALOGW("An error occurred while connecting to camera: %d", cameraId); c.clear(); } return c; }
下面咱們來分析BpCameraService的connect()成員函數。首先將傳遞過來的Camera對象轉換成IBinder類型,將調用的參數寫到Parcel中,經過BpBinder的transact()函數發送消息,而後由BnCameraService去響應該鏈接,最後就是等待服務端返回,若是成功這裏爲咱們生成一個BpCamera實例。函數
class BpCameraService: public BpInterface<ICameraService> { // connect to camera service (android.hardware.Camera) virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId, const String16 &clientPackageName, int clientUid, /*out*/ sp<ICamera>& device) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder()); data.writeInt32(cameraId); data.writeString16(clientPackageName); data.writeInt32(clientUid); remote()->transact(BnCameraService::CONNECT, data, &reply); // BpBinder的transact()函數向IPCThreadState實例發送消息,通知其有消息要發送給binder driver if (readExceptionCode(reply)) return -EPROTO; status_t status = reply.readInt32(); if (reply.readInt32() != 0) { device = interface_cast<ICamera>(reply.readStrongBinder()); // client端讀出server返回的binder } return status; } }
status_t BnCameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply); sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); // (1) int32_t cameraId = data.readInt32(); const String16 clientName = data.readString16(); int32_t clientUid = data.readInt32(); sp<ICamera> camera; status_t status = connect(cameraClient, cameraId, clientName, clientUid, /*out*/ camera); // (2) reply->writeNoException(); reply->writeInt32(status); if (camera != NULL) { reply->writeInt32(1); reply->writeStrongBinder(camera->asBinder()); // (3) } else { reply->writeInt32(0); } return NO_ERROR; } break; } }
接下來看CameraService::connect()函數,該函數返回一個BpCamera實例。post
status_t CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId, const String16& clientPackageName, int clientUid, /*out*/ sp<ICamera>& device) { String8 clientName8(clientPackageName); int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid, clientName8.string(), cameraId); status_t status = validateConnect(cameraId, /*inout*/clientUid); if (status != OK) { return status; } sp<Client> client; { Mutex::Autolock lock(mServiceLock); sp<BasicClient> clientTmp; if (!canConnectUnsafe(cameraId, clientPackageName, cameraClient->asBinder(), /*out*/clientTmp)) { return -EBUSY; } else if (client.get() != NULL) { device = static_cast<Client*>(clientTmp.get()); return OK; } int facing = -1; int deviceVersion = getDeviceVersion(cameraId, &facing); // If there are other non-exclusive users of the camera, // this will tear them down before we can reuse the camera if (isValidCameraId(cameraId)) { // transition from PRESENT -> NOT_AVAILABLE updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE, cameraId); } /* 根據HAL不一樣API的版本建立不一樣的client實例 */ switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, clientPackageName, cameraId, facing, callingPid, clientUid, getpid()); break; case CAMERA_DEVICE_API_VERSION_2_0: case CAMERA_DEVICE_API_VERSION_2_1: case CAMERA_DEVICE_API_VERSION_3_0: client = new Camera2Client(this, cameraClient, clientPackageName, cameraId, facing, callingPid, clientUid, getpid(), deviceVersion); break; case -1: ALOGE("Invalid camera id %d", cameraId); return BAD_VALUE; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return INVALID_OPERATION; } status_t status = connectFinishUnsafe(client, client->getRemote()); if (status != OK) { // this is probably not recoverable.. maybe the client can try again // OK: we can only get here if we were originally in PRESENT state updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId); return status; } mClient[cameraId] = client; // every camera is a Client class LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); } // important: release the mutex here so the client can call back // into the service from its destructor (can be at the end of the call) device = client; // 返回的camera device實例 return OK; }
至此,一次Framework層的Camera服務請求過程完成。ui