Merge "Turn off debug in downmix effect"
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index b81fe86..d43cb0b 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -116,13 +116,13 @@
     return cs->getCameraInfo(cameraId, cameraInfo);
 }
 
-sp<Camera> Camera::connect(int cameraId, bool force, bool keep)
+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, force, keep);
+        c->mCamera = cs->connect(c, cameraId);
     }
     if (c->mCamera != 0) {
         c->mCamera->asBinder()->linkToDeath(c);
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index c74298a..f2d367e 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -56,15 +56,12 @@
     }
 
     // connect to camera service
-    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
-                                bool force, bool keep)
+    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeStrongBinder(cameraClient->asBinder());
         data.writeInt32(cameraId);
-        data.writeInt32(force);
-        data.writeInt32(keep);
         remote()->transact(BnCameraService::CONNECT, data, &reply);
         return interface_cast<ICamera>(reply.readStrongBinder());
     }
@@ -96,10 +93,7 @@
         case CONNECT: {
             CHECK_INTERFACE(ICameraService, data, reply);
             sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
-            const int cameraId = data.readInt32();
-            const int force = data.readInt32();
-            const int keep = data.readInt32();
-            sp<ICamera> camera = connect(cameraClient, cameraId, force, keep);
+            sp<ICamera> camera = connect(cameraClient, data.readInt32());
             reply->writeStrongBinder(camera->asBinder());
             return NO_ERROR;
         } break;
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 3fedea0..234e165 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -72,7 +72,7 @@
     static  int32_t     getNumberOfCameras();
     static  status_t    getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo);
-    static  sp<Camera>  connect(int cameraId, bool force, bool keep);
+    static  sp<Camera>  connect(int cameraId);
             virtual     ~Camera();
             void        init();
 
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 97e3169..7d70c1e 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -42,7 +42,7 @@
     virtual status_t        getCameraInfo(int cameraId,
                                           struct CameraInfo* cameraInfo) = 0;
     virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient,
-                                    int cameraId, bool force, bool keep) = 0;
+                                    int cameraId) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 02dfc1b..05d834d 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -402,6 +402,15 @@
      int32_t                 mId;                // system wide unique effect engine instance ID
      Mutex                   mLock;               // Mutex for mEnabled access
 
+     // IEffectClient
+     virtual void controlStatusChanged(bool controlGranted);
+     virtual void enableStatusChanged(bool enabled);
+     virtual void commandExecuted(uint32_t cmdCode,
+             uint32_t cmdSize,
+             void *pCmdData,
+             uint32_t replySize,
+             void *pReplyData);
+
 private:
 
      // Implements the IEffectClient interface
@@ -433,20 +442,8 @@
         AudioEffect *mEffect;
     };
 
-
-    friend class EffectClient;
-
-    // IEffectClient
-    void controlStatusChanged(bool controlGranted);
-    void enableStatusChanged(bool enabled);
-    void commandExecuted(uint32_t cmdCode,
-                         uint32_t cmdSize,
-                         void *pCmdData,
-                         uint32_t replySize,
-                         void *pReplyData);
     void binderDied();
 
-
     sp<IEffect>             mIEffect;           // IEffect binder interface
     sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
     sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index 60fa15b..fdec5ee 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -108,6 +108,12 @@
     // returns the sampling rate of the audio being captured
     uint32_t getSamplingRate() { return mSampleRate; }
 
+    // set the way volume affects the captured data
+    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
+    //  VISUALIZER_SCALING_MODE_AS_PLAYED
+    status_t setScalingMode(uint32_t mode);
+    uint32_t getScalingMode() { return mScalingMode; }
+
     // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
     // getCaptureSize()
     status_t getWaveForm(uint8_t *waveform);
@@ -117,6 +123,10 @@
     // are returned
     status_t getFft(uint8_t *fft);
 
+protected:
+    // from IEffectClient
+    virtual void controlStatusChanged(bool controlGranted);
+
 private:
 
     static const uint32_t CAPTURE_RATE_MAX = 20000;
