Merge \\"Get gestures animation preview image in async loader.\\" into nyc-mr1-dev am: fd922cabd9
am: 8668aa0a8f

Change-Id: I01680b9241312c22ecf7539d6abc73a90e4228eb
diff --git a/src/com/android/settings/gestures/GesturePreference.java b/src/com/android/settings/gestures/GesturePreference.java
index c6ee0a7..a11455a 100644
--- a/src/com/android/settings/gestures/GesturePreference.java
+++ b/src/com/android/settings/gestures/GesturePreference.java
@@ -14,13 +14,18 @@
 
 package com.android.settings.gestures;
 
+import android.app.LoaderManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Loader;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.SurfaceTexture;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.Bundle;
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.view.View;
@@ -31,22 +36,24 @@
 import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.utils.AsyncLoader;
 
 /**
  * Preference item for a gesture with a switch to signify if it should be enabled.
  * This shows the title and description of the gesture along with an animation showing how to do
  * the gesture
  */
-public final class GesturePreference extends SwitchPreference {
+public final class GesturePreference extends SwitchPreference implements
+        LoaderManager.LoaderCallbacks<Bitmap> {
     private static final String TAG = "GesturePreference";
     private final Context mContext;
 
     private Uri mVideoPath;
     private MediaPlayer mMediaPlayer;
-    private MediaMetadataRetriever mMediaMetadata;
     private boolean mAnimationAvailable;
-    private boolean mPreviewReady;
+    private boolean mVideoReady;
     private boolean mScrolling;
+    private BitmapDrawable mPreviewImage;
 
     public GesturePreference(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -62,15 +69,12 @@
                     .authority(context.getPackageName())
                     .appendPath(String.valueOf(animation))
                     .build();
-            mMediaMetadata = new MediaMetadataRetriever();
-            mMediaMetadata.setDataSource(mContext, mVideoPath);
             mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
             if (mMediaPlayer != null) {
                 mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                     @Override
                     public void onSeekComplete(MediaPlayer mp) {
-                        mPreviewReady = true;
-                        mMediaPlayer.setOnSeekCompleteListener(null);
+                        mVideoReady = true;
                     }
                 });
 
@@ -82,6 +86,7 @@
                 });
             }
             mAnimationAvailable = true;
+
         } catch (Exception e) {
             Log.w(TAG, "Animation resource not found. Will not show animation.");
         } finally {
@@ -125,6 +130,7 @@
                     int height) {
                 if (mMediaPlayer != null) {
                     mMediaPlayer.setSurface(new Surface(surfaceTexture));
+                    mVideoReady = false;
                     mMediaPlayer.seekTo(0);
                 }
             }
@@ -136,12 +142,16 @@
 
             @Override
             public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+                if (mPreviewImage != null && imageView.getDrawable() == null) {
+                    imageView.setImageDrawable(mPreviewImage);
+                }
+                imageView.setVisibility(View.VISIBLE);
                 return false;
             }
 
             @Override
             public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
-                if (mPreviewReady && imageView.getVisibility() == View.VISIBLE) {
+                if (mVideoReady && imageView.getVisibility() == View.VISIBLE) {
                     imageView.setVisibility(View.GONE);
                 } else if (mScrolling) {
                     mScrolling = false;
@@ -153,13 +163,14 @@
             }
         });
 
