am a358badf: Merge d4b7315d551cc8a930c88e27ba623b3ac38f196a to mnc-dev-plus-aosp to fix build.

* commit 'a358badf0266d5188b86aecdcf4f33e0d4491ae1':
diff --git a/jni/GifTranscoder.cpp b/jni/GifTranscoder.cpp
index 44fa30c..1f329f7 100644
--- a/jni/GifTranscoder.cpp
+++ b/jni/GifTranscoder.cpp
@@ -498,11 +498,11 @@
 
 GifFilesCloser::~GifFilesCloser() {
     if (mGifIn) {
-        DGifCloseFile(mGifIn);
+        DGifCloseFile(mGifIn, NULL);
         mGifIn = NULL;
     }
     if (mGifOut) {
-        EGifCloseFile(mGifOut);
+        EGifCloseFile(mGifOut, NULL);
         mGifOut = NULL;
     }
 }
diff --git a/res/drawable-hdpi/ic_checkbox_light.png b/res/drawable-hdpi/ic_checkbox_light.png
index 7aa9f5f..e41ba42 100644
--- a/res/drawable-hdpi/ic_checkbox_light.png
+++ b/res/drawable-hdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_circle_blue.png b/res/drawable-hdpi/ic_checkmark_circle_blue.png
index 55f277e..7932c30 100644
--- a/res/drawable-hdpi/ic_checkmark_circle_blue.png
+++ b/res/drawable-hdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_checkmark_small_blue.png b/res/drawable-hdpi/ic_checkmark_small_blue.png
index 8661489..d84fd20 100644
--- a/res/drawable-hdpi/ic_checkmark_small_blue.png
+++ b/res/drawable-hdpi/ic_checkmark_small_blue.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png
index 2c52f06..5e4e62f 100644
--- a/res/drawable-hdpi/ic_launcher.png
+++ b/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_person_add_blue.png b/res/drawable-hdpi/ic_person_add_blue.png
index dfd2bc1..b7b85bd 100644
--- a/res/drawable-hdpi/ic_person_add_blue.png
+++ b/res/drawable-hdpi/ic_person_add_blue.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_remove_light.png b/res/drawable-hdpi/ic_remove_light.png
index 3992231..2222274 100644
--- a/res/drawable-hdpi/ic_remove_light.png
+++ b/res/drawable-hdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkbox_light.png b/res/drawable-mdpi/ic_checkbox_light.png
index 3762dc4..b1b1269 100644
--- a/res/drawable-mdpi/ic_checkbox_light.png
+++ b/res/drawable-mdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_circle_blue.png b/res/drawable-mdpi/ic_checkmark_circle_blue.png
index 85735be..6cf348e 100644
--- a/res/drawable-mdpi/ic_checkmark_circle_blue.png
+++ b/res/drawable-mdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_checkmark_small_blue.png b/res/drawable-mdpi/ic_checkmark_small_blue.png
index ec9dcb1..df6ea14 100644
--- a/res/drawable-mdpi/ic_checkmark_small_blue.png
+++ b/res/drawable-mdpi/ic_checkmark_small_blue.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png
index a6d2f55..ef6a3c5 100644
--- a/res/drawable-mdpi/ic_launcher.png
+++ b/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_person_add_blue.png b/res/drawable-mdpi/ic_person_add_blue.png
index 29f9066..0f63871 100644
--- a/res/drawable-mdpi/ic_person_add_blue.png
+++ b/res/drawable-mdpi/ic_person_add_blue.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_remove_light.png b/res/drawable-mdpi/ic_remove_light.png
index 0464885..5b1712a 100644
--- a/res/drawable-mdpi/ic_remove_light.png
+++ b/res/drawable-mdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkbox_light.png b/res/drawable-xhdpi/ic_checkbox_light.png
index 9cb2b7e..a388a2b 100644
--- a/res/drawable-xhdpi/ic_checkbox_light.png
+++ b/res/drawable-xhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_circle_blue.png b/res/drawable-xhdpi/ic_checkmark_circle_blue.png
index 211a405..ae0ac2d 100644
--- a/res/drawable-xhdpi/ic_checkmark_circle_blue.png
+++ b/res/drawable-xhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_checkmark_small_blue.png b/res/drawable-xhdpi/ic_checkmark_small_blue.png
index 9fc4a4b..d6354df 100644
--- a/res/drawable-xhdpi/ic_checkmark_small_blue.png
+++ b/res/drawable-xhdpi/ic_checkmark_small_blue.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png
index 3c82a06..ad1acb4 100644
--- a/res/drawable-xhdpi/ic_launcher.png
+++ b/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_person_add_blue.png b/res/drawable-xhdpi/ic_person_add_blue.png
index 4e76e64..0cdaeee 100644
--- a/res/drawable-xhdpi/ic_person_add_blue.png
+++ b/res/drawable-xhdpi/ic_person_add_blue.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_remove_light.png b/res/drawable-xhdpi/ic_remove_light.png
index cbaf6d0..9424e1e 100644
--- a/res/drawable-xhdpi/ic_remove_light.png
+++ b/res/drawable-xhdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_light.png b/res/drawable-xxhdpi/ic_checkbox_light.png
index 3a1896b..b10c8e9 100644
--- a/res/drawable-xxhdpi/ic_checkbox_light.png
+++ b/res/drawable-xxhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_circle_blue.png b/res/drawable-xxhdpi/ic_checkmark_circle_blue.png
index bede5b9..d40bb93 100644
--- a/res/drawable-xxhdpi/ic_checkmark_circle_blue.png
+++ b/res/drawable-xxhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_checkmark_small_blue.png b/res/drawable-xxhdpi/ic_checkmark_small_blue.png
index 65d3e5c..154c66e 100644
--- a/res/drawable-xxhdpi/ic_checkmark_small_blue.png
+++ b/res/drawable-xxhdpi/ic_checkmark_small_blue.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_launcher.png b/res/drawable-xxhdpi/ic_launcher.png
index 0d61198..de56e98 100644
--- a/res/drawable-xxhdpi/ic_launcher.png
+++ b/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_person_add_blue.png b/res/drawable-xxhdpi/ic_person_add_blue.png
index 10aa345..d9b6a77 100644
--- a/res/drawable-xxhdpi/ic_person_add_blue.png
+++ b/res/drawable-xxhdpi/ic_person_add_blue.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove_light.png b/res/drawable-xxhdpi/ic_remove_light.png
index 25bcc74..6f07cc5 100644
--- a/res/drawable-xxhdpi/ic_remove_light.png
+++ b/res/drawable-xxhdpi/ic_remove_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkbox_light.png b/res/drawable-xxxhdpi/ic_checkbox_light.png
index c8e8b79..f4c0cfc 100644
--- a/res/drawable-xxxhdpi/ic_checkbox_light.png
+++ b/res/drawable-xxxhdpi/ic_checkbox_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png b/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png
index 7bb1501..0c2a7d5 100644
--- a/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png
+++ b/res/drawable-xxxhdpi/ic_checkmark_circle_blue.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_checkmark_small_blue.png b/res/drawable-xxxhdpi/ic_checkmark_small_blue.png
index 3199069..855cfc5 100644
--- a/res/drawable-xxxhdpi/ic_checkmark_small_blue.png
+++ b/res/drawable-xxxhdpi/ic_checkmark_small_blue.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_launcher.png b/res/drawable-xxxhdpi/ic_launcher.png
index 0d61198..9ac88b4 100644
--- a/res/drawable-xxxhdpi/ic_launcher.png
+++ b/res/drawable-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_person_add_blue.png b/res/drawable-xxxhdpi/ic_person_add_blue.png
index b358660..13eb372 100644
--- a/res/drawable-xxxhdpi/ic_person_add_blue.png
+++ b/res/drawable-xxxhdpi/ic_person_add_blue.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_remove_light.png b/res/drawable-xxxhdpi/ic_remove_light.png
index b9288bf..e32a4dc 100644
--- a/res/drawable-xxxhdpi/ic_remove_light.png
+++ b/res/drawable-xxxhdpi/ic_remove_light.png
Binary files differ
diff --git a/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java
index f17591c..219e0a6 100644
--- a/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java
+++ b/src/com/android/messaging/datamodel/media/VideoThumbnailRequest.java
@@ -23,6 +23,7 @@
 
 import com.android.messaging.Factory;
 import com.android.messaging.util.MediaMetadataRetrieverWrapper;
