summaryrefslogtreecommitdiff
path: root/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
diff options
context:
space:
mode:
authorJay Shrauner <shrauner@google.com>2014-02-26 15:33:34 -0800
committerJay Shrauner <shrauner@google.com>2014-03-05 13:54:25 -0800
commit8567cd5af9b7cc6426e9ee89ba240e2a2efa2522 (patch)
tree3d4483fd66a1bd9a68c3a4fc0138191657c79edb /src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
parent7d63a49bd5d0d374795329a864f6b62038072dbb (diff)
Fix threading problems in voicemail code
Hold libvariablespeed handle in a reference counted singleton. Don't always reinitialize the engine twice in quick succession on startup. Catch and properly handle RejectedExecutionException exceptions thrown by the executor service. Bug:11511992 Change-Id: I6198dec303209445a0efd0f410a67332d75c7507
Diffstat (limited to 'src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java')
-rw-r--r--src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java104
1 files changed, 65 insertions, 39 deletions
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index ebda0eb3c..085ef669a 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -35,6 +35,7 @@ import com.android.ex.variablespeed.SingleThreadedMediaPlayerProxy;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -311,6 +312,7 @@ public class VoicemailPlaybackPresenter {
mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
mPlayer.setAudioStreamType(PLAYBACK_STREAM);
mPlayer.prepare();
+ mDuration.set(mPlayer.getDuration());
return null;
} catch (Exception e) {
return e;
@@ -344,7 +346,7 @@ public class VoicemailPlaybackPresenter {
mView.setSpeakerPhoneOn(mView.isSpeakerPhoneOn());
mView.setRateDecreaseButtonListener(createRateDecreaseListener());
mView.setRateIncreaseButtonListener(createRateIncreaseListener());
- mView.setClipPosition(0, mPlayer.getDuration());
+ mView.setClipPosition(0, mDuration.get());
mView.playbackStopped();
// Always disable on stop.
mView.disableProximitySensor();
@@ -363,6 +365,10 @@ public class VoicemailPlaybackPresenter {
}
public void onDestroy() {
+ if (mPrepareTask != null) {
+ mPrepareTask.cancel(false);
+ mPrepareTask = null;
+ }
mPlayer.release();
if (mFetchResultHandler != null) {
mFetchResultHandler.destroy();
@@ -430,49 +436,67 @@ public class VoicemailPlaybackPresenter {
}
}
+ private class AsyncPrepareTask extends AsyncTask<Void, Void, Exception> {
+ private int mClipPositionInMillis;
+
+ AsyncPrepareTask(int clipPositionInMillis) {
+ mClipPositionInMillis = clipPositionInMillis;
+ }
+
+ @Override
+ public Exception doInBackground(Void... params) {
+ try {
+ if (!mPlayer.isReadyToPlay()) {
+ mPlayer.reset();
+ mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
+ mPlayer.setAudioStreamType(PLAYBACK_STREAM);
+ mPlayer.prepare();
+ }
+ return null;
+ } catch (Exception e) {
+ return e;
+ }
+ }
+
+ @Override
+ public void onPostExecute(Exception exception) {
+ mPrepareTask = null;
+ if (exception == null) {
+ final int duration = mPlayer.getDuration();
+ mDuration.set(duration);
+ int startPosition =
+ constrain(mClipPositionInMillis, 0, duration);
+ mPlayer.seekTo(startPosition);
+ mView.setClipPosition(startPosition, duration);
+ try {
+ // Can throw RejectedExecutionException
+ mPlayer.start();
+ mView.playbackStarted();
+ if (!mWakeLock.isHeld()) {
+ mWakeLock.acquire();
+ }
+ // Only enable if we are not currently using the speaker phone.
+ if (!mView.isSpeakerPhoneOn()) {
+ mView.enableProximitySensor();
+ }
+ // Can throw RejectedExecutionException
+ mPositionUpdater.startUpdating(startPosition, duration);
+ } catch (RejectedExecutionException e) {
+ handleError(e);
+ }
+ } else {
+ handleError(exception);
+ }
+ }
+ }
+
private void resetPrepareStartPlaying(final int clipPositionInMillis) {
if (mPrepareTask != null) {
mPrepareTask.cancel(false);
+ mPrepareTask = null;
}
mPrepareTask = mAsyncTaskExecutor.submit(Tasks.RESET_PREPARE_START_MEDIA_PLAYER,
- new AsyncTask<Void, Void, Exception>() {
- @Override
- public Exception doInBackground(Void... params) {
- try {
- mPlayer.reset();
- mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
- mPlayer.setAudioStreamType(PLAYBACK_STREAM);
- mPlayer.prepare();
- return null;
- } catch (Exception e) {
- return e;
- }
- }
-
- @Override
- public void onPostExecute(Exception exception) {
- mPrepareTask = null;
- if (exception == null) {
- mDuration.set(mPlayer.getDuration());
- int startPosition =
- constrain(clipPositionInMillis, 0, mDuration.get());
- mView.setClipPosition(startPosition, mDuration.get());
- mPlayer.seekTo(startPosition);
- mPlayer.start();
- mView.playbackStarted();
- if (!mWakeLock.isHeld()) {
- mWakeLock.acquire();
- }
- // Only enable if we are not currently using the speaker phone.
- if (!mView.isSpeakerPhoneOn()) {
- mView.enableProximitySensor();
- }
- mPositionUpdater.startUpdating(startPosition, mDuration.get());
- } else {
- handleError(exception);
- }
- }
- });
+ new AsyncPrepareTask(clipPositionInMillis));
}
private void handleError(Exception e) {
@@ -598,6 +622,7 @@ public class VoicemailPlaybackPresenter {
synchronized (mLock) {
if (mScheduledFuture != null) {
mScheduledFuture.cancel(false);
+ mScheduledFuture = null;
}
mScheduledFuture = mExecutorService.scheduleAtFixedRate(this, 0, mPeriodMillis,
TimeUnit.MILLISECONDS);
@@ -620,6 +645,7 @@ public class VoicemailPlaybackPresenter {
}
if (mPrepareTask != null) {
mPrepareTask.cancel(false);
+ mPrepareTask = null;
}
if (mWakeLock.isHeld()) {
mWakeLock.release();