Merge commit '6373349836237abffc3de8a3632234170bc1cfca' into eclair-mr2-plus-aosp * commit '6373349836237abffc3de8a3632234170bc1cfca': Add some logging to detect if AsyncPlayer is lagging. Bug 2201082.
This commit is contained in:
@@ -19,10 +19,12 @@ package android.media;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.IllegalStateException;
|
import java.lang.IllegalStateException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays a series of audio URIs, but does all the hard work on another thread
|
* Plays a series of audio URIs, but does all the hard work on another thread
|
||||||
@@ -31,14 +33,15 @@ import java.lang.IllegalStateException;
|
|||||||
public class AsyncPlayer {
|
public class AsyncPlayer {
|
||||||
private static final int PLAY = 1;
|
private static final int PLAY = 1;
|
||||||
private static final int STOP = 2;
|
private static final int STOP = 2;
|
||||||
|
private static final boolean mDebug = false;
|
||||||
|
|
||||||
private static final class Command {
|
private static final class Command {
|
||||||
Command next;
|
|
||||||
int code;
|
int code;
|
||||||
Context context;
|
Context context;
|
||||||
Uri uri;
|
Uri uri;
|
||||||
boolean looping;
|
boolean looping;
|
||||||
int stream;
|
int stream;
|
||||||
|
long requestTime;
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{ code=" + code + " looping=" + looping + " stream=" + stream
|
return "{ code=" + code + " looping=" + looping + " stream=" + stream
|
||||||
@@ -46,6 +49,36 @@ public class AsyncPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LinkedList<Command> mCmdQueue = new LinkedList();
|
||||||
|
|
||||||
|
private void startSound(Command cmd) {
|
||||||
|
// Preparing can be slow, so if there is something else
|
||||||
|
// is playing, let it continue until we're done, so there
|
||||||
|
// is less of a glitch.
|
||||||
|
try {
|
||||||
|
if (mDebug) Log.d(mTag, "Starting playback");
|
||||||
|
MediaPlayer player = new MediaPlayer();
|
||||||
|
player.setAudioStreamType(cmd.stream);
|
||||||
|
player.setDataSource(cmd.context, cmd.uri);
|
||||||
|
player.setLooping(cmd.looping);
|
||||||
|
player.prepare();
|
||||||
|
player.start();
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mPlayer.release();
|
||||||
|
}
|
||||||
|
mPlayer = player;
|
||||||
|
long delay = SystemClock.uptimeMillis() - cmd.requestTime;
|
||||||
|
if (delay > 1000) {
|
||||||
|
Log.w(mTag, "Notification sound delayed by " + delay + "msecs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
Log.w(mTag, "error loading sound for " + cmd.uri, e);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class Thread extends java.lang.Thread {
|
private final class Thread extends java.lang.Thread {
|
||||||
Thread() {
|
Thread() {
|
||||||
super("AsyncPlayer-" + mTag);
|
super("AsyncPlayer-" + mTag);
|
||||||
@@ -55,41 +88,23 @@ public class AsyncPlayer {
|
|||||||
while (true) {
|
while (true) {
|
||||||
Command cmd = null;
|
Command cmd = null;
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mCmdQueue) {
|
||||||
if (mHead != null) {
|
if (mDebug) Log.d(mTag, "RemoveFirst");
|
||||||
cmd = mHead;
|
cmd = mCmdQueue.removeFirst();
|
||||||
mHead = cmd.next;
|
|
||||||
if (mTail == cmd) {
|
|
||||||
mTail = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd.code) {
|
switch (cmd.code) {
|
||||||
case PLAY:
|
case PLAY:
|
||||||
try {
|
if (mDebug) Log.d(mTag, "PLAY");
|
||||||
// Preparing can be slow, so if there is something else
|
startSound(cmd);
|
||||||
// is playing, let it continue until we're done, so there
|
|
||||||
// is less of a glitch.
|
|
||||||
MediaPlayer player = new MediaPlayer();
|
|
||||||
player.setAudioStreamType(cmd.stream);
|
|
||||||
player.setDataSource(cmd.context, cmd.uri);
|
|
||||||
player.setLooping(cmd.looping);
|
|
||||||
player.prepare();
|
|
||||||
player.start();
|
|
||||||
if (mPlayer != null) {
|
|
||||||
mPlayer.release();
|
|
||||||
}
|
|
||||||
mPlayer = player;
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
Log.w(mTag, "error loading sound for " + cmd.uri, e);
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case STOP:
|
case STOP:
|
||||||
|
if (mDebug) Log.d(mTag, "STOP");
|
||||||
if (mPlayer != null) {
|
if (mPlayer != null) {
|
||||||
|
long delay = SystemClock.uptimeMillis() - cmd.requestTime;
|
||||||
|
if (delay > 1000) {
|
||||||
|
Log.w(mTag, "Notification stop delayed by " + delay + "msecs");
|
||||||
|
}
|
||||||
mPlayer.stop();
|
mPlayer.stop();
|
||||||
mPlayer.release();
|
mPlayer.release();
|
||||||
mPlayer = null;
|
mPlayer = null;
|
||||||
@@ -99,8 +114,8 @@ public class AsyncPlayer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mCmdQueue) {
|
||||||
if (mHead == null) {
|
if (mCmdQueue.size() == 0) {
|
||||||
// nothing left to do, quit
|
// nothing left to do, quit
|
||||||
// doing this check after we're done prevents the case where they
|
// doing this check after we're done prevents the case where they
|
||||||
// added it during the operation from spawning two threads and
|
// added it during the operation from spawning two threads and
|
||||||
@@ -115,11 +130,8 @@ public class AsyncPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String mTag;
|
private String mTag;
|
||||||
private Command mHead;
|
|
||||||
private Command mTail;
|
|
||||||
private Thread mThread;
|
private Thread mThread;
|
||||||
private MediaPlayer mPlayer;
|
private MediaPlayer mPlayer;
|
||||||
private Object mLock = new Object();
|
|
||||||
private PowerManager.WakeLock mWakeLock;
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
|
||||||
// The current state according to the caller. Reality lags behind
|
// The current state according to the caller. Reality lags behind
|
||||||
@@ -154,12 +166,13 @@ public class AsyncPlayer {
|
|||||||
*/
|
*/
|
||||||
public void play(Context context, Uri uri, boolean looping, int stream) {
|
public void play(Context context, Uri uri, boolean looping, int stream) {
|
||||||
Command cmd = new Command();
|
Command cmd = new Command();
|
||||||
|
cmd.requestTime = SystemClock.uptimeMillis();
|
||||||
cmd.code = PLAY;
|
cmd.code = PLAY;
|
||||||
cmd.context = context;
|
cmd.context = context;
|
||||||
cmd.uri = uri;
|
cmd.uri = uri;
|
||||||
cmd.looping = looping;
|
cmd.looping = looping;
|
||||||
cmd.stream = stream;
|
cmd.stream = stream;
|
||||||
synchronized (mLock) {
|
synchronized (mCmdQueue) {
|
||||||
enqueueLocked(cmd);
|
enqueueLocked(cmd);
|
||||||
mState = PLAY;
|
mState = PLAY;
|
||||||
}
|
}
|
||||||
@@ -170,11 +183,12 @@ public class AsyncPlayer {
|
|||||||
* at this point. Calling this multiple times has no ill effects.
|
* at this point. Calling this multiple times has no ill effects.
|
||||||
*/
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
synchronized (mLock) {
|
synchronized (mCmdQueue) {
|
||||||
// This check allows stop to be called multiple times without starting
|
// This check allows stop to be called multiple times without starting
|
||||||
// a thread that ends up doing nothing.
|
// a thread that ends up doing nothing.
|
||||||
if (mState != STOP) {
|
if (mState != STOP) {
|
||||||
Command cmd = new Command();
|
Command cmd = new Command();
|
||||||
|
cmd.requestTime = SystemClock.uptimeMillis();
|
||||||
cmd.code = STOP;
|
cmd.code = STOP;
|
||||||
enqueueLocked(cmd);
|
enqueueLocked(cmd);
|
||||||
mState = STOP;
|
mState = STOP;
|
||||||
@@ -183,12 +197,7 @@ public class AsyncPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void enqueueLocked(Command cmd) {
|
private void enqueueLocked(Command cmd) {
|
||||||
if (mTail == null) {
|
mCmdQueue.add(cmd);
|
||||||
mHead = cmd;
|
|
||||||
} else {
|
|
||||||
mTail.next = cmd;
|
|
||||||
}
|
|
||||||
mTail = cmd;
|
|
||||||
if (mThread == null) {
|
if (mThread == null) {
|
||||||
acquireWakeLock();
|
acquireWakeLock();
|
||||||
mThread = new Thread();
|
mThread = new Thread();
|
||||||
|
|||||||
Reference in New Issue
Block a user