+import com.android.messaging.util.MediaUtil;
 import com.android.messaging.util.OsUtil;
 
 import java.io.FileNotFoundException;
@@ -41,7 +42,7 @@
     }
 
     public static boolean shouldShowIncomingVideoThumbnails() {
-        return OsUtil.isAtLeastM();
+        return MediaUtil.canAutoAccessIncomingMedia();
     }
 
     @Override
diff --git a/src/com/android/messaging/ui/AttachmentPreviewFactory.java b/src/com/android/messaging/ui/AttachmentPreviewFactory.java
index ed5d4d7..7f1fce8 100644
--- a/src/com/android/messaging/ui/AttachmentPreviewFactory.java
+++ b/src/com/android/messaging/ui/AttachmentPreviewFactory.java
@@ -269,7 +269,8 @@
         final View view = layoutInflater.inflate(layoutId, parent, false /* attachToRoot */);
         final AudioAttachmentView audioView = (AudioAttachmentView)
                 view.findViewById(R.id.audio_attachment_view);
-        audioView.bindMessagePartData(attachmentData, false /* incoming */);
+        audioView.bindMessagePartData(
+                attachmentData, false /* incoming */, false /* showAsSelected */);
         return view;
     }
 
diff --git a/src/com/android/messaging/ui/AudioAttachmentView.java b/src/com/android/messaging/ui/AudioAttachmentView.java
index bb649b0..ad91ed2 100644
--- a/src/com/android/messaging/ui/AudioAttachmentView.java
+++ b/src/com/android/messaging/ui/AudioAttachmentView.java
@@ -41,6 +41,7 @@
 import com.android.messaging.util.Assert;
 import com.android.messaging.util.ContentType;
 import com.android.messaging.util.LogUtil;
