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;