Merge "Whitelist getTimestamp from integer sanitization"
am: 51cd9a441e

* commit '51cd9a441ed0acf6e3b9c221e9b7f9424073191f':
  Whitelist getTimestamp from integer sanitization
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index c10963d..cdfa159 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -176,7 +176,7 @@
 
 private:
     // used by ResourceManagerClient
-    status_t reclaim();
+    status_t reclaim(bool force = false);
     friend struct ResourceManagerClient;
 
 private:
@@ -385,6 +385,9 @@
     uint64_t getGraphicBufferSize();
     void addResource(const String8 &type, const String8 &subtype, uint64_t value);
 
+    bool hasPendingBuffer(int portIndex);
+    bool hasPendingBuffer();
+
     /* called to get the last codec error when the sticky flag is set.
      * if no such codec error is found, returns UNKNOWN_ERROR.
      */
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 3aaa032..bf4db87 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -47,6 +47,10 @@
     virtual size_t countCodecs() const;
 
     virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const {
+        if (index >= mCodecInfos.size()) {
+            ALOGE("b/24445127");
+            return NULL;
+        }
         return mCodecInfos.itemAt(index);
     }
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7380418..82b6736 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1852,7 +1852,11 @@
         case NO_ERROR:
         case DEAD_OBJECT:
         case TIMED_OUT:
-            mCbf(EVENT_STREAM_END, mUserData, NULL);
+            if (status != DEAD_OBJECT) {
+                // for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
+                // instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
+                mCbf(EVENT_STREAM_END, mUserData, NULL);
+            }
             {
                 AutoMutex lock(mLock);
                 // The previously assigned value of waitStreamEnd is no longer valid,
@@ -1976,7 +1980,8 @@
         if (err != NO_ERROR) {
             if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR ||
                     (isOffloaded() && (err == DEAD_OBJECT))) {
-                return 0;
+                // FIXME bug 25195759
+                return 1000000;
             }
             ALOGE("Error %d obtaining an audio buffer, giving up.", err);
             return NS_NEVER;
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 5e45c85..666b747 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -933,7 +933,7 @@
     return (ssize_t) mState.mPosition;
 }
 
-status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused)
+status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
 {
     if (mIsShutdown) {
         buffer->mFrameCount = 0;
@@ -971,7 +971,9 @@
     // it is always larger or equal to avail.
     LOG_ALWAYS_FATAL_IF(mFramesReady < (int64_t) avail);
     buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail);
-    mUnreleased = avail;
+    if (!ackFlush) {
+        mUnreleased = avail;
+    }
     return NO_ERROR;
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index b3eb5fd..45da218 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -474,6 +474,8 @@
             {
                 Mutex::Autolock _l(mDisconnectLock);
                 mDataSource.clear();
+                mDecryptHandle = NULL;
+                mDrmManagerClient = NULL;
                 mCachedSource.clear();
                 mHttpSource.clear();
             }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index eee7cf8..b1eb696 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1076,6 +1076,12 @@
                 int32_t audio;
                 CHECK(msg->findInt32("audio", &audio));
 
+                if (audio) {
+                    mAudioEOS = false;
+                } else {
+                    mVideoEOS = false;
+                }
+
                 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
                 if (audio && (mFlushingAudio == NONE || mFlushingAudio == FLUSHED
                         || mFlushingAudio == SHUT_DOWN)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 3646828..c005f3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -635,8 +635,11 @@
             flags = AUDIO_OUTPUT_FLAG_NONE;
         }
 
-        mRenderer->openAudioSink(
+        status_t err = mRenderer->openAudioSink(
                 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
+        if (err != OK) {
+            handleError(err);
+        }
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 6419be0..f288c36 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -362,9 +362,9 @@
 }
 
 status_t NuPlayerDriver::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    Mutex::Autolock autoLock(mLock);
     status_t err = mPlayer->setPlaybackSettings(rate);
     if (err == OK) {
+        Mutex::Autolock autoLock(mLock);
         if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
             mState = STATE_PAUSED;
             // try to update position
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 776dba8..4d25294 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -111,6 +111,7 @@
       mVideoRenderingStarted(false),
       mVideoRenderingStartGeneration(0),
       mAudioRenderingStartGeneration(0),
+      mRenderingDataDelivered(false),
       mAudioOffloadPauseTimeoutGeneration(0),
       mAudioTornDown(false),
       mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
@@ -648,11 +649,16 @@
 void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
     mAudioRenderingStartGeneration = mAudioDrainGeneration;
     mVideoRenderingStartGeneration = mVideoDrainGeneration;
+    mRenderingDataDelivered = false;
 }
 
 void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
     if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
         mAudioRenderingStartGeneration == mAudioDrainGeneration) {
+        mRenderingDataDelivered = true;
+        if (mPaused) {
+            return;
+        }
         mVideoRenderingStartGeneration = -1;
         mAudioRenderingStartGeneration = -1;
 
@@ -910,6 +916,13 @@
 
         {
             Mutex::Autolock autoLock(mLock);
+            int64_t maxTimeMedia;
+            maxTimeMedia =
+                mAnchorTimeMediaUs +
+                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
+                                * 1000LL * mAudioSink->msecsPerFrame());
+            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
+
             notifyIfMediaRenderingStarted_l();
         }
 
@@ -936,15 +949,6 @@
             break;
         }
     }