+import com.android.messaging.util.MediaUtil;
 import com.android.messaging.util.UiUtils;
 
 /**
@@ -74,11 +75,15 @@
     private int mClipPathWidth;
     private int mClipPathHeight;
 
-    // Indicates whether the attachment view is to be styled as a part of an incoming message.
-    private boolean mShowAsIncoming;
+    private boolean mUseIncomingStyle;
+    private int mThemeColor;
 
+    private boolean mStartPlayAfterPrepare;
+    // should the MediaPlayer be prepared lazily when the user chooses to play the audio (as
+    // opposed to preparing it early, on bind)
+    private boolean mPrepareOnPlayback;
     private boolean mPrepared;
-    private boolean mPlaybackFinished;
+    private boolean mPlaybackFinished; // Was the audio played all the way to the end
     private final int mMode;
 
     public AudioAttachmentView(final Context context, final AttributeSet attrs) {
@@ -108,7 +113,7 @@
         mPlayPauseButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(final View v) {
-                setupMediaPlayer();
+                // Has the MediaPlayer already been prepared?
                 if (mMediaPlayer != null && mPrepared) {
                     if (mMediaPlayer.isPlaying()) {
                         mMediaPlayer.pause();
@@ -117,6 +122,17 @@
                     } else {
                         playAudio();
                     }
+                } else {
+                    // Either eager preparation is still going on (the user must have clicked
+                    // the Play button immediately after the view is bound) or this is lazy
+                    // preparation.
+                    if (mStartPlayAfterPrepare) {
+                        // The user is (starting and) pausing before the MediaPlayer is prepared
+                        mStartPlayAfterPrepare = false;
+                    } else {
+                        mStartPlayAfterPrepare = true;
+                        setupMediaPlayer();
+                    }
                 }
                 updatePlayPauseButtonState();
             }
@@ -125,26 +141,52 @@
         initializeViewsForMode();
     }
 
+    private void updateChronometerVisibility(final boolean playing) {
+        if (mChronometer.getVisibility() == View.GONE) {
+            // The chronometer is always GONE for LAYOUT_MODE_SUB_COMPACT
+            Assert.equals(LAYOUT_MODE_SUB_COMPACT, mMode);
+            return;
+        }
+
+        if (mPrepareOnPlayback) {
+            // For lazy preparation, the chronometer will only be shown during playback
+            mChronometer.setVisibility(playing ? View.VISIBLE : View.INVISIBLE);
+        } else {
+            mChronometer.setVisibility(View.VISIBLE);
+        }
+    }
+
     /**
      * Bind the audio attachment view with a MessagePartData.
      * @param incoming indicates whether the attachment view is to be styled as a part of an
      *        incoming message.
      */
     public void bindMessagePartData(final MessagePartData messagePartData,
-            final boolean incoming) {
+            final boolean incoming, final boolean showAsSelected) {
         Assert.isTrue(messagePartData == null ||
                 ContentType.isAudioType(messagePartData.getContentType()));
         final Uri contentUri = (messagePartData == null) ? null : messagePartData.getContentUri();
-        bind(contentUri, incoming);
+        bind(contentUri, incoming, showAsSelected);
     }
 
