Loading camera/libcameraservice/Android.mk +22 −13 Original line number Diff line number Diff line LOCAL_PATH:= $(call my-dir) # # Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want # the camera service to use the fake camera. For emulator or simulator builds, # we always use the fake camera. # Set USE_CAMERA_STUB if you want to use the fake camera. # Set USE_CAMERA_HARDWARE if you want to use the hardware camera. # For emulator or simulator builds, we use the fake camera only by default. ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=false ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),) ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=true endif ifeq ($(USE_CAMERA_HARDWARE),) USE_CAMERA_HARDWARE:=false endif else # force USE_CAMERA_STUB for testing temporarily # ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=true endif #libcamerastub # endif ifeq ($(USE_CAMERA_HARDWARE),) USE_CAMERA_HARDWARE:=true endif endif ifeq ($(USE_CAMERA_STUB),true) Loading Loading @@ -54,18 +63,18 @@ LOCAL_SHARED_LIBRARIES:= \ LOCAL_MODULE:= libcameraservice LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\" ifeq ($(TARGET_SIMULATOR),true) LOCAL_CFLAGS += -DSINGLE_PROCESS endif ifeq ($(USE_CAMERA_STUB), true) LOCAL_STATIC_LIBRARIES += libcamerastub LOCAL_CFLAGS += -include CameraHardwareStub.h else LOCAL_CFLAGS += -DUSE_CAMERA_STUB endif ifeq ($(USE_CAMERA_HARDWARE),true) LOCAL_CFLAGS += -DUSE_CAMERA_HARDWARE LOCAL_SHARED_LIBRARIES += libcamera endif include $(BUILD_SHARED_LIBRARY) camera/libcameraservice/CameraHardwareStub.cpp +18 −27 Original line number Diff line number Diff line Loading @@ -47,14 +47,14 @@ void CameraHardwareStub::initDefaultParameters() { CameraParameters p; p.set("preview-size-values","320x240"); p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240"); p.setPreviewSize(320, 240); p.setPreviewFrameRate(15); p.setPreviewFormat("yuv422sp"); p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP); p.set("picture-size-values", "320x240"); p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240"); p.setPictureSize(320, 240); p.setPictureFormat("jpeg"); p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); if (setParameters(p) != NO_ERROR) { LOGE("Failed to set default parameters?!"); Loading @@ -66,14 +66,14 @@ void CameraHardwareStub::initHeapLocked() // Create raw heap. int picture_width, picture_height; mParameters.getPictureSize(&picture_width, &picture_height); mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height); mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2); int preview_width, preview_height; mParameters.getPreviewSize(&preview_width, &preview_height); LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height); // Note that we enforce yuv422 in setParameters(). int how_big = preview_width * preview_height * 2; // Note that we enforce yuv420sp in setParameters(). int how_big = preview_width * preview_height * 3 / 2; // If we are being reinitialized to the same size as before, no // work needs to be done. Loading @@ -99,7 +99,6 @@ CameraHardwareStub::~CameraHardwareStub() { delete mFakeCamera; mFakeCamera = 0; // paranoia singleton.clear(); } sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const Loading Loading @@ -175,7 +174,7 @@ int CameraHardwareStub::previewThread() // Fill the current frame with the fake camera. uint8_t *frame = ((uint8_t *)base) + offset; fakeCamera->getNextFrameAsYuv422(frame); fakeCamera->getNextFrameAsYuv420(frame); //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); Loading Loading @@ -288,9 +287,9 @@ int CameraHardwareStub::pictureThread() // In the meantime just make another fake camera picture. int w, h; mParameters.getPictureSize(&w, &h); sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h); sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2); FakeCamera cam(w, h); cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base()); cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base()); mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie); } Loading @@ -307,7 +306,7 @@ status_t CameraHardwareStub::takePicture() { stopPreview(); if (createThread(beginPictureThread, this) == false) return -1; return UNKNOWN_ERROR; return NO_ERROR; } Loading Loading @@ -339,12 +338,14 @@ status_t CameraHardwareStub::setParameters(const CameraParameters& params) Mutex::Autolock lock(mLock); // XXX verify params if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) { LOGE("Only yuv422sp preview is supported"); if (strcmp(params.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) { LOGE("Only yuv420sp preview is supported"); return -1; } if (strcmp(params.getPictureFormat(), "jpeg") != 0) { if (strcmp(params.getPictureFormat(), CameraParameters::PIXEL_FORMAT_JPEG) != 0) { LOGE("Only jpeg still pictures are supported"); return -1; } Loading Loading @@ -379,22 +380,12 @@ void CameraHardwareStub::release() { } wp<CameraHardwareInterface> CameraHardwareStub::singleton; sp<CameraHardwareInterface> CameraHardwareStub::createInstance() { if (singleton != 0) { sp<CameraHardwareInterface> hardware = singleton.promote(); if (hardware != 0) { return hardware; } } sp<CameraHardwareInterface> hardware(new CameraHardwareStub()); singleton = hardware; return hardware; return new CameraHardwareStub(); } extern "C" sp<CameraHardwareInterface> openCameraHardware() extern "C" sp<CameraHardwareInterface> openCameraHardwareStub() { return CameraHardwareStub::createInstance(); } Loading camera/libcameraservice/CameraHardwareStub.h +2 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,6 @@ private: CameraHardwareStub(); virtual ~CameraHardwareStub(); static wp<CameraHardwareInterface> singleton; static const int kBufferCount = 4; class PreviewThread : public Thread { Loading Loading @@ -130,6 +128,8 @@ private: int mCurrentPreviewFrame; }; extern "C" sp<CameraHardwareInterface> openCameraHardwareStub(); }; // namespace android #endif camera/libcameraservice/CameraService.cpp +824 −956 File changed.Preview size limit exceeded, changes collapsed. Show changes camera/libcameraservice/CameraService.h +109 −145 Original line number Diff line number Diff line Loading @@ -21,207 +21,171 @@ #include <camera/ICameraService.h> #include <camera/CameraHardwareInterface.h> #include <camera/Camera.h> /* This needs to be increased if we can have more cameras */ #define MAX_CAMERAS 2 namespace android { class MemoryHeapBase; class MediaPlayer; // ---------------------------------------------------------------------------- #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) // When enabled, this feature allows you to send an event to the CameraService // so that you can cause all references to the heap object gWeakHeap, defined // below, to be printed. You will also need to set DEBUG_REFS=1 and // DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to // set gWeakHeap to the appropriate heap you want to track. #define DEBUG_HEAP_LEAKS 0 // ---------------------------------------------------------------------------- class CameraService: public BnCameraService { class Client; public: static void instantiate(); // ICameraService interface virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient); CameraService(); virtual ~CameraService(); virtual int32_t getNumberOfCameras(); virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId); virtual void removeClient(const sp<ICameraClient>& cameraClient); virtual sp<Client> getClientById(int cameraId); virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); void removeClient(const sp<ICameraClient>& cameraClient); enum sound_kind { SOUND_SHUTTER = 0, SOUND_RECORDING = 1, NUM_SOUNDS }; virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); void loadSound(); void playSound(sound_kind kind); void releaseSound(); private: Mutex mServiceLock; wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock // ---------------------------------------------------------------------------- // atomics to record whether the hardware is allocated to some client. volatile int32_t mBusy[MAX_CAMERAS]; void setCameraBusy(int cameraId); void setCameraFree(int cameraId); class Client : public BnCamera { // sounds Mutex mSoundLock; sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS]; int mSoundRef; // reference count (release all MediaPlayer when 0) class Client : public BnCamera { public: // ICamera interface (see ICamera for details) virtual void disconnect(); // connect new client with existing camera remote virtual status_t connect(const sp<ICameraClient>& client); // prevent other processes from using this ICamera interface virtual status_t lock(); // allow other processes to use this ICamera interface virtual status_t unlock(); // pass the buffered ISurface to the camera service virtual status_t setPreviewDisplay(const sp<ISurface>& surface); // set the preview callback flag to affect how the received frames from // preview are handled. virtual void setPreviewCallbackFlag(int callback_flag); // start preview mode, must call setPreviewDisplay first virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); // stop preview mode virtual void stopPreview(); // get preview state virtual bool previewEnabled(); // start recording mode virtual status_t startRecording(); // stop recording mode virtual void stopRecording(); // get recording state virtual bool recordingEnabled(); // release a recording frame virtual void releaseRecordingFrame(const sp<IMemory>& mem); // auto focus virtual status_t autoFocus(); // cancel auto focus virtual status_t cancelAutoFocus(); // take a picture - returns an IMemory (ref-counted mmap) virtual status_t takePicture(); // set preview/capture parameters - key/value pairs virtual status_t setParameters(const String8& params); // get preview/capture parameters - key/value pairs virtual String8 getParameters() const; // send command to camera driver virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); // our client... const sp<ICameraClient>& getCameraClient() const { return mCameraClient; } private: friend class CameraService; Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, pid_t clientPid); Client(); virtual ~Client(); int cameraId, int clientPid); ~Client(); status_t checkPid(); // return our camera client const sp<ICameraClient>& getCameraClient() { return mCameraClient; } static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user); static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user); // check whether the calling process matches mClientPid. status_t checkPid() const; status_t checkPidAndHardware() const; // also check mHardware != 0 static sp<Client> getClientFromCookie(void* user); void handlePreviewData(const sp<IMemory>&); void handleShutter(image_rect_type *image); void handlePostview(const sp<IMemory>&); void handleRawPicture(const sp<IMemory>&); void handleCompressedPicture(const sp<IMemory>&); void copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, size_t offset, size_t size); // these are internal functions used to set up preview buffers status_t registerPreviewBuffers(); status_t setOverlay(); // camera operation mode enum camera_mode { CAMERA_PREVIEW_MODE = 0, // frame automatically released CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame() }; // these are internal functions used for preview/recording status_t startCameraMode(camera_mode mode); status_t startPreviewMode(); status_t startRecordingMode(); status_t setOverlay(); status_t registerPreviewBuffers(); // Ensures atomicity among the public methods mutable Mutex mLock; // mSurfaceLock synchronizes access to mSurface between // setPreviewSurface() and postPreviewFrame(). Note that among // the public methods, all accesses to mSurface are // syncrhonized by mLock. However, postPreviewFrame() is called // by the CameraHardwareInterface callback, and needs to // access mSurface. It cannot hold mLock, however, because // stopPreview() may be holding that lock while attempting // to stop preview, and stopPreview itself will block waiting // for a callback from CameraHardwareInterface. If this // happens, it will cause a deadlock. mutable Mutex mSurfaceLock; mutable Condition mReady; sp<CameraService> mCameraService; sp<ISurface> mSurface; int mPreviewCallbackFlag; int mOrientation; sp<MediaPlayer> mMediaPlayerClick; sp<MediaPlayer> mMediaPlayerBeep; // these are immutable once the object is created, // they don't need to be protected by a lock // 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, void* user); static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user); // convert client from cookie static sp<Client> getClientFromCookie(void* user); // handlers for messages void handleShutter(image_rect_type *size); void handlePreviewData(const sp<IMemory>& mem); 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); void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void copyFrameAndPostCopiedFrame( const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, size_t offset, size_t size); // these are initialized in the constructor. sp<CameraService> mCameraService; // immutable after constructor sp<ICameraClient> mCameraClient; sp<CameraHardwareInterface> mHardware; int mCameraId; // immutable after constructor pid_t mClientPid; bool mUseOverlay; sp<CameraHardwareInterface> mHardware; // cleared after disconnect() bool mUseOverlay; // immutable after constructor sp<OverlayRef> mOverlayRef; int mOverlayW; int mOverlayH; int mPreviewCallbackFlag; int mOrientation; mutable Mutex mPreviewLock; sp<MemoryHeapBase> mPreviewBuffer; }; // ---------------------------------------------------------------------------- CameraService(); virtual ~CameraService(); // We use a count for number of clients (shoule only be 0 or 1). volatile int32_t mUsers; virtual void incUsers(); virtual void decUsers(); // Ensures atomicity among the public methods mutable Mutex mLock; sp<ISurface> mSurface; mutable Mutex mServiceLock; wp<Client> mClient; // If the user want us to return a copy of the preview frame (instead // of the original one), we allocate mPreviewBuffer and reuse it if possible. sp<MemoryHeapBase> mPreviewBuffer; #if DEBUG_HEAP_LEAKS wp<IMemoryHeap> gWeakHeap; #endif // We need to avoid the deadlock when the incoming command thread and // the CameraHardwareInterface callback thread both want to grab mLock. // An extra flag is used to tell the callback thread that it should stop // trying to deliver the callback messages if the client is not // interested in it anymore. For example, if the client is calling // stopPreview(), the preview frame messages do not need to be delivered // anymore. // This function takes the same parameter as the enableMsgType() and // disableMsgType() functions in CameraHardwareInterface. void enableMsgType(int32_t msgType); void disableMsgType(int32_t msgType); volatile int32_t mMsgEnabled; // This function keeps trying to grab mLock, or give up if the message // is found to be disabled. It returns true if mLock is grabbed. bool lockIfMessageWanted(int32_t msgType); }; }; // ---------------------------------------------------------------------------- }; // namespace android } // namespace android #endif Loading
camera/libcameraservice/Android.mk +22 −13 Original line number Diff line number Diff line LOCAL_PATH:= $(call my-dir) # # Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want # the camera service to use the fake camera. For emulator or simulator builds, # we always use the fake camera. # Set USE_CAMERA_STUB if you want to use the fake camera. # Set USE_CAMERA_HARDWARE if you want to use the hardware camera. # For emulator or simulator builds, we use the fake camera only by default. ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=false ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),) ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=true endif ifeq ($(USE_CAMERA_HARDWARE),) USE_CAMERA_HARDWARE:=false endif else # force USE_CAMERA_STUB for testing temporarily # ifeq ($(USE_CAMERA_STUB),) USE_CAMERA_STUB:=true endif #libcamerastub # endif ifeq ($(USE_CAMERA_HARDWARE),) USE_CAMERA_HARDWARE:=true endif endif ifeq ($(USE_CAMERA_STUB),true) Loading Loading @@ -54,18 +63,18 @@ LOCAL_SHARED_LIBRARIES:= \ LOCAL_MODULE:= libcameraservice LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\" ifeq ($(TARGET_SIMULATOR),true) LOCAL_CFLAGS += -DSINGLE_PROCESS endif ifeq ($(USE_CAMERA_STUB), true) LOCAL_STATIC_LIBRARIES += libcamerastub LOCAL_CFLAGS += -include CameraHardwareStub.h else LOCAL_CFLAGS += -DUSE_CAMERA_STUB endif ifeq ($(USE_CAMERA_HARDWARE),true) LOCAL_CFLAGS += -DUSE_CAMERA_HARDWARE LOCAL_SHARED_LIBRARIES += libcamera endif include $(BUILD_SHARED_LIBRARY)
camera/libcameraservice/CameraHardwareStub.cpp +18 −27 Original line number Diff line number Diff line Loading @@ -47,14 +47,14 @@ void CameraHardwareStub::initDefaultParameters() { CameraParameters p; p.set("preview-size-values","320x240"); p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240"); p.setPreviewSize(320, 240); p.setPreviewFrameRate(15); p.setPreviewFormat("yuv422sp"); p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP); p.set("picture-size-values", "320x240"); p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240"); p.setPictureSize(320, 240); p.setPictureFormat("jpeg"); p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); if (setParameters(p) != NO_ERROR) { LOGE("Failed to set default parameters?!"); Loading @@ -66,14 +66,14 @@ void CameraHardwareStub::initHeapLocked() // Create raw heap. int picture_width, picture_height; mParameters.getPictureSize(&picture_width, &picture_height); mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height); mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2); int preview_width, preview_height; mParameters.getPreviewSize(&preview_width, &preview_height); LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height); // Note that we enforce yuv422 in setParameters(). int how_big = preview_width * preview_height * 2; // Note that we enforce yuv420sp in setParameters(). int how_big = preview_width * preview_height * 3 / 2; // If we are being reinitialized to the same size as before, no // work needs to be done. Loading @@ -99,7 +99,6 @@ CameraHardwareStub::~CameraHardwareStub() { delete mFakeCamera; mFakeCamera = 0; // paranoia singleton.clear(); } sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const Loading Loading @@ -175,7 +174,7 @@ int CameraHardwareStub::previewThread() // Fill the current frame with the fake camera. uint8_t *frame = ((uint8_t *)base) + offset; fakeCamera->getNextFrameAsYuv422(frame); fakeCamera->getNextFrameAsYuv420(frame); //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); Loading Loading @@ -288,9 +287,9 @@ int CameraHardwareStub::pictureThread() // In the meantime just make another fake camera picture. int w, h; mParameters.getPictureSize(&w, &h); sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h); sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2); FakeCamera cam(w, h); cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base()); cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base()); mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie); } Loading @@ -307,7 +306,7 @@ status_t CameraHardwareStub::takePicture() { stopPreview(); if (createThread(beginPictureThread, this) == false) return -1; return UNKNOWN_ERROR; return NO_ERROR; } Loading Loading @@ -339,12 +338,14 @@ status_t CameraHardwareStub::setParameters(const CameraParameters& params) Mutex::Autolock lock(mLock); // XXX verify params if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) { LOGE("Only yuv422sp preview is supported"); if (strcmp(params.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) { LOGE("Only yuv420sp preview is supported"); return -1; } if (strcmp(params.getPictureFormat(), "jpeg") != 0) { if (strcmp(params.getPictureFormat(), CameraParameters::PIXEL_FORMAT_JPEG) != 0) { LOGE("Only jpeg still pictures are supported"); return -1; } Loading Loading @@ -379,22 +380,12 @@ void CameraHardwareStub::release() { } wp<CameraHardwareInterface> CameraHardwareStub::singleton; sp<CameraHardwareInterface> CameraHardwareStub::createInstance() { if (singleton != 0) { sp<CameraHardwareInterface> hardware = singleton.promote(); if (hardware != 0) { return hardware; } } sp<CameraHardwareInterface> hardware(new CameraHardwareStub()); singleton = hardware; return hardware; return new CameraHardwareStub(); } extern "C" sp<CameraHardwareInterface> openCameraHardware() extern "C" sp<CameraHardwareInterface> openCameraHardwareStub() { return CameraHardwareStub::createInstance(); } Loading
camera/libcameraservice/CameraHardwareStub.h +2 −2 Original line number Diff line number Diff line Loading @@ -67,8 +67,6 @@ private: CameraHardwareStub(); virtual ~CameraHardwareStub(); static wp<CameraHardwareInterface> singleton; static const int kBufferCount = 4; class PreviewThread : public Thread { Loading Loading @@ -130,6 +128,8 @@ private: int mCurrentPreviewFrame; }; extern "C" sp<CameraHardwareInterface> openCameraHardwareStub(); }; // namespace android #endif
camera/libcameraservice/CameraService.cpp +824 −956 File changed.Preview size limit exceeded, changes collapsed. Show changes
camera/libcameraservice/CameraService.h +109 −145 Original line number Diff line number Diff line Loading @@ -21,207 +21,171 @@ #include <camera/ICameraService.h> #include <camera/CameraHardwareInterface.h> #include <camera/Camera.h> /* This needs to be increased if we can have more cameras */ #define MAX_CAMERAS 2 namespace android { class MemoryHeapBase; class MediaPlayer; // ---------------------------------------------------------------------------- #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) // When enabled, this feature allows you to send an event to the CameraService // so that you can cause all references to the heap object gWeakHeap, defined // below, to be printed. You will also need to set DEBUG_REFS=1 and // DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to // set gWeakHeap to the appropriate heap you want to track. #define DEBUG_HEAP_LEAKS 0 // ---------------------------------------------------------------------------- class CameraService: public BnCameraService { class Client; public: static void instantiate(); // ICameraService interface virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient); CameraService(); virtual ~CameraService(); virtual int32_t getNumberOfCameras(); virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId); virtual void removeClient(const sp<ICameraClient>& cameraClient); virtual sp<Client> getClientById(int cameraId); virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); void removeClient(const sp<ICameraClient>& cameraClient); enum sound_kind { SOUND_SHUTTER = 0, SOUND_RECORDING = 1, NUM_SOUNDS }; virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); void loadSound(); void playSound(sound_kind kind); void releaseSound(); private: Mutex mServiceLock; wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock // ---------------------------------------------------------------------------- // atomics to record whether the hardware is allocated to some client. volatile int32_t mBusy[MAX_CAMERAS]; void setCameraBusy(int cameraId); void setCameraFree(int cameraId); class Client : public BnCamera { // sounds Mutex mSoundLock; sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS]; int mSoundRef; // reference count (release all MediaPlayer when 0) class Client : public BnCamera { public: // ICamera interface (see ICamera for details) virtual void disconnect(); // connect new client with existing camera remote virtual status_t connect(const sp<ICameraClient>& client); // prevent other processes from using this ICamera interface virtual status_t lock(); // allow other processes to use this ICamera interface virtual status_t unlock(); // pass the buffered ISurface to the camera service virtual status_t setPreviewDisplay(const sp<ISurface>& surface); // set the preview callback flag to affect how the received frames from // preview are handled. virtual void setPreviewCallbackFlag(int callback_flag); // start preview mode, must call setPreviewDisplay first virtual void setPreviewCallbackFlag(int flag); virtual status_t startPreview(); // stop preview mode virtual void stopPreview(); // get preview state virtual bool previewEnabled(); // start recording mode virtual status_t startRecording(); // stop recording mode virtual void stopRecording(); // get recording state virtual bool recordingEnabled(); // release a recording frame virtual void releaseRecordingFrame(const sp<IMemory>& mem); // auto focus virtual status_t autoFocus(); // cancel auto focus virtual status_t cancelAutoFocus(); // take a picture - returns an IMemory (ref-counted mmap) virtual status_t takePicture(); // set preview/capture parameters - key/value pairs virtual status_t setParameters(const String8& params); // get preview/capture parameters - key/value pairs virtual String8 getParameters() const; // send command to camera driver virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); // our client... const sp<ICameraClient>& getCameraClient() const { return mCameraClient; } private: friend class CameraService; Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, pid_t clientPid); Client(); virtual ~Client(); int cameraId, int clientPid); ~Client(); status_t checkPid(); // return our camera client const sp<ICameraClient>& getCameraClient() { return mCameraClient; } static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user); static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user); static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user); // check whether the calling process matches mClientPid. status_t checkPid() const; status_t checkPidAndHardware() const; // also check mHardware != 0 static sp<Client> getClientFromCookie(void* user); void handlePreviewData(const sp<IMemory>&); void handleShutter(image_rect_type *image); void handlePostview(const sp<IMemory>&); void handleRawPicture(const sp<IMemory>&); void handleCompressedPicture(const sp<IMemory>&); void copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, size_t offset, size_t size); // these are internal functions used to set up preview buffers status_t registerPreviewBuffers(); status_t setOverlay(); // camera operation mode enum camera_mode { CAMERA_PREVIEW_MODE = 0, // frame automatically released CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame() }; // these are internal functions used for preview/recording status_t startCameraMode(camera_mode mode); status_t startPreviewMode(); status_t startRecordingMode(); status_t setOverlay(); status_t registerPreviewBuffers(); // Ensures atomicity among the public methods mutable Mutex mLock; // mSurfaceLock synchronizes access to mSurface between // setPreviewSurface() and postPreviewFrame(). Note that among // the public methods, all accesses to mSurface are // syncrhonized by mLock. However, postPreviewFrame() is called // by the CameraHardwareInterface callback, and needs to // access mSurface. It cannot hold mLock, however, because // stopPreview() may be holding that lock while attempting // to stop preview, and stopPreview itself will block waiting // for a callback from CameraHardwareInterface. If this // happens, it will cause a deadlock. mutable Mutex mSurfaceLock; mutable Condition mReady; sp<CameraService> mCameraService; sp<ISurface> mSurface; int mPreviewCallbackFlag; int mOrientation; sp<MediaPlayer> mMediaPlayerClick; sp<MediaPlayer> mMediaPlayerBeep; // these are immutable once the object is created, // they don't need to be protected by a lock // 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, void* user); static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user); // convert client from cookie static sp<Client> getClientFromCookie(void* user); // handlers for messages void handleShutter(image_rect_type *size); void handlePreviewData(const sp<IMemory>& mem); 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); void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); void copyFrameAndPostCopiedFrame( const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap, size_t offset, size_t size); // these are initialized in the constructor. sp<CameraService> mCameraService; // immutable after constructor sp<ICameraClient> mCameraClient; sp<CameraHardwareInterface> mHardware; int mCameraId; // immutable after constructor pid_t mClientPid; bool mUseOverlay; sp<CameraHardwareInterface> mHardware; // cleared after disconnect() bool mUseOverlay; // immutable after constructor sp<OverlayRef> mOverlayRef; int mOverlayW; int mOverlayH; int mPreviewCallbackFlag; int mOrientation; mutable Mutex mPreviewLock; sp<MemoryHeapBase> mPreviewBuffer; }; // ---------------------------------------------------------------------------- CameraService(); virtual ~CameraService(); // We use a count for number of clients (shoule only be 0 or 1). volatile int32_t mUsers; virtual void incUsers(); virtual void decUsers(); // Ensures atomicity among the public methods mutable Mutex mLock; sp<ISurface> mSurface; mutable Mutex mServiceLock; wp<Client> mClient; // If the user want us to return a copy of the preview frame (instead // of the original one), we allocate mPreviewBuffer and reuse it if possible. sp<MemoryHeapBase> mPreviewBuffer; #if DEBUG_HEAP_LEAKS wp<IMemoryHeap> gWeakHeap; #endif // We need to avoid the deadlock when the incoming command thread and // the CameraHardwareInterface callback thread both want to grab mLock. // An extra flag is used to tell the callback thread that it should stop // trying to deliver the callback messages if the client is not // interested in it anymore. For example, if the client is calling // stopPreview(), the preview frame messages do not need to be delivered // anymore. // This function takes the same parameter as the enableMsgType() and // disableMsgType() functions in CameraHardwareInterface. void enableMsgType(int32_t msgType); void disableMsgType(int32_t msgType); volatile int32_t mMsgEnabled; // This function keeps trying to grab mLock, or give up if the message // is found to be disabled. It returns true if mLock is grabbed. bool lockIfMessageWanted(int32_t msgType); }; }; // ---------------------------------------------------------------------------- }; // namespace android } // namespace android #endif