-    int64_t maxTimeMedia;
-    {
-        Mutex::Autolock autoLock(mLock);
-        maxTimeMedia =
-            mAnchorTimeMediaUs +
-                    (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
-                            * 1000LL * mAudioSink->msecsPerFrame());
-    }
-    mMediaClock->updateMaxTimeMedia(maxTimeMedia);
 
     // calculate whether we need to reschedule another write.
     bool reschedule = !mAudioQueue.empty()
@@ -1506,7 +1510,10 @@
     {
         Mutex::Autolock autoLock(mLock);
         mPaused = false;
-
+        // rendering started message may have been delayed if we were paused.
+        if (mRenderingDataDelivered) {
+            notifyIfMediaRenderingStarted_l();
+        }
         // configure audiosink as we did not do it when pausing
         if (mAudioSink != NULL && mAudioSink->ready()) {
             mAudioSink->setPlaybackRate(mPlaybackSettings);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 87bcbf9..9479c31 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -176,6 +176,7 @@
     bool mVideoRenderingStarted;
     int32_t mVideoRenderingStartGeneration;
     int32_t mAudioRenderingStartGeneration;
+    bool mRenderingDataDelivered;
 
     int64_t mLastPositionUpdateUs;
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7019537..c2ffdf2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -63,6 +63,7 @@
 }
 
 static const int kMaxRetry = 2;
+static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
 
 struct ResourceManagerClient : public BnResourceManagerClient {
     ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
@@ -74,6 +75,12 @@
             return true;
         }
         status_t err = codec->reclaim();
+        if (err == WOULD_BLOCK) {
+            ALOGD("Wait for the client to release codec.");
+            usleep(kMaxReclaimWaitTimeInUs);
+            ALOGD("Try to reclaim again.");
+            err = codec->reclaim(true /* force */);
+        }
         if (err != OK) {
             ALOGW("ResourceManagerClient failed to release codec with err %d", err);
         }
@@ -571,13 +578,34 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
-status_t MediaCodec::reclaim() {
+bool MediaCodec::hasPendingBuffer(int portIndex) {
+    const Vector<BufferInfo> &buffers = mPortBuffers[portIndex];
+    for (size_t i = 0; i < buffers.size(); ++i) {
+        const BufferInfo &info = buffers.itemAt(i);
+        if (info.mOwnedByClient) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool MediaCodec::hasPendingBuffer() {
+    return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
+}
+
+status_t MediaCodec::reclaim(bool force) {
     ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
     sp<AMessage> msg = new AMessage(kWhatRelease, this);
     msg->setInt32("reclaimed", 1);
+    msg->setInt32("force", force ? 1 : 0);
 
     sp<AMessage> response;
-    return PostAndAwaitResponse(msg, &response);
+    status_t ret = PostAndAwaitResponse(msg, &response);
+    if (ret == -ENOENT) {
+        ALOGD("MediaCodec looper is gone, skip reclaim");
+        ret = OK;
+    }
+    return ret;
 }
 
 status_t MediaCodec::release() {
@@ -1787,6 +1815,23 @@
             msg->findInt32("reclaimed", &reclaimed);
             if (reclaimed) {
                 mReleasedByResourceManager = true;
+
+                int32_t force = 0;
+                msg->findInt32("force", &force);
+                if (!force && hasPendingBuffer()) {
+                    ALOGW("Can't reclaim codec right now due to pending buffers.");
+
+                    // return WOULD_BLOCK to ask resource manager to retry later.
+                    sp<AMessage> response = new AMessage;
+                    response->setInt32("err", WOULD_BLOCK);
+                    response->postReply(replyID);
+
+                    // notify the async client
+                    if (mFlags & kFlagIsAsync) {
+                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
+                    }
+                    break;
+                }
             }
 
             if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 90b5f68..5c2e9f9 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -151,6 +151,10 @@
     }
 
     mQueueChangedCondition.signal();
+    {
+        Mutex::Autolock autoLock(mRepliesLock);
+        mRepliesCondition.broadcast();
+    }
 
     if (!runningLocally && !thread->isCurrentThread()) {
         // If not running locally and this thread _is_ the looper thread,
@@ -230,13 +234,31 @@
 
 // to be called by AMessage::postAndAwaitResponse only
 status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response) {
+    {
+        Mutex::Autolock autoLock(mLock);
+        if (mThread == NULL) {
+            return -ENOENT;
+        }
+    }
+
     // return status in case we want to handle an interrupted wait
     Mutex::Autolock autoLock(mRepliesLock);
     CHECK(replyToken != NULL);
-    while (!replyToken->retrieveReply(response)) {
+    bool gotReply;
+    bool shouldContinue = true;
+    while (!(gotReply = replyToken->retrieveReply(response)) && shouldContinue) {
         mRepliesCondition.wait(mRepliesLock);
+
+        {
+            Mutex::Autolock autoLock(mLock);
+            if (mThread == NULL) {
+                shouldContinue = false;
+                // continue and try to get potential reply one more time before break the loop
+            }
+        }
     }
-    return OK;
+
+    return gotReply ? OK : -ENOENT;
 }
 
 status_t ALooper::postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &reply) {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9ec5802..fab1ef5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1352,12 +1352,16 @@
 AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
     :   RefBase(),
         mAudioFlinger(audioFlinger),
-        // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
-        mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
         mPid(pid),
         mTimedTrackCount(0)
 {
-    // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+    size_t heapSize = kClientSharedHeapSizeBytes;
+    // Increase heap size on non low ram devices to limit risk of reconnection failure for
+    // invalidated tracks
+    if (!audioFlinger->isLowRamDevice()) {
+        heapSize *= kClientSharedHeapSizeMultiplier;
+    }
+    mMemoryDealer = new MemoryDealer(heapSize, "AudioFlinger::Client");
 }
 
 // Client destructor must be called with AudioFlinger::mClientLock held
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20c34ef..08fa70d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -88,6 +88,12 @@
 
 static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
 
+
+// Max shared memory size for audio tracks and audio records per client process
+static const size_t kClientSharedHeapSizeBytes = 1024*1024;
+// Shared memory size multiplier for non low ram devices
+static const size_t kClientSharedHeapSizeMultiplier = 4;
+
 #define INCLUDING_FROM_AUDIOFLINGER_H
 
 class AudioFlinger :
@@ -423,7 +429,7 @@
                             Client(const Client&);
                             Client& operator = (const Client&);
         const sp<AudioFlinger> mAudioFlinger;
-        const sp<MemoryDealer> mMemoryDealer;
+              sp<MemoryDealer> mMemoryDealer;
         const pid_t         mPid;
 
         Mutex               mTimedTrackLock;
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 79ac12b..1bba5f6 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -131,7 +131,9 @@
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal capture thread allocate for
             //       us to avoid blocking here and to prevent possible priority inversion
-            (void)posix_memalign(&mReadBuffer, 32, frameCount * Format_frameSize(mFormat));
+            size_t bufferSize = frameCount * Format_frameSize(mFormat);
+            (void)posix_memalign(&mReadBuffer, 32, bufferSize);
+            memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
             mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;      // 1.00
             mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate;    // 1.75
             mOverrunNs = (frameCount * 500000000LL) / mSampleRate;      // 0.50
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f586291..71fc498 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6932,6 +6932,7 @@
     mRsmpInFrames = mFrameCount * 7;
     mRsmpInFramesP2 = roundup(mRsmpInFrames);
     free(mRsmpInBuffer);
+    mRsmpInBuffer = NULL;
 
     // TODO optimize audio capture buffer sizes ...
     // Here we calculate the size of the sliding buffer used as a source
@@ -6941,7 +6942,9 @@
     // The current value is higher than necessary.  However it should not add to latency.
 
     // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer
-    (void)posix_memalign(&mRsmpInBuffer, 32, (mRsmpInFramesP2 + mFrameCount - 1) * mFrameSize);
+    size_t bufferSize = (mRsmpInFramesP2 + mFrameCount - 1) * mFrameSize;
+    (void)posix_memalign(&mRsmpInBuffer, 32, bufferSize);
+    memset(mRsmpInBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
 
     // AudioRecord mSampleRate and mChannelCount are constant due to AudioRecord API constraints.
     // But if thread's mSampleRate or mChannelCount changes, how will that affect active tracks?
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b3fac0b..0e24b52 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -715,6 +715,7 @@
             // But in this case we know the mixer thread (whether normal mixer or fast mixer)
             // isn't looking at this track yet:  we still hold the normal mixer thread lock,
             // and for fast tracks the track is not yet in the fast mixer thread's active set.
+            // For static tracks, this is used to acknowledge change in position or loop.
             ServerProxy::Buffer buffer;
             buffer.mFrameCount = 1;
             (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8419ed5..5ff1c0b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -402,6 +402,20 @@
             patch.num_sources = 2;
         }
 
+        // terminate active capture if on the same HW module as the call TX source device
+        // FIXME: would be better to refine to only inputs whose profile connects to the
+        // call TX device but this information is not in the audio patch and logic here must be
+        // symmetric to the one in startInput()
+        audio_io_handle_t activeInput = mInputs.getActiveInput();
+        if (activeInput != 0) {
+            sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
+            if (activeDesc->getModuleHandle() == txSourceDeviceDesc->getModuleHandle()) {
+                audio_session_t activeSession = activeDesc->mSessions.itemAt(0);
+                stopInput(activeInput, activeSession);
+                releaseInput(activeInput, activeSession);
+            }
+        }
+
         afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
         status = mpClientInterface->createAudioPatch(&patch, &afPatchHandle, 0);
         ALOGW_IF(status != NO_ERROR, "setPhoneState() error %d creating TX audio patch",
@@ -566,9 +580,15 @@
 
     audio_io_handle_t activeInput = mInputs.getActiveInput();
     if (activeInput != 0) {
-        setInputDevice(activeInput, getNewInputDevice(activeInput));
+        sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
+        audio_devices_t newDevice = getNewInputDevice(activeInput);
+        // Force new input selection if the new device can not be reached via current input
+        if (activeDesc->mProfile->mSupportedDevices.types() & (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+            setInputDevice(activeInput, newDevice);
+        } else {
+            closeInput(activeInput);
+        }
     }
-
 }
 
 void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
@@ -1499,6 +1519,15 @@
                 return INVALID_OPERATION;
             }
         }
+
+        // Do not allow capture if an active voice call is using a software patch and
+        // the call TX source device is on the same HW module.
+        // FIXME: would be better to refine to only inputs whose profile connects to the
+        // call TX device but this information is not in the audio patch
+        if (mCallTxPatch != 0 &&
+            inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
+            return INVALID_OPERATION;
+        }
     }
 
     // Routing?
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index e42c596..406c1c4 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -99,7 +99,8 @@
 
 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
     if (!mFlashlightMapInitialized) {
-        ALOGE("%s: findFlashUnits() must be called before this method.");
+        ALOGE("%s: findFlashUnits() must be called before this method.",
+               __FUNCTION__);
         return NO_INIT;
     }
 
@@ -200,7 +201,8 @@
 
 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
     if (!mFlashlightMapInitialized) {
-        ALOGE("%s: findFlashUnits() must be called before this method.");
+        ALOGE("%s: findFlashUnits() must be called before this method.",
+               __FUNCTION__);
         return false;
     }
 
@@ -219,7 +221,8 @@
 
     Mutex::Autolock l(mLock);
     if (!mFlashlightMapInitialized) {
-        ALOGE("%s: findFlashUnits() must be called before this method.");
+        ALOGE("%s: findFlashUnits() must be called before this method.",
+               __FUNCTION__);
         return NO_INIT;
     }
 
@@ -256,7 +259,8 @@
 
     Mutex::Autolock l(mLock);
     if (!mFlashlightMapInitialized) {
-        ALOGE("%s: findFlashUnits() must be called before this method.");
+        ALOGE("%s: findFlashUnits() must be called before this method.",
+               __FUNCTION__);
         return NO_INIT;
     }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 013250b..3deb396 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -173,6 +173,13 @@
     mNumberOfCameras = mModule->getNumberOfCameras();
     mNumberOfNormalCameras = mNumberOfCameras;
 
+    // Setup vendor tags before we call get_camera_info the first time
+    // because HAL might need to setup static vendor keys in get_camera_info
+    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
+        setUpVendorTags();
+    }
+
     mFlashlight = new CameraFlashlight(*mModule, *this);
     status_t res = mFlashlight->findFlashUnits();
     if (res) {
@@ -239,12 +246,6 @@
         mModule->setCallbacks(this);
     }
 
-    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-
-    if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_2) {
-        setUpVendorTags();
-    }
-
     CameraDeviceFactory::registerService(this);
 
     CameraService::pingCameraServiceProxy();
@@ -1833,7 +1834,8 @@
     if (mSoundRef++) return;
 
     mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
-    mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    mSoundPlayer[SOUND_RECORDING_START] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    mSoundPlayer[SOUND_RECORDING_STOP] = newMediaPlayer("/system/media/audio/ui/VideoStop.ogg");
 }
 
 void CameraService::releaseSound() {
@@ -2084,7 +2086,11 @@
 
 void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
         const CaptureResultExtras& resultExtras) {
-    mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+    if (mRemoteCallback != NULL) {
+        mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+    } else {
+        ALOGE("mRemoteCallback is NULL!!");
+    }
 }
 
 // NOTE: function is idempotent
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cd97b08..4b0eeb7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -159,7 +159,8 @@
 
     enum sound_kind {
         SOUND_SHUTTER = 0,
-        SOUND_RECORDING = 1,
+        SOUND_RECORDING_START = 1,
+        SOUND_RECORDING_STOP = 2,
         NUM_SOUNDS
     };
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 48b5a26..4338d64 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1040,7 +1040,7 @@
     }
 
     if (!restart) {
-        mCameraService->playSound(CameraService::SOUND_RECORDING);
+        mCameraService->playSound(CameraService::SOUND_RECORDING_START);
         mStreamingProcessor->updateRecordingRequest(params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update recording request: %s (%d)",
@@ -1212,7 +1212,7 @@
             return;
     };
 
-    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    mCameraService->playSound(CameraService::SOUND_RECORDING_STOP);
 
     // Remove recording stream to prevent it from slowing down takePicture later
     if (!l.mParameters.recordingHint && l.mParameters.isJpegSizeOverridden()) {
@@ -1638,7 +1638,7 @@
 }
 
 status_t Camera2Client::commandPlayRecordingSoundL() {
-    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    mCameraService->playSound(CameraService::SOUND_RECORDING_START);
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 38e35cd..30b462b 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -439,7 +439,7 @@
 
     // start recording mode
     enableMsgType(CAMERA_MSG_VIDEO_FRAME);
-    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    mCameraService->playSound(CameraService::SOUND_RECORDING_START);
     result = mHardware->startRecording();
     if (result != NO_ERROR) {
         ALOGE("mHardware->startRecording() failed with status %d", result);
@@ -470,7 +470,7 @@
 
     disableMsgType(CAMERA_MSG_VIDEO_FRAME);
     mHardware->stopRecording();
-    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    mCameraService->playSound(CameraService::SOUND_RECORDING_STOP);
 
     mPreviewBuffer.clear();
 }
@@ -648,7 +648,7 @@
         }
         return OK;
     } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
