Add SoundPool API to pause and resume all active streams. Bug 2426531.
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index df21aa4..62a4fe9 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -321,6 +321,28 @@
     public native final void resume(int streamID);
 
     /**
+     * Pause all active streams.
+     *
+     * Pause all streams that are currently playing. This function
+     * iterates through all the active streams and pauses any that
+     * are playing. It also sets a flag so that any streams that
+     * are playing can be resumed by calling autoResume().
+     *
+     * @hide
+     */
+    public native final void autoPause();
+
+    /**
+     * Resume all previously active streams.
+     *
+     * Automatically resumes all streams that were paused in previous
+     * calls to autoPause().
+     *
+     * @hide
+     */
+    public native final void autoResume();
+
+    /**
      * Stop a playback stream.
      *
      * Stop the stream specified by the streamID. This
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index e57f4a4..2a65b0d 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -294,6 +294,16 @@
     }
 }
 
+void SoundPool::autoPause()
+{
+    LOGV("pauseAll()");
+    Mutex::Autolock lock(&mLock);
+    for (int i = 0; i < mMaxChannels; ++i) {
+        SoundChannel* channel = &mChannelPool[i];
+        channel->autoPause();
+    }
+}
+
 void SoundPool::resume(int channelID)
 {
     LOGV("resume(%d)", channelID);
@@ -304,6 +314,16 @@
     }
 }
 
+void SoundPool::autoResume()
+{
+    LOGV("pauseAll()");
+    Mutex::Autolock lock(&mLock);
+    for (int i = 0; i < mMaxChannels; ++i) {
+        SoundChannel* channel = &mChannelPool[i];
+        channel->autoResume();
+    }
+}
+
 void SoundPool::stop(int channelID)
 {
     LOGV("stop(%d)", channelID);
@@ -710,12 +730,35 @@
     }
 }
 
+void SoundChannel::autoPause()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PLAYING) {
+        LOGV("pause track");
+        mState = PAUSED;
+        mAutoPaused = true;
+        mAudioTrack->pause();
+    }
+}
+
 void SoundChannel::resume()
 {
     Mutex::Autolock lock(&mLock);
     if (mState == PAUSED) {
         LOGV("resume track");
         mState = PLAYING;
+        mAutoPaused = false;
+        mAudioTrack->start();
+    }
+}
+
+void SoundChannel::autoResume()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAutoPaused && (mState == PAUSED)) {
+        LOGV("resume track");
+        mState = PLAYING;
+        mAutoPaused = false;
         mAudioTrack->start();
     }
 }
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 7a2d631..42037af 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -117,7 +117,8 @@
 class SoundChannel : public SoundEvent {
 public:
     enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
-    SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1), mPos(0), mToggle(0) {}
+    SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1),
+            mPos(0), mToggle(0), mAutoPaused(false) {}
     ~SoundChannel();
     void init(SoundPool* soundPool);
     void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
@@ -127,7 +128,9 @@
     void stop_l();
     void stop();
     void pause();
+    void autoPause();
     void resume();
+    void autoResume();
     void setRate(float rate);
     int state() { return mState; }
     void setPriority(int priority) { mPriority = priority; }
@@ -151,6 +154,7 @@
     int                 mPos;
     int                 mAudioBufferSize;
     unsigned long       mToggle;
+    bool                mAutoPaused;
 };
 
 // application object for managing a pool of sounds
@@ -166,7 +170,9 @@
     int play(int sampleID, float leftVolume, float rightVolume, int priority,
             int loop, float rate);
     void pause(int channelID);
+    void autoPause();
     void resume(int channelID);
+    void autoResume();
     void stop(int channelID);
     void setVolume(int channelID, float leftVolume, float rightVolume);
     void setPriority(int channelID, int priority);
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index f0677a6..447f931 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -102,6 +102,24 @@
 }
 
 static void
+android_media_SoundPool_autoPause(JNIEnv *env, jobject thiz)
+{
+    LOGV("android_media_SoundPool_autoPause");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->autoPause();
+}
+
+static void
+android_media_SoundPool_autoResume(JNIEnv *env, jobject thiz)
+{
+    LOGV("android_media_SoundPool_autoResume");
+    SoundPool *ap = MusterSoundPool(env, thiz);
+    if (ap == NULL) return;
+    ap->autoResume();
+}
+
+static void
 android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
 {
     LOGV("android_media_SoundPool_stop");
@@ -223,6 +241,14 @@
         "(I)V",
         (void *)android_media_SoundPool_resume
     },
+    {   "autoPause",
+        "()V",
+        (void *)android_media_SoundPool_autoPause
+    },
+    {   "autoResume",
+        "()V",
+        (void *)android_media_SoundPool_autoResume
+    },
     {   "stop",
         "(I)V",
         (void *)android_media_SoundPool_stop
diff --git a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
index 1434d3f..df1b375 100644
--- a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
+++ b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
@@ -52,7 +52,6 @@
         R.raw.test5
     };
 
-    private final static int MAX_STREAMS = 1;
     private final static float SEMITONE = 1.059463094f;
     private final static float DEFAULT_VOLUME = 0.707f;
     private final static float MAX_VOLUME = 1.0f;
@@ -70,6 +69,7 @@
         private boolean mRunning;
         private SoundPool mSoundPool = null;
         private int mLastSample;
+        private int mMaxStreams;
         private int mLoadStatus;
         private int[] mSounds;
         private float mScale[];
@@ -101,17 +101,18 @@
             return id;
         }
 
-        private int initSoundPool() throws java.lang.InterruptedException {
+        private int initSoundPool(int numStreams) throws java.lang.InterruptedException {
 
             if (mSoundPool != null) {
-                if (mLoadStatus == 0) return mLoadStatus;
+                if ((mMaxStreams == numStreams) && (mLoadStatus == 0)) return mLoadStatus;
                 mSoundPool.release();
                 mSoundPool = null;
             }
 
             // create sound pool
             mLoadStatus = 0;
-            mSoundPool = new SoundPool(MAX_STREAMS, AudioSystem.STREAM_MUSIC, 0);
+            mMaxStreams = numStreams;
+            mSoundPool = new SoundPool(numStreams, AudioSystem.STREAM_MUSIC, 0);
             mSoundPool.setOnLoadCompleteListener(new LoadCompleteCallback());
             int numSounds = mTestFiles.length;
             mSounds = new int[numSounds];
@@ -262,6 +263,31 @@
 
             mSoundPool.stop(id);
 
+            // play 5 sounds, forces one to be stolen
+            int ids[] = new int[5];
+            for (int i = 0; i < 5; i++) {
+                ids[i] = mSoundPool.play(mSounds[0], DEFAULT_VOLUME, DEFAULT_VOLUME,
+                        NORMAL_PRIORITY, DEFAULT_LOOP, mScale[i]);
+                if (DEBUG) Log.d(LOG_TAG, "Start note " + ids[i]);
+                if (ids[i] == 0) {
+                    Log.e(LOG_TAG, "Error occurred starting note");
+                    return false;
+                }
+                sleep(250);
+            }
+
+            // pause and resume sound a few times
+            for (int count = 0; count < 5; count++) {
+                mSoundPool.autoPause();
+                sleep(250);
+                mSoundPool.autoResume();
+                sleep(250);
+            }
+
+            for (int i = 0; i < 5; i++) {
+                mSoundPool.stop(ids[i]);
+            }
+
             if (DEBUG) Log.d(LOG_TAG, "End pause/resume test");
             return result;
         }
@@ -309,17 +335,18 @@
 
             try {
 
-                // load sound pool
-                initSoundPool();
-
-                // do tests
+                // do single stream tests
+                initSoundPool(1);
                 if (!TestSounds()) failures = failures + 1;
                 if (!TestScales()) failures = failures + 1;
                 if (!TestRates()) failures = failures + 1;
                 if (!TestPriority()) failures = failures + 1;
-                if (!TestPauseResume()) failures = failures + 1;
                 if (!TestVolume()) failures = failures + 1;
 
+                // do multiple stream tests
+                initSoundPool(4);
+                if (!TestPauseResume()) failures = failures + 1;
+
             } catch (java.lang.InterruptedException e) {
                 if (DEBUG) Log.d(LOG_TAG, "Test interrupted");
                 failures = failures + 1;