@@ -147,6 +157,7 @@
     uint32_t mCaptureRate;
     uint32_t mCaptureSize;
     uint32_t mSampleRate;
+    uint32_t mScalingMode;
     capture_cbk_t mCaptureCallBack;
     void *mCaptureCbkUser;
     sp<CaptureThread> mCaptureThread;
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index bdb1a1c..44d05cd 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Visualizer"
+#define LOG_TAG "EffectVisualizer"
 //#define LOG_NDEBUG 0
 #include <cutils/log.h>
 #include <assert.h>
@@ -57,6 +57,7 @@
     effect_config_t mConfig;
     uint32_t mCaptureIdx;
     uint32_t mCaptureSize;
+    uint32_t mScalingMode;
     uint8_t mState;
     uint8_t mCurrentBuf;
     uint8_t mLastBuf;
@@ -164,6 +165,7 @@
     pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
 
     pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
+    pContext->mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED;
 
     Visualizer_setConfig(pContext, &pContext->mConfig);
 
@@ -285,26 +287,32 @@
     }
 
     // all code below assumes stereo 16 bit PCM output and input
+    int32_t shift;
 
-    // derive capture scaling factor from peak value in current buffer
-    // this gives more interesting captures for display.
-    int32_t shift = 32;
-    int len = inBuffer->frameCount * 2;
-    for (int i = 0; i < len; i++) {
-        int32_t smp = inBuffer->s16[i];
-        if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
-        int32_t clz = __builtin_clz(smp);
-        if (shift > clz) shift = clz;
+    if (pContext->mScalingMode == VISUALIZER_SCALING_MODE_NORMALIZED) {
+        // derive capture scaling factor from peak value in current buffer
+        // this gives more interesting captures for display.
+        shift = 32;
+        int len = inBuffer->frameCount * 2;
+        for (int i = 0; i < len; i++) {
+            int32_t smp = inBuffer->s16[i];
+            if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
+            int32_t clz = __builtin_clz(smp);
+            if (shift > clz) shift = clz;
+        }
+        // A maximum amplitude signal will have 17 leading zeros, which we want to
+        // translate to a shift of 8 (for converting 16 bit to 8 bit)
+        shift = 25 - shift;
+        // Never scale by less than 8 to avoid returning unaltered PCM signal.
+        if (shift < 3) {
+            shift = 3;
+        }
+        // add one to combine the division by 2 needed after summing left and right channels below
+        shift++;
+    } else {
+        assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED);
+        shift = 9;
     }
-    // A maximum amplitude signal will have 17 leading zeros, which we want to
-    // translate to a shift of 8 (for converting 16 bit to 8 bit)
-     shift = 25 - shift;
-    // Never scale by less than 8 to avoid returning unaltered PCM signal.
-    if (shift < 3) {
-        shift = 3;
-    }
-    // add one to combine the division by 2 needed after summing left and right channels below
-    shift++;
 
     uint32_t captIdx;
     uint32_t inIdx;
@@ -414,15 +422,26 @@
         effect_param_t *p = (effect_param_t *)pReplyData;
         p->status = 0;
         *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
-        if (p->psize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
+        if (p->psize != sizeof(uint32_t)) {
             p->status = -EINVAL;
             break;
         }
-        ALOGV("get mCaptureSize = %d", pContext->mCaptureSize);
-        *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
-        p->vsize = sizeof(uint32_t);
-        *replySize += sizeof(uint32_t);
+        switch (*(uint32_t *)p->data) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE:
+            ALOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+            *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
+            p->vsize = sizeof(uint32_t);
+            *replySize += sizeof(uint32_t);
+            break;
+        case VISUALIZER_PARAM_SCALING_MODE:
+            ALOGV("get mScalingMode = %d", pContext->mScalingMode);
+            *((uint32_t *)p->data + 1) = pContext->mScalingMode;
+            p->vsize = sizeof(uint32_t);
+            *replySize += sizeof(uint32_t);
+            break;
+        default:
+            p->status = -EINVAL;
+        }
         } break;
     case EFFECT_CMD_SET_PARAM: {
         if (pCmdData == NULL ||
@@ -432,14 +451,22 @@
         }
         *(int32_t *)pReplyData = 0;
         effect_param_t *p = (effect_param_t *)pCmdData;
-        if (p->psize != sizeof(uint32_t) ||
-            p->vsize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
+        if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t)) {
             *(int32_t *)pReplyData = -EINVAL;
-            break;;
+            break;
         }
-        pContext->mCaptureSize = *((uint32_t *)p->data + 1);
-        ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+        switch (*(uint32_t *)p->data) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE:
+            pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+            ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+            break;
+        case VISUALIZER_PARAM_SCALING_MODE:
+            pContext->mScalingMode = *((uint32_t *)p->data + 1);
+            ALOGV("set mScalingMode = %d", pContext->mScalingMode);
+            break;
+        default:
+            *(int32_t *)pReplyData = -EINVAL;
+        }
         } break;
     case EFFECT_CMD_SET_DEVICE:
     case EFFECT_CMD_SET_VOLUME:
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index bcd6ae4..de0bf7d 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -41,6 +41,7 @@
         mCaptureRate(CAPTURE_RATE_DEF),
         mCaptureSize(CAPTURE_SIZE_DEF),
         mSampleRate(44100000),
+        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
         mCaptureCallBack(NULL),
         mCaptureCbkUser(NULL)
 {
@@ -146,9 +147,38 @@
 
     if (status == NO_ERROR) {
         status = p->status;
+        if (status == NO_ERROR) {
+            mCaptureSize = size;
+        }
     }
+
+    return status;
+}
+
+status_t Visualizer::setScalingMode(uint32_t mode) {
+    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
+            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCaptureLock);
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
+    *((int32_t *)p->data + 1)= mode;
+    status_t status = setParameter(p);
+
+    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
+
     if (status == NO_ERROR) {
-        mCaptureSize = size;
+        status = p->status;
+        if (status == NO_ERROR) {
+            mScalingMode = mode;
+        }
     }
 
     return status;
@@ -289,6 +319,19 @@
     return size;
 }
 
+void Visualizer::controlStatusChanged(bool controlGranted) {
+    if (controlGranted) {
+        // this Visualizer instance regained control of the effect, reset the scaling mode
+        //   and capture size as has been cached through it.
+        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
+        ALOGV("    scaling mode reset to %d", mScalingMode);
+        setScalingMode(mScalingMode);
+        ALOGV("    capture size reset to %d", mCaptureSize);
+        setCaptureSize(mCaptureSize);
+    }
+    AudioEffect::controlStatusChanged(controlGranted);
+}
+
 //-------------------------------------------------------------------------
 
 Visualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava)
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index fd3f892..3ddad93 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -182,7 +182,7 @@
     int32_t cameraId) {
 
     if (camera == 0) {
-        mCamera = Camera::connect(cameraId, false, false);
+        mCamera = Camera::connect(cameraId);
         if (mCamera == 0) return -EBUSY;
         mCameraFlags &= ~FLAGS_HOT_CAMERA;
     } else {
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 5b3d216..2808745 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -12,7 +12,8 @@
           frameworks/av/media/libstagefright/include \
           frameworks/native/include/media/openmax \
           external/aac/libAACdec/include \
-          external/aac/libCDK/include \
+          external/aac/libPCMutils/include \
+          external/aac/libFDK/include \
           external/aac/libMpegTPDec/include \
           external/aac/libSBRdec/include \
           external/aac/libSYS/include
@@ -20,7 +21,7 @@
   LOCAL_CFLAGS :=
 
   LOCAL_STATIC_LIBRARIES := \
-          libAACdec libMpegTPDec libSBRdec libCDK libSYS
+          libAACdec libMpegTPDec libSBRdec libPCMutils libFDK libSYS
 
   LOCAL_SHARED_LIBRARIES := \
           libstagefright_omx libstagefright_foundation libutils
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 4589d37..27cf5b9 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -26,23 +26,6 @@
 
 namespace android {
 
-static Mutex gAACLibraryLock;
-static int gAACLibraryCount = 0;
-
-void initializeAACLibrary() {
-  Mutex::Autolock autoLock(gAACLibraryLock);
-  if (gAACLibraryCount++ == 0) {
-    CDKprolog();
-  }
-}
-
-void cleanupAACLibrary() {
-  Mutex::Autolock autoLock(gAACLibraryLock);
-  if (--gAACLibraryCount == 0) {
-    CDKepilog();
-  }
-}
-
 template<class T>
 static void InitOMXParams(T *params) {
     params->nSize = sizeof(T);
@@ -63,17 +46,16 @@
       mIsADTS(false),
       mInputBufferCount(0),
       mSignalledError(false),
+      mInputDiscontinuity(false),
       mAnchorTimeUs(0),
       mNumSamplesOutput(0),
       mOutputPortSettingsChange(NONE) {
-    initializeAACLibrary();
     initPorts();
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
 SoftAAC2::~SoftAAC2() {
     aacDecoder_Close(mAACDecoder);
-    cleanupAACLibrary();
 }
 
 void SoftAAC2::initPorts() {
@@ -102,7 +84,7 @@
     def.eDir = OMX_DirOutput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = 8192;
+    def.nBufferSize = 8192 * 2;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -183,6 +165,10 @@
             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
+            pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
+            pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
+            pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
 
             if (!isConfigured()) {
                 pcmParams->nChannels = 1;
@@ -360,15 +346,17 @@
         INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
         bytesValid[0] = inBufferLength[0];
 
+        int flags = mInputDiscontinuity ? AACDEC_INTR : 0;
         int prevSampleRate = mStreamInfo->sampleRate;
         decoderErr = aacDecoder_Fill(mAACDecoder,
-                                      inBuffer,
-                                      inBufferLength,
-                                      bytesValid);
+                                     inBuffer,
+                                     inBufferLength,
+                                     bytesValid);
         decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
                                             outBuffer,
                                             outHeader->nAllocLen,
-                                            /* flags */ 0);
+                                            flags);
+        mInputDiscontinuity = false;
 
         /*
          * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
@@ -447,13 +435,9 @@
 
 void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
     if (portIndex == 0) {
-
         // Make sure that the next buffer output does not still
         // depend on fragments from the last one decoded.
-        aacDecoder_DecodeFrame(mAACDecoder,
-                               NULL,
-                               0,
-                               AACDEC_FLUSH);
+        mInputDiscontinuity = true;
     }
 }
 
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index 828b34e..d93685c 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -52,6 +52,7 @@
     bool mIsADTS;
     size_t mInputBufferCount;
     bool mSignalledError;
+    bool mInputDiscontinuity;
     int64_t mAnchorTimeUs;
     int64_t mNumSamplesOutput;
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index dc3f083..92d1223 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -21,7 +21,6 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <pthread.h>
-#include <time.h>
 
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
@@ -34,7 +33,6 @@
 #include <hardware/hardware.h>
 #include <media/AudioSystem.h>
 #include <media/mediaplayer.h>
-#include <utils/Condition.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
@@ -44,8 +42,6 @@
 
 namespace android {
 
-#define WAIT_RELEASE_TIMEOUT 250 // 250ms
-
 // ----------------------------------------------------------------------------
 // Logging support -- this is for debugging only
 // Use "adb shell dumpsys media.camera -v 1" to change it.
@@ -68,13 +64,6 @@
     return IPCThreadState::self()->getCallingUid();
 }
 
-static long long getTimeInMs() {
-    struct timeval t;
-    t.tv_sec = t.tv_usec = 0;
-    gettimeofday(&t, NULL);
-    return t.tv_sec * 1000LL + t.tv_usec / 1000;
-}
-
 // ----------------------------------------------------------------------------
 
 // This is ugly and only safe if we never re-create the CameraService, but
@@ -142,7 +131,7 @@
 }
 
 sp<ICamera> CameraService::connect(
-        const sp<ICameraClient>& cameraClient, int cameraId, bool force, bool keep) {
+        const sp<ICameraClient>& cameraClient, int cameraId) {
     int callingPid = getCallingPid();
     sp<CameraHardwareInterface> hardware = NULL;
 
@@ -168,73 +157,27 @@
         return NULL;
     }
 
-    if (keep && !checkCallingPermission(String16("android.permission.KEEP_CAMERA"))) {
-        ALOGE("connect X (pid %d) rejected (no KEEP_CAMERA permission).", callingPid);
-        return NULL;
-    }
-
     Mutex::Autolock lock(mServiceLock);
-    // Check if there is an existing client.
-    client = mClient[cameraId].promote();
-    if (client != 0 &&
-            cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
-        LOG1("connect X (pid %d) (the same client)", callingPid);
-        return client;
-    }
-
-    if (!force) {
-        if (mClient[cameraId].promote() != 0) {
-            ALOGW("connect X (pid %d) rejected (existing client).", callingPid);
-            return NULL;
-        }
-        mClient[cameraId].clear();
-        if (mBusy[cameraId]) {
-            ALOGW("connect X (pid %d) rejected (camera %d is still busy).",
-                  callingPid, cameraId);
-            return NULL;
-        }
-    } else { // force == true
-        int i = 0;
-        long long start_time = getTimeInMs();
-        while (i < mNumberOfCameras) {
-            if (getTimeInMs() - start_time >= 3000LL) {
-                ALOGE("connect X (pid %d) rejected (timeout 3s)", callingPid);
+    if (mClient[cameraId] != 0) {
+        client = mClient[cameraId].promote();
+        if (client != 0) {
+            if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+                LOG1("CameraService::connect X (pid %d) (the same client)",
+                     callingPid);
+                return client;
+            } else {
+                ALOGW("CameraService::connect X (pid %d) rejected (existing client).",
+                      callingPid);
                 return NULL;
             }
-
-            client = mClient[i].promote();
-            if (client != 0) {
-                if (client->keep()) {
-                    ALOGW("connect X (pid %d) rejected (existing client wants to keeps the camera)",
-                          callingPid);
-                    return NULL;
-                } else {
-                    ALOGW("New client (pid %d, id=%d). Disconnect the existing client (id=%d).",
-                         callingPid, cameraId, i);
-                    // Do not hold mServiceLock because disconnect will try to get it.
-                    mServiceLock.unlock();
-                    client->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0, &i);
-                    client->waitRelease(WAIT_RELEASE_TIMEOUT);
-                    client->disconnectInternal(false);
-                    mServiceLock.lock();
-                    // Restart from the first client because a new client may have connected
-                    // when mServiceLock is unlocked.
-                    i = 0;
-                    continue;
-                }
-            }
-
-            if (mBusy[i]) {
-                // Give the client a chance to release the hardware.
-                mServiceLock.unlock();
-                usleep(10 * 1000);
-                mServiceLock.lock();
-                i = 0; // Restart from the first client
-                continue;
-            }
-
-            i++;
         }
+        mClient[cameraId].clear();
+    }
+
+    if (mBusy[cameraId]) {
+        ALOGW("CameraService::connect X (pid %d) rejected"
+                " (camera %d is still busy).", callingPid, cameraId);
+        return NULL;
     }
 
     struct camera_info info;
@@ -252,13 +195,7 @@
         return NULL;
     }
 
-    client = new Client(this, cameraClient, hardware, cameraId, info.facing,
-                        callingPid, keep);
-    // We need to clear the hardware here. After the destructor of mServiceLock
-    // finishes, a new client may connect and disconnect this client. If this
-    // reference is not cleared, the destructor of CameraHardwareInterface
-    // cannot run. The new client will not be able to connect.
-    hardware.clear();
+    client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid);
     mClient[cameraId] = client;
     LOG1("CameraService::connect X (id %d)", cameraId);
     return client;
@@ -399,7 +336,7 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
         const sp<CameraHardwareInterface>& hardware,
-        int cameraId, int cameraFacing, int clientPid, bool keep) {
+        int cameraId, int cameraFacing, int clientPid) {
     int callingPid = getCallingPid();
     LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
 
@@ -409,7 +346,6 @@
     mCameraId = cameraId;
     mCameraFacing = cameraFacing;
     mClientPid = clientPid;
-    mKeep = keep;
     mMsgEnabled = 0;
     mSurface = 0;
     mPreviewWindow = 0;
@@ -544,24 +480,18 @@
 }
 
 void CameraService::Client::disconnect() {
-    disconnectInternal(true);
-}
-
-void CameraService::Client::disconnectInternal(bool needCheckPid) {
     int callingPid = getCallingPid();
-    LOG1("disconnectInternal E (pid %d)", callingPid);
+    LOG1("disconnect E (pid %d)", callingPid);
     Mutex::Autolock lock(mLock);
 
-    if (needCheckPid) {
-        if (checkPid() != NO_ERROR) {
-            ALOGW("different client - don't disconnect");
-            return;
-        }
+    if (checkPid() != NO_ERROR) {
+        ALOGW("different client - don't disconnect");
+        return;
+    }
 
-        if (mClientPid <= 0) {
-            LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
-            return;
-        }
+    if (mClientPid <= 0) {
+        LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
+        return;
     }
 
     // Make sure disconnect() is done once and once only, whether it is called
@@ -588,16 +518,8 @@
 
     mCameraService->removeClient(mCameraClient);
     mCameraService->setCameraFree(mCameraId);
-    mReleaseCondition.signal();
 
-    LOG1("disconnectInternal X (pid %d)", callingPid);
-}
-
-void CameraService::Client::waitRelease(int ms) {
-    Mutex::Autolock lock(mLock);
-    if (mHardware != 0) {
-        mReleaseCondition.waitRelative(mLock, ms * 1000000);
-    }
+    LOG1("disconnect X (pid %d)", callingPid);
 }
 
 // ----------------------------------------------------------------------------
@@ -1330,11 +1252,6 @@
     return -1;
 }
 
-// Whether the client wants to keep the camera from taking
-bool CameraService::Client::keep() const {
-    return mKeep;
-}
-
 // ----------------------------------------------------------------------------
 
 static const int kDumpLockRetries = 50;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7972201..5b63399 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -46,8 +46,7 @@
     virtual int32_t     getNumberOfCameras();
     virtual status_t    getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo);
-    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
-                                bool force, bool keep);
+    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
     virtual void        removeClient(const sp<ICameraClient>& cameraClient);
     // returns plain pointer of client. Note that mClientLock should be acquired to
     // prevent the client from destruction. The result can be NULL.
@@ -119,8 +118,7 @@
                                        const sp<CameraHardwareInterface>& hardware,
                                        int cameraId,
                                        int cameraFacing,
-                                       int clientPid,
-                                       bool keep);
+                                       int clientPid);
                                 ~Client();
 
         // return our camera client
@@ -179,19 +177,12 @@
                                     const sp<IBinder>& binder,
                                     const sp<ANativeWindow>& window);
 
-        void                    disconnectInternal(bool needCheckPid);
-        bool                    keep() const;
-        void                    waitRelease(int ms);
-
-
         // these are initialized in the constructor.
         sp<CameraService>               mCameraService;  // immutable after constructor
         sp<ICameraClient>               mCameraClient;
         int                             mCameraId;       // immutable after constructor
         int                             mCameraFacing;   // immutable after constructor
         pid_t                           mClientPid;
-        // Client wants to keep the camera from taking by other clients.
-        bool                            mKeep;
         sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()
         int                             mPreviewCallbackFlag;
         int                             mOrientation;     // Current display orientation
@@ -199,8 +190,6 @@
 
         // Ensures atomicity among the public methods
         mutable Mutex                   mLock;
-        // This will get notified when the hardware is released.
-        Condition                       mReleaseCondition;
         // This is a binder of Surface or SurfaceTexture.
         sp<IBinder>                     mSurface;
         sp<ANativeWindow>               mPreviewWindow;