-        mCameraService->playSound(CameraService::SOUND_RECORDING);
+        mCameraService->playSound(CameraService::SOUND_RECORDING_START);
     } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
         // Silently ignore this command
         return INVALID_OPERATION;
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
index eecc1ea..4df2068 100644
--- a/soundtrigger/ISoundTrigger.cpp
+++ b/soundtrigger/ISoundTrigger.cpp
@@ -60,11 +60,13 @@
         data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(modelMemory));
         status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply);
-        if (status != NO_ERROR ||
-                (status = (status_t)reply.readInt32()) != NO_ERROR) {
+        if (status != NO_ERROR) {
             return status;
         }
-        reply.read(handle, sizeof(sound_model_handle_t));
+        status = (status_t)reply.readInt32();
+        if (status == NO_ERROR) {
+            reply.read(handle, sizeof(sound_model_handle_t));
+        }
         return status;
     }
 
@@ -74,7 +76,7 @@
         data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
         data.write(&handle, sizeof(sound_model_handle_t));
         status_t status = remote()->transact(UNLOAD_SOUND_MODEL, data, &reply);
-        if (status != NO_ERROR) {
+        if (status == NO_ERROR) {
             status = (status_t)reply.readInt32();
         }
         return status;
@@ -93,7 +95,7 @@
         }
         data.writeStrongBinder(IInterface::asBinder(dataMemory));
         status_t status = remote()->transact(START_RECOGNITION, data, &reply);
-        if (status != NO_ERROR) {
+        if (status == NO_ERROR) {
             status = (status_t)reply.readInt32();
         }
         return status;
@@ -105,7 +107,7 @@
         data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
         data.write(&handle, sizeof(sound_model_handle_t));
         status_t status = remote()->transact(STOP_RECOGNITION, data, &reply);
-        if (status != NO_ERROR) {
+        if (status == NO_ERROR) {
             status = (status_t)reply.readInt32();
         }
         return status;
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
index e14a771..e37bae3 100644
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ b/soundtrigger/ISoundTriggerHwService.cpp
@@ -85,8 +85,11 @@
         data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
         data.write(&handle, sizeof(sound_trigger_module_handle_t));
         data.writeStrongBinder(IInterface::asBinder(client));
-        remote()->transact(ATTACH, data, &reply);
-        status_t status = reply.readInt32();
+        status_t status = remote()->transact(ATTACH, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
         if (reply.readInt32() != 0) {
             module = interface_cast<ISoundTrigger>(reply.readStrongBinder());
         }