• Android Camera Client&Service 函数调用关系


    1. JNI

    @frameworks/base/core/jni/android_hardware_Camera.cpp

    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());
    }
    android_hardware_Camera_native_setup()

     Class JNICameraContext 的定义:

    // 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: public CameraListener
    Class JNICameraContext继承了接口类CameraListener(@Camera.h),Class CameraListener定义如下:
    // 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 CameraListener定义了三个纯虚函数,这三个纯虚函数都被Class JNICameraContext继承实现(@android_hardware_Camera.cpp)
    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);
    }
    JNICameraContext::notify
    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);
        }
    }
    JNICameraContext::postData
    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);
    }
    JNICameraContext::postDataTimestamp

    接下来看从JNI到Camera类的调用

    camera->setListener(context);

     

    2Camera&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,

    // 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);
        }
    }
    Callback

    而三个函数是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中被调用,那么,CameraClientservice之间是如何建立联系的?

    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

    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; 
    } 
    interface_cast

    然后在其上调用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(), connectBnCameraService中没有实现,调用子类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端的回调函数,在类CameraServiceClient类中定义一些回调函数都由此实现:

      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);
    }

    由此可以实现从serviceclient的调用

    另外注意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);
        }
    }
  • 相关阅读:
    12月12日学习日志
    12月11日学习日志
    12月10日学习日志
    linux下安装git
    ubuntu上安装mysql
    扩展虚拟机容量
    【linux】你需要以 root 身份执行此命令
    Ubuntu新建Django工程错误:ModuleNotFoundError: No module named 'distutils.core'
    LeetCode26. 删除排序数组中的重复项
    LeetCode27. 移除元素
  • 原文地址:https://www.cnblogs.com/leino11121/p/3153025.html
Copyright © 2020-2023  润新知