-    public void bind(final Uri dataSourceUri, final boolean incoming) {
+    public void bind(
+            final Uri dataSourceUri, final boolean incoming, final boolean showAsSelected) {
         final String currentUriString = (mDataSourceUri == null) ? "" : mDataSourceUri.toString();
         final String newUriString = (dataSourceUri == null) ? "" : dataSourceUri.toString();
-        mShowAsIncoming = incoming;
+        final int themeColor = ConversationDrawables.get().getConversationThemeColor();
+        final boolean useIncomingStyle = incoming || showAsSelected;
+        final boolean visualStyleChanged = mThemeColor != themeColor ||
+                mUseIncomingStyle != useIncomingStyle;
+
+        mUseIncomingStyle = useIncomingStyle;
+        mThemeColor = themeColor;
+        mPrepareOnPlayback = incoming && !MediaUtil.canAutoAccessIncomingMedia();
+
         if (!TextUtils.equals(currentUriString, newUriString)) {
             mDataSourceUri = dataSourceUri;
             resetToZeroState();
+        } else if (visualStyleChanged) {
+            updateVisualStyle();
         }
     }
 
@@ -173,11 +215,15 @@
         releaseMediaPlayer();
     }
 
+    /**
+     * Prepare the MediaPlayer, and if mPrepareOnPlayback, start playing the audio
+     */
     private void setupMediaPlayer() {
         Assert.notNull(mDataSourceUri);
         if (mMediaPlayer == null) {
             Assert.isTrue(!mPrepared);
             mMediaPlayer = new MediaPlayer();
+
             try {
                 mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                 mMediaPlayer.setDataSource(Factory.get().getApplicationContext(), mDataSourceUri);
@@ -188,6 +234,7 @@
                         mChronometer.reset();
                         mChronometer.setBase(SystemClock.elapsedRealtime() -
                                 mMediaPlayer.getDuration());
+                        updateChronometerVisibility(false /* playing */);
                         mProgressBar.reset();
 
                         mPlaybackFinished = true;
@@ -203,16 +250,24 @@
                         mProgressBar.setDuration(mMediaPlayer.getDuration());
                         mMediaPlayer.seekTo(0);
                         mPrepared = true;
+
+                        if (mStartPlayAfterPrepare) {
+                            mStartPlayAfterPrepare = false;
+                            playAudio();
+                            updatePlayPauseButtonState();
+                        }
                     }
                 });
 
                 mMediaPlayer.setOnErrorListener(new OnErrorListener() {
                     @Override
                     public boolean onError(final MediaPlayer mp, final int what, final int extra) {
+                        mStartPlayAfterPrepare = false;
                         onAudioReplayError(what, extra, null);
                         return true;
                     }
                 });
+
                 mMediaPlayer.prepareAsync();
             } catch (final Exception exception) {
                 onAudioReplayError(0, 0, exception);
@@ -226,13 +281,17 @@
             mMediaPlayer.release();
             mMediaPlayer = null;
             mPrepared = false;
+            mStartPlayAfterPrepare = false;
             mPlaybackFinished = false;
+            mChronometer.reset();
+            mProgressBar.reset();
         }
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        // The view must have scrolled off. Stop playback.
         releaseMediaPlayer();
     }
 
@@ -258,22 +317,23 @@
     }
 
     private void updatePlayPauseButtonState() {
-        if (mMediaPlayer == null || !mMediaPlayer.isPlaying()) {
-            mPlayPauseButton.setDisplayedChild(PLAY_BUTTON);
-        } else {
+        final boolean playing = mMediaPlayer != null && mMediaPlayer.isPlaying();
+        updateChronometerVisibility(playing);
+        if (mStartPlayAfterPrepare || playing) {
             mPlayPauseButton.setDisplayedChild(PAUSE_BUTTON);
+        } else {
+            mPlayPauseButton.setDisplayedChild(PLAY_BUTTON);
         }
     }
 
     private void resetToZeroState() {
         // Release the media player so it may be set up with the new audio source.
         releaseMediaPlayer();
-        mChronometer.reset();
-        mProgressBar.reset();
         updateVisualStyle();
+        updateChronometerVisibility(false /* playing */);
 
-        if (mDataSourceUri != null) {
-            // Re-ensure the media player, so we can read the duration of the audio.
+        if (mDataSourceUri != null && !mPrepareOnPlayback) {
+            // Prepare the media player, so we can read the duration of the audio.
             setupMediaPlayer();
         }
     }
@@ -284,13 +344,13 @@
             return;
         }
 
-        if (mShowAsIncoming) {
+        if (mUseIncomingStyle) {
             mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_incoming));
         } else {
             mChronometer.setTextColor(getResources().getColor(R.color.message_text_color_outgoing));
         }
-        mProgressBar.setVisualStyle(mShowAsIncoming);
-        mPlayPauseButton.setVisualStyle(mShowAsIncoming);
+        mProgressBar.setVisualStyle(mUseIncomingStyle);
+        mPlayPauseButton.setVisualStyle(mUseIncomingStyle);
         updatePlayPauseButtonState();
     }
 
diff --git a/src/com/android/messaging/ui/conversation/ConversationMessageView.java b/src/com/android/messaging/ui/conversation/ConversationMessageView.java
index e22e2c7..0bfb960 100644
--- a/src/com/android/messaging/ui/conversation/ConversationMessageView.java
+++ b/src/com/android/messaging/ui/conversation/ConversationMessageView.java
@@ -1110,7 +1110,7 @@
         @Override
         public void bindView(final View view, final MessagePartData attachment) {
             final AudioAttachmentView audioView = (AudioAttachmentView) view;
-            audioView.bindMessagePartData(attachment, isSelected() || mData.getIsIncoming());
+            audioView.bindMessagePartData(attachment, mData.getIsIncoming(), isSelected());
             audioView.setBackground(ConversationDrawables.get().getBubbleDrawable(
                     isSelected(), mData.getIsIncoming(), false /* needArrow */,
                     mData.hasIncomingErrorStatus()));
@@ -1118,7 +1118,7 @@
 
         @Override
         public void unbind(final View view) {
-            ((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming());
+            ((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming(), false);
         }
     };
 
diff --git a/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java b/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java
index 7525182..9b8c5ff 100644
--- a/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java
+++ b/src/com/android/messaging/ui/conversationlist/ConversationListItemView.java
@@ -465,7 +465,8 @@
         int audioPreviewVisiblity = GONE;
         if (previewUri != null && !TextUtils.isEmpty(previewContentType)) {
             if (ContentType.isAudioType(previewContentType)) {
-                mAudioAttachmentView.bind(previewUri, false);
+                boolean incoming = !(mData.getShowDraft() || mData.getIsMessageTypeOutgoing());
+                mAudioAttachmentView.bind(previewUri, incoming, false);
                 audioPreviewVisiblity = VISIBLE;
             } else if (ContentType.isVideoType(previewContentType)) {
                 previewImageUri = UriUtil.getUriForResourceId(
diff --git a/src/com/android/messaging/util/MediaUtil.java b/src/com/android/messaging/util/MediaUtil.java
index f25354c..c23ded3 100644
--- a/src/com/android/messaging/util/MediaUtil.java
+++ b/src/com/android/messaging/util/MediaUtil.java
@@ -33,4 +33,8 @@
      */
     public abstract void playSound(final Context context, final int resId,
             final OnCompletionListener completionListener);
+
+    public static boolean canAutoAccessIncomingMedia() {
+        return OsUtil.isAtLeastM();
+    }
 }