From 46e7fbc485dd15a6c627497f121f60798d62cf80 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Fri, 5 Jun 2015 15:13:38 -0700 Subject: Handle FetchResultHandler race condition. Previously, the voicemail only needed to be looked up once, but now a single presenter may load multiple voicemails. As such, destroy the old FetchResultHandler if one already exists. Bug: 21663448 Change-Id: Ibdb08f03760b770d0800bd44d4cdcf0ca7c57fc9 --- .../voicemail/VoicemailPlaybackPresenter.java | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'src/com/android/dialer/voicemail') diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java index 1a1547692..f06840139 100644 --- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java +++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java @@ -141,6 +141,7 @@ public class VoicemailPlaybackPresenter * This variable is thread-contained, accessed only on the ui thread. */ private FetchResultHandler mFetchResultHandler; + private Handler mHandler = new Handler(); private PowerManager.WakeLock mProximityWakeLock; private AudioManager mAudioManager; @@ -298,13 +299,12 @@ public class VoicemailPlaybackPresenter * was not available. */ private void requestContent() { - Preconditions.checkState(mFetchResultHandler == null, "mFetchResultHandler should be null"); + if (mFetchResultHandler != null) { + mFetchResultHandler.destroy(); + } - Handler handler = new Handler(); - mFetchResultHandler = new FetchResultHandler(handler); - mContext.getContentResolver().registerContentObserver( - mVoicemailUri, false, mFetchResultHandler); - handler.postDelayed(mFetchResultHandler.getTimeoutRunnable(), FETCH_CONTENT_TIMEOUT_MS); + mFetchResultHandler = new FetchResultHandler(new Handler()); + mFetchResultHandler.registerContentObserver(mVoicemailUri); // Send voicemail fetch request. Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, mVoicemailUri); @@ -313,30 +313,37 @@ public class VoicemailPlaybackPresenter @ThreadSafe private class FetchResultHandler extends ContentObserver implements Runnable { - private AtomicBoolean mResultStillPending = new AtomicBoolean(true); - private final Handler mHandler; + private AtomicBoolean mIsWaitingForResult = new AtomicBoolean(true); + private final Handler mFetchResultHandler; public FetchResultHandler(Handler handler) { super(handler); - mHandler = handler; + mFetchResultHandler = handler; } - public Runnable getTimeoutRunnable() { - return this; + public void registerContentObserver(Uri voicemailUri) { + if (mIsWaitingForResult.get()) { + mContext.getContentResolver().registerContentObserver( + voicemailUri, false, this); + mFetchResultHandler.postDelayed(this, FETCH_CONTENT_TIMEOUT_MS); + } } + /** + * Stop waiting for content and notify UI if {@link FETCH_CONTENT_TIMEOUT_MS} has elapsed. + */ @Override public void run() { - if (mResultStillPending.getAndSet(false)) { - mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this); + if (mIsWaitingForResult.getAndSet(false)) { + mContext.getContentResolver().unregisterContentObserver(this); mView.setFetchContentTimeout(); } } public void destroy() { - if (mResultStillPending.getAndSet(false)) { - mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this); - mHandler.removeCallbacks(this); + if (mIsWaitingForResult.getAndSet(false)) { + mContext.getContentResolver().unregisterContentObserver(this); + mFetchResultHandler.removeCallbacks(this); } } @@ -352,7 +359,7 @@ public class VoicemailPlaybackPresenter @Override public void onPostExecute(Boolean hasContent) { if (hasContent) { - if (mResultStillPending.getAndSet(false)) { + if (mIsWaitingForResult.getAndSet(false)) { mContext.getContentResolver().unregisterContentObserver( FetchResultHandler.this); prepareToPlayContent(); -- cgit v1.2.3