+        if (mPreviewImage != null) {
+            imageView.setImageDrawable(mPreviewImage);
+        }
+
     }
 
     @Override
     public void onDetached() {
-        if (mMediaMetadata != null) {
-            mMediaMetadata.release();
-        }
         if (mMediaPlayer != null) {
             mMediaPlayer.stop();
             mMediaPlayer.reset();
@@ -172,4 +183,55 @@
         mScrolling = scrolling;
     }
 
+    void loadPreview(LoaderManager manager, int id) {
+        Loader<Bitmap> loader = manager.initLoader(id, Bundle.EMPTY, this);
+    }
+
+    private static final class PreviewRetriever extends AsyncLoader<Bitmap> {
+        private Uri mVideoPath;
+
+        public PreviewRetriever(Context context, Uri videoPath) {
+            super(context);
+            mVideoPath = videoPath;
+        }
+
+        @Override
+        public Bitmap loadInBackground() {
+            MediaMetadataRetriever mediaMetadata = new MediaMetadataRetriever();
+            try {
+                mediaMetadata.setDataSource(getContext(), mVideoPath);
+                return mediaMetadata.getFrameAtTime(0);
+            } catch (Exception e) {
+                Log.w(TAG, "Unable to get animation preview.");
+            } finally {
+                mediaMetadata.release();
+            }
+            return null;
+        }
+
+        @Override
+        public void onDiscardResult(final Bitmap result) {
+            if (result != null && !result.isRecycled()) {
+                result.recycle();
+            }
+        }
+
+    }
+
+    @Override
+    public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
+        return new PreviewRetriever(mContext, mVideoPath);
+    }
+
+    @Override
+    public void onLoadFinished(final Loader<Bitmap> loader, final Bitmap bitmap) {
+        if (bitmap != null) {
+            mPreviewImage = new BitmapDrawable(mContext.getResources(), bitmap);
+        }
+    }
+
+    @Override
+    public void onLoaderReset(Loader<Bitmap> loader) {
+    }
+
 }
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
index a61509f..37dcc7e 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -56,6 +56,10 @@
     private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint";
     private static final String DEBUG_DOZE_COMPONENT = "debug.doze.component";
     private static final String ARG_SCROLL_TO_PREFERENCE = "gesture_scroll_to_preference";
+    private static final int PREF_ID_DOUBLE_TAP_POWER = 0;
+    private static final int PREF_ID_DOUBLE_TWIST = 1;
+    private static final int PREF_ID_PICK_UP_AND_NUDG = 2;
+    private static final int PREF_ID_SWIPE_DOWN_FINGERPRINT = 3;
 
     private int mScrollPosition = -1;
     private List<GesturePreference> mPreferences;
@@ -71,7 +75,7 @@
         if (isCameraDoubleTapPowerGestureAvailable(getResources())) {
             int cameraDisabled = Secure.getInt(
                     getContentResolver(), Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
-            addPreference(PREF_KEY_DOUBLE_TAP_POWER, cameraDisabled == 0);
+            addPreference(PREF_KEY_DOUBLE_TAP_POWER, cameraDisabled == 0, PREF_ID_DOUBLE_TAP_POWER);
         } else {
             removePreference(PREF_KEY_DOUBLE_TAP_POWER);
         }
@@ -79,14 +83,15 @@
         // Ambient Display
         if (isDozeAvailable(context)) {
             int dozeEnabled = Secure.getInt(getContentResolver(), Secure.DOZE_ENABLED, 1);
-            addPreference(PREF_KEY_PICK_UP_AND_NUDGE, dozeEnabled != 0);
+            addPreference(PREF_KEY_PICK_UP_AND_NUDGE, dozeEnabled != 0, PREF_ID_DOUBLE_TWIST);
         } else {
             removePreference(PREF_KEY_PICK_UP_AND_NUDGE);
         }
 
         // Fingerprint slide for notifications
         if (isSystemUINavigationAvailable(context)) {
-            addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context));
+            addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context),
+                    PREF_ID_PICK_UP_AND_NUDG);
         } else {
             removePreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT);
         }
@@ -95,7 +100,8 @@
         if (isDoubleTwistAvailable(context)) {
             int doubleTwistEnabled = Secure.getInt(
                     getContentResolver(), Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1);
-            addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0);
+            addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0,
+                    PREF_ID_SWIPE_DOWN_FINGERPRINT);
         } else {
             removePreference(PREF_KEY_DOUBLE_TWIST);
         }
@@ -211,10 +217,11 @@
         return false;
     }
 
-    private void addPreference(String key, boolean enabled) {
+    private void addPreference(String key, boolean enabled, int id) {
         GesturePreference preference = (GesturePreference) findPreference(key);
         preference.setChecked(enabled);
         preference.setOnPreferenceChangeListener(this);
+        preference.loadPreview(getLoaderManager(), id);
         mPreferences.add(preference);
     }