Merge "Create the voicemail fragment on-demand, not every time."
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 83d3e20..94bc072 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -57,12 +57,7 @@
         android:layout_height="wrap_content"
         android:layout_below="@id/contact_background_sizer"
     >
-        <fragment
-            class="com.android.contacts.voicemail.VoicemailPlaybackFragment"
-            android:id="@+id/voicemail_playback_fragment"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-        />
+        <!-- The voicemail fragment will be put here. -->
     </LinearLayout>
     <LinearLayout
         android:layout_width="match_parent"
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 813ebb1..e9a693e 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -25,7 +25,6 @@
 import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
 
 import android.app.ActionBar;
-import android.app.FragmentManager;
 import android.app.ListActivity;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -179,16 +178,22 @@
      */
     private void optionallyHandleVoicemail() {
         if (hasVoicemail()) {
-            // Has voicemail: leave the fragment visible.  Optionally start the playback.
+            // Has voicemail: add the voicemail fragment.  Add suitable arguments to set the uri
+            // to play and optionally start the playback.
             // Do a query to fetch the voicemail status messages.
-            boolean startPlayback = getIntent().getBooleanExtra(
-                    EXTRA_VOICEMAIL_START_PLAYBACK, false);
+            VoicemailPlaybackFragment playbackFragment = new VoicemailPlaybackFragment();
+            Bundle fragmentArguments = new Bundle();
             Uri voicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
-            getVoicemailPlaybackFragment().setVoicemailUri(voicemailUri, startPlayback);
+            fragmentArguments.putParcelable(EXTRA_VOICEMAIL_URI, voicemailUri);
+            if (getIntent().getBooleanExtra(EXTRA_VOICEMAIL_START_PLAYBACK, false)) {
+                fragmentArguments.putBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, true);
+            }
+            playbackFragment.setArguments(fragmentArguments);
+            getFragmentManager().beginTransaction()
+                    .add(R.id.voicemail_container, playbackFragment).commit();
             mAsyncQueryHandler.startVoicemailStatusQuery(voicemailUri);
         } else {
-            // No voicemail uri: hide the voicemail fragment and the status view.
-            getFragmentManager().beginTransaction().hide(getVoicemailPlaybackFragment()).commit();
+            // No voicemail uri: hide the status view.
             mStatusMessageView.setVisibility(View.GONE);
         }
     }
@@ -197,12 +202,6 @@
         return getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI) != null;
     }
 
-    private VoicemailPlaybackFragment getVoicemailPlaybackFragment() {
-        FragmentManager manager = getFragmentManager();
-        return (VoicemailPlaybackFragment) manager.findFragmentById(
-                R.id.voicemail_playback_fragment);
-    }
-
     /**
      * Returns the list of URIs to show.
      * <p>
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index b1da1a1..edc1bb4 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -16,9 +16,13 @@
 
 package com.android.contacts.voicemail;
 
+import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK;
+import static com.android.contacts.CallDetailActivity.EXTRA_VOICEMAIL_URI;
+
 import com.android.contacts.R;
 import com.android.ex.variablespeed.MediaPlayerProxy;
 import com.android.ex.variablespeed.VariableSpeed;
+import com.google.common.base.Preconditions;
 
 import android.app.Fragment;
 import android.content.Context;
@@ -71,7 +75,7 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.playback_layout, container);
+        View view = inflater.inflate(R.layout.playback_layout, null);
         mPlaybackSeek = (SeekBar) view.findViewById(R.id.playback_seek);
         mPlaybackSeek = (SeekBar) view.findViewById(R.id.playback_seek);
         mStartStopButton = (ImageButton) view.findViewById(R.id.playback_start_stop);
@@ -88,8 +92,14 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mScheduledExecutorService = createScheduledExecutorService();
+        Bundle arguments = getArguments();
+        Preconditions.checkNotNull(arguments, "fragment must be started with arguments");
+        Uri voicemailUri = arguments.getParcelable(EXTRA_VOICEMAIL_URI);
+        Preconditions.checkNotNull(voicemailUri, "fragment must contain EXTRA_VOICEMAIL_URI");
+        boolean startPlayback = arguments.getBoolean(EXTRA_VOICEMAIL_START_PLAYBACK, false);
         mPresenter = new VoicemailPlaybackPresenter(new PlaybackViewImpl(),
-                createMediaPlayer(mScheduledExecutorService), mScheduledExecutorService);
+                createMediaPlayer(mScheduledExecutorService), voicemailUri,
+                mScheduledExecutorService, startPlayback);
         mPresenter.onCreate(savedInstanceState);
     }
 
@@ -106,11 +116,6 @@
         super.onDestroy();
     }
 
-    /** Call this from the Activity containing this fragment to set the voicemail to play. */
-    public void setVoicemailUri(Uri voicemailUri, boolean startPlaying) {
-        mPresenter.setVoicemailUri(voicemailUri, startPlaying);
-    }
-
     private MediaPlayerProxy createMediaPlayer(ExecutorService executorService) {
         return VariableSpeed.createVariableSpeed(executorService);
     }
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index 5e7b707..0e7470a 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -119,13 +119,18 @@
     private final MediaPlayerProxy mPlayer;
     private final PositionUpdater mPositionUpdater;
 
