Android Camera Client&Service 函数调用关系
2013-06-24 18:36 白居不易 阅读(1988) 评论(0) 编辑 收藏 举报1. JNI
@frameworks/base/core/jni/android_hardware_Camera.cpp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()); }
Class JNICameraContext 的定义:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// provides persistent context for calls from native code to Java class JNICameraContext: public CameraListener { public: JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera); ~JNICameraContext() { release(); } virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata); void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType); void setCallbackMode(JNIEnv *env, bool installed, bool manualMode); sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; } bool isRawImageCallbackBufferAvailable() const; void release(); private: void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType); void clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers); void clearCallbackBuffers_l(JNIEnv *env); jbyteArray getCallbackBuffer(JNIEnv *env, Vector<jbyteArray> *buffers, size_t bufferSize); jobject mCameraJObjectWeak; // weak reference to java object jclass mCameraJClass; // strong reference to java class sp<Camera> mCamera; // strong reference to native object jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class Mutex mLock; /* * Global reference application-managed raw image buffer queue. * * Manual-only mode is supported for raw image callbacks, which is * set whenever method addCallbackBuffer() with msgType = * CAMERA_MSG_RAW_IMAGE is called; otherwise, null is returned * with raw image callbacks. */ Vector<jbyteArray> mRawImageCallbackBuffers; /* * Application-managed preview buffer queue and the flags * associated with the usage of the preview buffer callback. */ Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[] bool mManualBufferMode; // Whether to use application managed buffers. bool mManualCameraCallbackSet; // Whether the callback has been set, used to // reduce unnecessary calls to set the callback. };
Class JNICameraContext继承了接口类CameraListener(@Camera.h),Class CameraListener定义如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// ref-counted object for callbacks class CameraListener: virtual public RefBase { public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) = 0; virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0; };
Class CameraListener定义了三个纯虚函数,这三个纯虚函数都被Class JNICameraContext继承实现(@android_hardware_Camera.cpp)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2) { ALOGV("notify"); // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); if (mCameraJObjectWeak == NULL) { ALOGW("callback on dead camera object"); return; } JNIEnv *env = AndroidRuntime::getJNIEnv(); /* * If the notification or msgType is CAMERA_MSG_RAW_IMAGE_NOTIFY, change it * to CAMERA_MSG_RAW_IMAGE since CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed * to the Java app. */ if (msgType == CAMERA_MSG_RAW_IMAGE_NOTIFY) { msgType = CAMERA_MSG_RAW_IMAGE; } env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, ext1, ext2, NULL); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); JNIEnv *env = AndroidRuntime::getJNIEnv(); if (mCameraJObjectWeak == NULL) { ALOGW("callback on dead camera object"); return; } int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; // return data based on callback type switch (dataMsgType) { case CAMERA_MSG_VIDEO_FRAME: // should never happen break; // For backward-compatibility purpose, if there is no callback // buffer for raw image, the callback returns null. case CAMERA_MSG_RAW_IMAGE: ALOGV("rawCallback"); if (mRawImageCallbackBuffers.isEmpty()) { env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, dataMsgType, 0, 0, NULL); } else { copyAndPost(env, dataPtr, dataMsgType); } break; // There is no data. case 0: break; default: ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get()); copyAndPost(env, dataPtr, dataMsgType); break; } // post frame metadata to Java if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) { postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { // TODO: plumb up to Java. For now, just drop the timestamp postData(msgType, dataPtr, NULL); }
接下来看从JNI到Camera类的调用
camera->setListener(context);
2、Camera&BnCameraClient @frameworks/av/camera/Camera.cpp
void Camera::setListener(const sp<CameraListener>& listener) { Mutex::Autolock _l(mLock); mListener = listener; }
mListener定义在Class Camera中:
class Camera : public BnCameraClient, public IBinder::DeathRecipient { ... private: sp<CameraListener> mListener; …. }
在Camera类中定义了三个回调函数,会用到mListener,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// callback from camera service void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { sp<CameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->notify(msgType, ext1, ext2); } } // callback from camera service when frame or image is ready void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->postData(msgType, dataPtr, metadata); } } // callback from camera service when timestamped frame is ready void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { // If recording proxy listener is registered, forward the frame and return. // The other listener (mListener) is ignored because the receiver needs to // call releaseRecordingFrame. sp<ICameraRecordingProxyListener> proxylistener; { Mutex::Autolock _l(mLock); proxylistener = mRecordingProxyListener; } if (proxylistener != NULL) { proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr); return; } sp<CameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->postDataTimestamp(timestamp, msgType, dataPtr); } else { ALOGW("No listener was set. Drop a recording frame."); releaseRecordingFrame(dataPtr); } }
而三个函数是Camera类继承父类BnCameraClient的函数实现,而BnCameraClient继承接口类BnInterface<ICameraClient>
class Camera : public BnCameraClient, public Ibinder::DeathRecipient { ... }
class ICameraClient: public IInterface { public: DECLARE_META_INTERFACE(CameraClient); virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data, camera_frame_metadata_t *metadata) = 0; virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0; }; // ---------------------------------------------------------------------------- class BnCameraClient: public BnInterface<ICameraClient> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
看一下BnCameraClient::onTransact的实现:
status_t BnCameraClient::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case NOTIFY_CALLBACK: { ALOGV("NOTIFY_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); int32_t ext1 = data.readInt32(); int32_t ext2 = data.readInt32(); notifyCallback(msgType, ext1, ext2); return NO_ERROR; } break; case DATA_CALLBACK: { ALOGV("DATA_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); camera_frame_metadata_t *metadata = NULL; if (data.dataAvail() > 0) { metadata = new camera_frame_metadata_t; metadata->number_of_faces = data.readInt32(); metadata->faces = (camera_face_t *) data.readInplace( sizeof(camera_face_t) * metadata->number_of_faces); } dataCallback(msgType, imageData, metadata); if (metadata) delete metadata; return NO_ERROR; } break; case DATA_CALLBACK_TIMESTAMP: { ALOGV("DATA_CALLBACK_TIMESTAMP"); CHECK_INTERFACE(ICameraClient, data, reply); nsecs_t timestamp = data.readInt64(); int32_t msgType = data.readInt32(); sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); dataCallbackTimestamp(timestamp, msgType, imageData); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
onTransact()函数实现了三种类型的回调。那是谁在调用这些毁掉函数?
3、CameraService&BpCameraClient
先不关心Binder的细节,找一下BpCameraClient类
@frameworks/av/camera/ICameraClient.cpp
class BpCameraClient: public BpInterface<ICameraClient> { public: BpCameraClient(const sp<IBinder>& impl) : BpInterface<ICameraClient>(impl) { } // generic callback from camera service to app void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) { ALOGV("notifyCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeInt32(ext1); data.writeInt32(ext2); remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } // generic data callback from camera service to app with image data void dataCallback(int32_t msgType, const sp<IMemory>& imageData, camera_frame_metadata_t *metadata) { ALOGV("dataCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeStrongBinder(imageData->asBinder()); if (metadata) { data.writeInt32(metadata->number_of_faces); data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces); } remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } // generic data callback from camera service to app with image data void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData) { ALOGV("dataCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt64(timestamp); data.writeInt32(msgType); data.writeStrongBinder(imageData->asBinder()); remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY); } };
这部分是在CameraService中被调用,那么,Camera的Client与service之间是如何建立联系的?
4、Camera<->CameraService
Camera app通过framework中的Camera Java类进入JNI部分,在android_hard_camera.cpp中:
android_hardware_Camera_native_setup() { sp<Camera> camera = Camera::connect(); }
@Camera.cpp
sp<Camera> Camera::connect(int cameraId) { ALOGV("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; }
这里首先New一个Camera对象,
getCameraService()会返回跨进程的ICameraService,
// 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; ALOGW("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); } ALOGE_IF(mCameraService==0, "no CameraService!?"); return mCameraService; }
Service的获取最后再讲;
最重要的,把返回的binder对象经过interface_cast<ICameraService>转换,变成了BpCameraService类型:
@IInterface
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); } sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \ { \ sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \
然后在其上调用connect(ICameraService::connect):
class BpCameraService: public BpInterface<ICameraService> { public: BpCameraService(const sp<IBinder>& impl) : BpInterface<ICameraService>(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<ICamera> connect(const sp<ICameraClient>& 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<ICamera>(reply.readStrongBinder()); } };
这里会向remote发起一个transaction,然后在reply中读取binder,经过interface_cast<ICamera>转换为BpCamera类型。BpCamera是一个非常重要的类型,所有的Camera功能性的调用都是由他过度。
那么BnCameraService::CONNECT的实现是怎样的呢?注意此transaction的参数中有一个是const sp<ICameraClient>& cameraClient,
BnCameraService::onTransact() status_t BnCameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_NUMBER_OF_CAMERAS: { … } break; case GET_CAMERA_INFO: { … } break; case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply); sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); sp<ICamera> camera = connect(cameraClient, data.readInt32()); reply->writeStrongBinder(camera->asBinder()); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
这里从data中得到ICameraClient类型,之后以此为参数调用connect(), connect在BnCameraService中没有实现,调用子类Class CameraService 的connect:
class CameraService : public BinderService<CameraService>, public BnCameraService { virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId); }
sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) { ... client = new Client(this, cameraClient, callingPid); return client; ... }
在new client时将 cameraClient传入:
CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, const sp<CameraHardwareInterface>& hardware, int cameraId, int cameraFacing, int clientPid) { int callingPid = getCallingPid(); LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId); mCameraService = cameraService; mCameraClient = cameraClient; ... }
之后,CameraService就可以通过mCameraClient对象来调用Cameraclient端的回调函数,在类CameraService的Client类中定义一些回调函数都由此实现:
class Client : public BnCamera { // these are static callback functions static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user); static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user); static Mutex* getClientLockFromCookie(void* user); // convert client from cookie. Client lock should be acquired before getting Client. static Client* getClientFromCookie(void* user); // handlers for messages void handleShutter(void); void handlePreviewData(int32_t msgType, const sp<IMemory>& mem, camera_frame_metadata_t *metadata); void handlePostview(const sp<IMemory>& mem); void handleRawPicture(const sp<IMemory>& mem); void handleCompressedPicture(const sp<IMemory>& mem); void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2); void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata); void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void copyFrameAndPostCopiedFrame( int32_t msgType, const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, size_t offset, size_t size, camera_frame_metadata_t *metadata); }
由此可以实现从service到client的调用
另外注意CameraService::connect的返回值
sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) { client = new Client(this, cameraClient, callingPid); return client; }
client 经transaction 的reply返回,而被Client端获取,Client端可由此发起从Client向service的调用。
5、除了Class Camera及Class ICameraClient,还有一个稍不重要的类Class ICameraService。用于建立Camera及ICameraClient。用法与上面的connect()函数类似,
其主要目的是为了通过CameraService获取Camera相关信息,用于建立Client及ICameraClient
@ICameraService
class BpCameraService: public BpInterface<ICameraService> { public: BpCameraService(const sp<IBinder>& impl) : BpInterface<ICameraService>(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<ICamera> connect(const sp<ICameraClient>& 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<ICamera>(reply.readStrongBinder()); } }
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<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); sp<ICamera> camera = connect(cameraClient, data.readInt32()); reply->writeStrongBinder(camera->asBinder()); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }