Merge "Removed unnecessary include JNI from two drm Android.mk files"
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 22836e3..dc3f083 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -299,9 +299,14 @@
     LOG1("CameraService::removeClient X (pid %d)", callingPid);
 }
 
-sp<CameraService::Client> CameraService::getClientById(int cameraId) {
+CameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
     if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
-    return mClient[cameraId].promote();
+    return mClient[cameraId].unsafe_get();
+}
+
+Mutex* CameraService::getClientLockById(int cameraId) {
+    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
+    return &mClientLock[cameraId];
 }
 
 status_t CameraService::onTransact(
@@ -408,6 +413,7 @@
     mMsgEnabled = 0;
     mSurface = 0;
     mPreviewWindow = 0;
+    mDestructionStarted = false;
     mHardware->setCallbacks(notifyCallback,
                             dataCallback,
                             dataCallbackTimestamp,
@@ -428,6 +434,12 @@
 
 // tear down the client
 CameraService::Client::~Client() {
+    // this lock should never be NULL
+    Mutex* lock = mCameraService->getClientLockById(mCameraId);
+    lock->lock();
+    mDestructionStarted = true;
+    // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
+    lock->unlock();
     int callingPid = getCallingPid();
     LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
 
@@ -994,16 +1006,22 @@
 
 // ----------------------------------------------------------------------------
 
-// Converts from a raw pointer to the client to a strong pointer during a
-// hardware callback. This requires the callbacks only happen when the client
-// is still alive.
-sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
-    sp<Client> client = gCameraService->getClientById((int) user);
+Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
+    return gCameraService->getClientLockById((int) user);
+}
+
+// Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
+// be acquired for this to be safe
+CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
+    Client* client = gCameraService->getClientByIdUnsafe((int) user);
 
     // This could happen if the Client is in the process of shutting down (the
     // last strong reference is gone, but the destructor hasn't finished
     // stopping the hardware).
-    if (client == 0) return NULL;
+    if (client == NULL) return NULL;
+
+    // destruction already started, so should not be accessed
+    if (client->mDestructionStarted) return NULL;
 
     // The checks below are not necessary and are for debugging only.
     if (client->mCameraService.get() != gCameraService) {
@@ -1046,8 +1064,13 @@
         int32_t ext2, void* user) {
     LOG2("notifyCallback(%d)", msgType);
 
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) return;
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
+
+    Client* client = getClientFromCookie(user);
+    if (client == NULL) return;
+
     if (!client->lockIfMessageWanted(msgType)) return;
 
     switch (msgType) {
@@ -1065,10 +1088,14 @@
         const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
     LOG2("dataCallback(%d)", msgType);
 
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) return;
-    if (!client->lockIfMessageWanted(msgType)) return;
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
 
+    Client* client = getClientFromCookie(user);
+    if (client == NULL) return;
+
+    if (!client->lockIfMessageWanted(msgType)) return;
     if (dataPtr == 0 && metadata == NULL) {
         ALOGE("Null data returned in data callback");
         client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
@@ -1098,8 +1125,13 @@
         int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
     LOG2("dataCallbackTimestamp(%d)", msgType);
 
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) return;
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
+
+    Client* client = getClientFromCookie(user);
+    if (client == NULL) return;
+
     if (!client->lockIfMessageWanted(msgType)) return;
 
     if (dataPtr == 0) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 457c79b..7972201 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -49,7 +49,10 @@
     virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
                                 bool force, bool keep);
     virtual void        removeClient(const sp<ICameraClient>& cameraClient);
-    virtual sp<Client>  getClientById(int cameraId);
+    // returns plain pointer of client. Note that mClientLock should be acquired to
+    // prevent the client from destruction. The result can be NULL.
+    virtual Client*     getClientByIdUnsafe(int cameraId);
+    virtual Mutex*      getClientLockById(int cameraId);
 
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    onTransact(uint32_t code, const Parcel& data,
@@ -69,6 +72,7 @@
 private:
     Mutex               mServiceLock;
     wp<Client>          mClient[MAX_CAMERAS];  // protected by mServiceLock
+    Mutex               mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
     int                 mNumberOfCameras;
 
     // atomics to record whether the hardware is allocated to some client.
@@ -147,8 +151,9 @@
         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);
-        // convert client from cookie
-        static sp<Client>       getClientFromCookie(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,
@@ -204,6 +209,11 @@
         // of the original one), we allocate mPreviewBuffer and reuse it if possible.
         sp<MemoryHeapBase>              mPreviewBuffer;
 
+        // the instance is in the middle of destruction. When this is set,
+        // the instance should not be accessed from callback.
+        // CameraService's mClientLock should be acquired to access this.
+        bool                            mDestructionStarted;
+
         // 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