-    /** Voicemail uri to play, will be set with a call to {@link #setVoicemailUri(Uri, boolean)}. */
-    private Uri mVoicemailUri;
+    /** Voicemail uri to play. */
+    private final Uri mVoicemailUri;
+    /** Start playing in onCreate iff this is true. */
+    private final boolean mStartPlayingImmediately;
 
     public VoicemailPlaybackPresenter(PlaybackView view, MediaPlayerProxy player,
-            ScheduledExecutorService executorService) {
+            Uri voicemailUri, ScheduledExecutorService executorService,
+            boolean startPlayingImmediately) {
         mView = view;
         mPlayer = player;
+        mVoicemailUri = voicemailUri;
+        mStartPlayingImmediately = startPlayingImmediately;
         mPositionUpdater = new PositionUpdater(executorService, SLIDER_UPDATE_PERIOD_MILLIS);
     }
 
@@ -141,6 +146,9 @@
         mView.setRateIncreaseButtonListener(createRateIncreaseListener());
         mView.setClipPosition(0, 0);
         mView.playbackStopped();
+        if (mStartPlayingImmediately) {
+            resetPrepareStartPlaying(0);
+        }
         // TODO: Now I'm ignoring the bundle, when previously I was checking for contains against
         // the PAUSED_STATE_KEY, and CLIP_POSITION_KEY.
     }
@@ -157,13 +165,6 @@
         mPlayer.release();
     }
 
-    public void setVoicemailUri(Uri voicemailUri, boolean startPlaying) {
-        mVoicemailUri = voicemailUri;
-        if (startPlaying) {
-            resetPrepareStartPlaying(0);
-        }
-    }
-
     private class MediaPlayerErrorListener implements MediaPlayer.OnErrorListener {
         @Override
         public boolean onError(MediaPlayer mp, int what, int extra) {
@@ -334,7 +335,13 @@
         private final Runnable mSetClipPostitionRunnable = new Runnable() {
             @Override
             public void run() {
-                mView.setClipPosition(mPlayer.getCurrentPosition(), mDuration.get());
+                int currentPosition = 0;
+                synchronized (mLock) {
+                    if (mScheduledFuture != null) {
+                        currentPosition = mPlayer.getCurrentPosition();
+                    }
+                }
+                mView.setClipPosition(currentPosition, mDuration.get());
             }
         };
 
@@ -345,11 +352,7 @@
 
         @Override
         public void run() {
-            synchronized (mLock) {
-                if (mScheduledFuture != null) {
-                    mView.runOnUiThread(mSetClipPostitionRunnable);
-                }
-            }
+            mView.runOnUiThread(mSetClipPostitionRunnable);
         }
 
         public void startUpdating(int beginPosition, int endPosition) {