Merge "Miscellaneous code cleanup in audio framework"
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 70519ef..9b1af6b 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -24,7 +24,6 @@
 namespace android {
 
 class Parcel;
-class ISurface;
 class Surface;
 class ISurfaceTexture;
 
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 16a9342..3c65147 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -33,7 +33,6 @@
 class IMemory;
 class IOMXObserver;
 class IOMXRenderer;
-class ISurface;
 class Surface;
 
 class IOMX : public IInterface {
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 117d7eb..447942b 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -32,7 +32,6 @@
 namespace android {
 
 class Parcel;
-class ISurface;
 class Surface;
 class ISurfaceTexture;
 
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 4610135..1827c3e 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -83,13 +83,12 @@
 
                 uint8_t     frameSize;
                 uint8_t     channelCount;
-                uint16_t    flags;
-
                 uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
-                uint16_t    waitTimeMs;      // Cumulated wait time
 
+                uint16_t    waitTimeMs;      // Cumulated wait time
                 uint16_t    sendLevel;
-                uint16_t    reserved;
+    volatile    int32_t     flags;
+
                 // Cache line boundary (32 bytes)
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
@@ -98,6 +97,7 @@
                 uint32_t    framesAvailable();
                 uint32_t    framesAvailable_l();
                 uint32_t    framesReady();
+                bool        tryLock();
 };
 
 
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index cee1c75..5d74a0a 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -35,6 +35,7 @@
 #include <binder/Parcel.h>
 #include <binder/IPCThreadState.h>
 #include <utils/Timers.h>
+#include <utils/Atomic.h>
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
@@ -299,7 +300,7 @@
             ret = mAudioRecord->start();
             cblk->lock.lock();
             if (ret == DEAD_OBJECT) {
-                cblk->flags |= CBLK_INVALID_MSK;
+                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
             }
         }
         if (cblk->flags & CBLK_INVALID_MSK) {
@@ -467,7 +468,7 @@
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
     mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
-    mCblk->flags &= ~CBLK_DIRECTION_MSK;
+    android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
     mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
     mCblk->waitTimeMs = 0;
     return NO_ERROR;
@@ -522,7 +523,7 @@
                     result = mAudioRecord->start();
                     cblk->lock.lock();
                     if (result == DEAD_OBJECT) {
-                        cblk->flags |= CBLK_INVALID_MSK;
+                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
 create_new_record:
                         result = AudioRecord::restoreRecord_l(cblk);
                     }
@@ -722,12 +723,8 @@
     // Manage overrun callback
     if (mActive && (cblk->framesAvailable() == 0)) {
         LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
-        AutoMutex _l(cblk->lock);
-        if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
-            cblk->flags |= CBLK_UNDERRUN_ON;
-            cblk->lock.unlock();
+        if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
             mCbf(EVENT_OVERRUN, mUserData, 0);
-            cblk->lock.lock();
         }
     }
 
@@ -746,10 +743,8 @@
 {
     status_t result;
 
-    if (!(cblk->flags & CBLK_RESTORING_MSK)) {
+    if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
         LOGW("dead IAudioRecord, creating a new one");
-
-        cblk->flags |= CBLK_RESTORING_ON;
         // signal old cblk condition so that other threads waiting for available buffers stop
         // waiting now
         cblk->cv.broadcast();
@@ -768,10 +763,8 @@
         }
 
         // signal old cblk condition for other threads waiting for restore completion
-        cblk->lock.lock();
-        cblk->flags |= CBLK_RESTORED_MSK;
+        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
         cblk->cv.broadcast();
-        cblk->lock.unlock();
     } else {
         if (!(cblk->flags & CBLK_RESTORED_MSK)) {
             LOGW("dead IAudioRecord, waiting for a new one to be created");
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index fb2ee0f..66e11d2 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -35,6 +35,7 @@
 #include <binder/Parcel.h>
 #include <binder/IPCThreadState.h>
 #include <utils/Timers.h>
+#include <utils/Atomic.h>
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
@@ -332,7 +333,7 @@
         cblk->lock.lock();
         cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         cblk->waitTimeMs = 0;
-        cblk->flags &= ~CBLK_DISABLED_ON;
+        android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
         if (t != 0) {
            t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
         } else {
@@ -345,7 +346,7 @@
             status = mAudioTrack->start();
             cblk->lock.lock();
             if (status == DEAD_OBJECT) {
-                cblk->flags |= CBLK_INVALID_MSK;
+                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
             }
         }
         if (cblk->flags & CBLK_INVALID_MSK) {
@@ -636,7 +637,7 @@
     if (position > mCblk->user) return BAD_VALUE;
 
     mCblk->server = position;
-    mCblk->flags |= CBLK_FORCEREADY_ON;
+    android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags);
 
     return NO_ERROR;
 }
@@ -793,7 +794,7 @@
     mCblkMemory.clear();
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
-    mCblk->flags |= CBLK_DIRECTION_OUT;
+    android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
     if (sharedBuffer == 0) {
         mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
     } else {
@@ -873,7 +874,7 @@
                         result = mAudioTrack->start();
                         cblk->lock.lock();
                         if (result == DEAD_OBJECT) {
-                            cblk->flags |= CBLK_INVALID_MSK;
+                            android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
 create_new_track:
                             result = restoreTrack_l(cblk, false);
                         }
@@ -900,14 +901,9 @@
 
     // restart track if it was disabled by audioflinger due to previous underrun
     if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
-        AutoMutex _l(cblk->lock);
-        if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
-            cblk->flags &= ~CBLK_DISABLED_ON;
-            cblk->lock.unlock();
-            LOGW("obtainBuffer() track %p disabled, restarting", this);
-            mAudioTrack->start();
-            cblk->lock.lock();
-        }
+        android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
+        LOGW("obtainBuffer() track %p disabled, restarting", this);
+        mAudioTrack->start();
     }
 
     cblk->waitTimeMs = 0;
@@ -1026,17 +1022,13 @@
     mLock.unlock();
 
     // Manage underrun callback
-    if (mActive && (cblk->framesReady() == 0)) {
+    if (mActive && (cblk->framesAvailable() == cblk->frameCount)) {
         LOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
-        AutoMutex _l(cblk->lock);
-        if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
-            cblk->flags |= CBLK_UNDERRUN_ON;
-            cblk->lock.unlock();
+        if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (cblk->server == cblk->frameCount) {
                 mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
-            cblk->lock.lock();
             if (mSharedBuffer != 0) return false;
         }
     }
@@ -1150,12 +1142,10 @@
 {
     status_t result;
 
-    if (!(cblk->flags & CBLK_RESTORING_MSK)) {
+    if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
         LOGW("dead IAudioTrack, creating a new one from %s",
              fromStart ? "start()" : "obtainBuffer()");
 
-        cblk->flags |= CBLK_RESTORING_ON;
-
         // signal old cblk condition so that other threads waiting for available buffers stop
         // waiting now
         cblk->cv.broadcast();
@@ -1198,10 +1188,8 @@
         }
 
         // signal old cblk condition for other threads waiting for restore completion
-        cblk->lock.lock();
-        cblk->flags |= CBLK_RESTORED_MSK;
+        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
         cblk->cv.broadcast();
-        cblk->lock.unlock();
     } else {
         if (!(cblk->flags & CBLK_RESTORED_MSK)) {
             LOGW("dead IAudioTrack, waiting for a new one");
@@ -1275,11 +1263,12 @@
 
 // =========================================================================
 
+
 audio_track_cblk_t::audio_track_cblk_t()
     : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
     userBase(0), serverBase(0), buffers(0), frameCount(0),
     loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
-    flags(0), sendLevel(0)
+    sendLevel(0), flags(0)
 {
 }
 
@@ -1307,10 +1296,7 @@
 
     // Clear flow control error condition as new data has been written/read to/from buffer.
     if (flags & CBLK_UNDERRUN_MSK) {
-        AutoMutex _l(lock);
-        if (flags & CBLK_UNDERRUN_MSK) {
-            flags &= ~CBLK_UNDERRUN_MSK;
-        }
+        android_atomic_and(~CBLK_UNDERRUN_MSK, &flags);
     }
 
     return u;
@@ -1318,18 +1304,8 @@
 
 bool audio_track_cblk_t::stepServer(uint32_t frameCount)
 {
-    // the code below simulates lock-with-timeout
-    // we MUST do this to protect the AudioFlinger server
-    // as this lock is shared with the client.
-    status_t err;
-
-    err = lock.tryLock();
-    if (err == -EBUSY) { // just wait a bit
-        usleep(1000);
-        err = lock.tryLock();
-    }
-    if (err != NO_ERROR) {
-        // probably, the client just died.
+    if (!tryLock()) {
+        LOGW("stepServer() could not lock cblk");
         return false;
     }
 
@@ -1406,18 +1382,42 @@
         if (u < loopEnd) {
             return u - s;
         } else {
-            Mutex::Autolock _l(lock);
-            if (loopCount >= 0) {
-                return (loopEnd - loopStart)*loopCount + u - s;
-            } else {
-                return UINT_MAX;
+            // do not block on mutex shared with client on AudioFlinger side
+            if (!tryLock()) {
+                LOGW("framesReady() could not lock cblk");
+                return 0;
             }
+            uint32_t frames = UINT_MAX;
+            if (loopCount >= 0) {
+                frames = (loopEnd - loopStart)*loopCount + u - s;
+            }
+            lock.unlock();
+            return frames;
         }
     } else {
         return s - u;
     }
 }
 
+bool audio_track_cblk_t::tryLock()
+{
+    // the code below simulates lock-with-timeout
+    // we MUST do this to protect the AudioFlinger server
+    // as this lock is shared with the client.
+    status_t err;
+
+    err = lock.tryLock();
+    if (err == -EBUSY) { // just wait a bit
+        usleep(1000);
+        err = lock.tryLock();
+    }
+    if (err != NO_ERROR) {
+        // probably, the client just died.
+        return false;
+    }
+    return true;
+}
+
 // -------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 1efa715..fa729a8 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -70,6 +70,9 @@
                                     int fileGroup, int filePerm, int directoryPerm);
     virtual             ~MtpServer();
 
+    MtpStorage*         getStorage(MtpStorageID id);
+    inline bool         hasStorage() { return mStorages.size() > 0; }
+    bool                hasStorage(MtpStorageID id);
     void                addStorage(MtpStorage* storage);
     void                removeStorage(MtpStorage* storage);
 
@@ -79,9 +82,6 @@
     void                sendObjectRemoved(MtpObjectHandle handle);
 
 private:
-    MtpStorage*         getStorage(MtpStorageID id);
-    inline bool         hasStorage() { return mStorages.size() > 0; }
-    bool                hasStorage(MtpStorageID id);
     void                sendStoreAdded(MtpStorageID id);
     void                sendStoreRemoved(MtpStorageID id);
     void                sendEvent(MtpEventCode code, uint32_t param1);
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
index 6cb88b3..fff0b5f 100644
--- a/media/mtp/MtpStorage.cpp
+++ b/media/mtp/MtpStorage.cpp
@@ -32,9 +32,11 @@
 
 namespace android {
 
-MtpStorage::MtpStorage(MtpStorageID id, const char* filePath, uint64_t reserveSpace)
+MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
+        const char* description, uint64_t reserveSpace)
     :   mStorageID(id),
         mFilePath(filePath),
+        mDescription(description),
         mMaxCapacity(0),
         mReserveSpace(reserveSpace)
 {
@@ -75,7 +77,7 @@
 }
 
 const char* MtpStorage::getDescription() const {
-    return "Device Storage";
+    return (const char *)mDescription;
 }
 
 }  // namespace android
diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h
index 858c9d3..d6ad25f 100644
--- a/media/mtp/MtpStorage.h
+++ b/media/mtp/MtpStorage.h
@@ -29,13 +29,14 @@
 private:
     MtpStorageID            mStorageID;
     MtpString               mFilePath;
+    MtpString               mDescription;
     uint64_t                mMaxCapacity;
     // amount of free space to leave unallocated
     uint64_t                mReserveSpace;
 
 public:
                             MtpStorage(MtpStorageID id, const char* filePath,
-                                    uint64_t reserveSpace);
+                                    const char* description, uint64_t reserveSpace);
     virtual                 ~MtpStorage();
 
     inline MtpStorageID     getStorageID() const { return mStorageID; }
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
index 6fedc16..8bc2e22 100644
--- a/media/mtp/mtp.h
+++ b/media/mtp/mtp.h
@@ -22,8 +22,6 @@
 
 #define MTP_STANDARD_VERSION            100
 
-#define MTP_FIRST_STORAGE_ID            0x00010001
-
 // Container Types
 #define MTP_CONTAINER_TYPE_UNDEFINED    0
 #define MTP_CONTAINER_TYPE_COMMAND      1
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 52135e7..04cfa08 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -31,6 +31,7 @@
 #include <binder/IPCThreadState.h>
 #include <utils/String16.h>
 #include <utils/threads.h>
+#include <utils/Atomic.h>
 
 #include <cutils/properties.h>
 
@@ -1738,10 +1739,7 @@
                     LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                     tracksToRemove->add(track);
                     // indicate to client process that the track was disabled because of underrun
-                    {
-                        AutoMutex _l(cblk->lock);
-                        cblk->flags |= CBLK_DISABLED_ON;
-                    }
+                    android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
                 } else if (mixerStatus != MIXER_TRACKS_READY) {
                     mixerStatus = MIXER_TRACKS_ENABLED;
                 }
@@ -1790,8 +1788,7 @@
     for (size_t i = 0; i < size; i++) {
         sp<Track> t = mTracks[i];
         if (t->type() == streamType) {
-            AutoMutex _lcblk(t->mCblk->lock);
-            t->mCblk->flags |= CBLK_INVALID_ON;
+            android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
             t->mCblk->cv.signal();
         }
     }
@@ -2950,9 +2947,8 @@
 
     if (mCblk->framesReady() >= mCblk->frameCount ||
             (mCblk->flags & CBLK_FORCEREADY_MSK)) {
-        AutoMutex _l(mCblk->lock);
         mFillingUpStatus = FS_FILLED;
-        mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+        android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
         return true;
     }
     return false;
@@ -3066,26 +3062,25 @@
         // STOPPED state
         mState = STOPPED;
 
-        // NOTE: reset() will reset cblk->user and cblk->server with
-        // the risk that at the same time, the AudioMixer is trying to read
-        // data. In this case, getNextBuffer() would return a NULL pointer
-        // as audio buffer => the AudioMixer code MUST always test that pointer
-        // returned by getNextBuffer() is not NULL!
-        reset();
+        // do not reset the track if it is still in the process of being stopped or paused.
+        // this will be done by prepareTracks_l() when the track is stopped.
+        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+            reset();
+        }
     }
 }
 
 void AudioFlinger::PlaybackThread::Track::reset()
 {
-    AutoMutex _l(mCblk->lock);
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
     if (!mResetDone) {
         TrackBase::reset();
         // Force underrun condition to avoid false underrun callback until first data is
         // written to buffer
-        mCblk->flags |= CBLK_UNDERRUN_ON;
-        mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+        android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
+        android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
         mFillingUpStatus = FS_FILLING;
         mResetDone = true;
     }
@@ -3211,13 +3206,10 @@
     if (thread != 0) {
         RecordThread *recordThread = (RecordThread *)thread.get();
         recordThread->stop(this);
-        {
-            AutoMutex _l(mCblk->lock);
-            TrackBase::reset();
-            // Force overerrun condition to avoid false overrun callback until first data is
-            // read from buffer
-            mCblk->flags |= CBLK_UNDERRUN_ON;
-        }
+        TrackBase::reset();
+        // Force overerrun condition to avoid false overrun callback until first data is
+        // read from buffer
+        android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
     }
 }
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f3c9959..7e3c643 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -472,15 +472,15 @@
     result = NO_ERROR;
 
     // return if no change in surface.
-    // asBinder() is safe on NULL (returns NULL)
-    if (getISurface(surface)->asBinder() == mSurface) {
+    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
+    if (binder == mSurface) {
         return result;
     }
 
     if (mSurface != 0) {
         LOG1("clearing old preview surface %p", mSurface.get());
     }
-    mSurface = getISurface(surface)->asBinder();
+    mSurface = binder;
     mPreviewWindow = surface;
 
     // If preview has been already started, register preview
@@ -1241,12 +1241,4 @@
     return NO_ERROR;
 }
 
-sp<ISurface> CameraService::getISurface(const sp<Surface>& surface) {
-    if (surface != 0) {
-        return surface->getISurface();
-    } else {
-        return sp<ISurface>(0);
-    }
-}
-
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 28e8cc0..9a9ab0e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -79,12 +79,6 @@
     sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
     int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
 
-    // Used by Client objects to extract the ISurface from a Surface object.
-    // This is used because making Client a friend class of Surface would
-    // require including this header in Surface.h since Client is a nested
-    // class.
-    static sp<ISurface> getISurface(const sp<Surface>& surface);
-
     class Client : public BnCamera
     {
     public: