Refactor all voicemail audio handling to new audio manager class.

Since voicemail audio handling is about to get more complicated (adding
head phone switching and bluetooth), we need a separate class to handle
audio.

Bug: 23816959
Change-Id: If891739ef80f5646145d7a44ec70f5b7544010b0
diff --git a/src/com/android/dialer/voicemail/VoicemailAudioManager.java b/src/com/android/dialer/voicemail/VoicemailAudioManager.java
new file mode 100644
index 0000000..e64e180
--- /dev/null
+++ b/src/com/android/dialer/voicemail/VoicemailAudioManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dialer.voicemail;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.util.Log;
+
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * This class manages all audio changes for voicemail playback.
+ */
+final class VoicemailAudioManager implements OnAudioFocusChangeListener {
+    private static final String TAG = VoicemailAudioManager.class.getSimpleName();
+
+    public static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
+
+    private AudioManager mAudioManager;
+    private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
+
+    public VoicemailAudioManager(Context context,
+            VoicemailPlaybackPresenter voicemailPlaybackPresenter) {
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mVoicemailPlaybackPresenter = voicemailPlaybackPresenter;
+    }
+
+    public void requestAudioFocus() {
+        int result = mAudioManager.requestAudioFocus(
+                this,
+                PLAYBACK_STREAM,
+                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+        if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+            throw new RejectedExecutionException("Could not capture audio focus.");
+        }
+    }
+
+    public void abandonAudioFocus() {
+        mAudioManager.abandonAudioFocus(this);
+    }
+
+    @Override
+    public void onAudioFocusChange(int focusChange) {
+        Log.d(TAG, "onAudioFocusChange: focusChange=" + focusChange);
+        mVoicemailPlaybackPresenter.onAudioFocusChange(focusChange == AudioManager.AUDIOFOCUS_GAIN);
+    }
+
+    public void turnOnSpeaker(boolean on) {
+        if (mAudioManager.isSpeakerphoneOn() != on) {
+            Log.i(TAG, "turning speaker phone on: " + on);
+            mAudioManager.setSpeakerphoneOn(on);
+        }
+    }
+
+    public boolean isSpeakerphoneOn() {
+        return mAudioManager.isSpeakerphoneOn();
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index e6ab267..62da942 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -23,7 +23,6 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.media.AudioManager;
-import android.media.AudioManager.OnAudioFocusChangeListener;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -68,8 +67,7 @@
  */
 @NotThreadSafe
 @VisibleForTesting
-public class VoicemailPlaybackPresenter
-        implements OnAudioFocusChangeListener, MediaPlayer.OnPreparedListener,
+public class VoicemailPlaybackPresenter implements MediaPlayer.OnPreparedListener,
                 MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
 
     private static final String TAG = VoicemailPlaybackPresenter.class.getSimpleName();
@@ -105,7 +103,6 @@
         VoicemailContract.Voicemails.HAS_CONTENT,
     };
 
-    public static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
     private static final int NUMBER_OF_THREADS_IN_POOL = 2;
     // Time to wait for content to be fetched before timing out.
     private static final long FETCH_CONTENT_TIMEOUT_MS = 20000;
@@ -159,7 +156,7 @@
     private FetchResultHandler mFetchResultHandler;
     private Handler mHandler = new Handler();
     private PowerManager.WakeLock mProximityWakeLock;
-    private AudioManager mAudioManager;
+    private VoicemailAudioManager mVoicemailAudioManager;
 
     private OnVoicemailDeletedListener mOnVoicemailDeletedListener;
 
@@ -188,7 +185,7 @@
     private VoicemailPlaybackPresenter(Activity activity) {
         Context context = activity.getApplicationContext();
         mAsyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
-        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mVoicemailAudioManager = new VoicemailAudioManager(context, this);
 
         PowerManager powerManager =
                 (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -206,7 +203,7 @@
         mContext = activity;
 
         mInitialOrientation = mContext.getResources().getConfiguration().orientation;
-        mActivity.setVolumeControlStream(VoicemailPlaybackPresenter.PLAYBACK_STREAM);
+        mActivity.setVolumeControlStream(VoicemailAudioManager.PLAYBACK_STREAM);
 
         if (savedInstanceState != null) {
             // Restores playback state when activity is recreated, such as after rotation.
@@ -503,7 +500,7 @@
 
             mMediaPlayer.reset();
             mMediaPlayer.setDataSource(mContext, mVoicemailUri);
-            mMediaPlayer.setAudioStreamType(PLAYBACK_STREAM);
+            mMediaPlayer.setAudioStreamType(VoicemailAudioManager.PLAYBACK_STREAM);
             mMediaPlayer.prepareAsync();
         } catch (IOException e) {
             handleError(e);
@@ -577,15 +574,22 @@
         }
     }
 
-    @Override
-    public void onAudioFocusChange(int focusChange) {
-        Log.d(TAG, "onAudioFocusChange: focusChange=" + focusChange);
-        boolean lostFocus = focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
-                || focusChange == AudioManager.AUDIOFOCUS_LOSS;
-        if (mIsPlaying && focusChange == AudioManager.AUDIOFOCUS_LOSS) {
-            pausePlayback();
-        } else if (!mIsPlaying && focusChange == AudioManager.AUDIOFOCUS_GAIN) {
+    /**
+     * Only play voicemail when audio focus is granted. When it is lost (usually by another
+     * application requesting focus), pause playback.
+     *
+     * @param gainedFocus {@code true} if the audio focus was gained, {@code} false otherwise.
+     */
+    public void onAudioFocusChange(boolean gainedFocus) {
+        if (mIsPlaying == gainedFocus) {
+            // Nothing new here, just exit.
+            return;
+        }
+
+        if (!mIsPlaying) {
             resumePlayback();
+        } else {
+            pausePlayback();
         }
     }
 
@@ -614,16 +618,10 @@
 
             try {
                 // Grab audio focus.
-                int result = mAudioManager.requestAudioFocus(
-                        this,
-                        PLAYBACK_STREAM,
-                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-                if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
-                    throw new RejectedExecutionException("Could not capture audio focus.");
-                }
+                // Can throw RejectedExecutionException.
+                mVoicemailAudioManager.requestAudioFocus();
 
                 setSpeakerphoneOn(mIsSpeakerphoneOn);
-                // Can throw RejectedExecutionException.
                 mMediaPlayer.start();
             } catch (RejectedExecutionException e) {
                 handleError(e);
@@ -655,7 +653,8 @@
         if (mView != null) {
             mView.onPlaybackStopped();
         }
-        mAudioManager.abandonAudioFocus(this);
+
+        mVoicemailAudioManager.abandonAudioFocus();
 
         if (mActivity != null) {
             mActivity.getWindow().clearFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -720,7 +719,7 @@
         }
 
         mIsSpeakerphoneOn = on;
-        mAudioManager.setSpeakerphoneOn(mIsSpeakerphoneOn);
+        mVoicemailAudioManager.turnOnSpeaker(on);
 
         if (mIsPlaying) {
             if (on) {