Update Wallpaper picker and fix bug

-Fixed b/3271838
-On a phone, Fragment would not remember its
previous state and crash on rotation
Change-Id: Ida923fba0c7f4622b090e2838fd932328ad68c63
diff --git a/src/com/android/launcher2/WallpaperChooserDialogFragment.java b/src/com/android/launcher2/WallpaperChooserDialogFragment.java
new file mode 100644
index 0000000..10bfc56
--- /dev/null
+++ b/src/com/android/launcher2/WallpaperChooserDialogFragment.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2010 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.launcher2;
+
+import com.android.launcher.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.SpinnerAdapter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class WallpaperChooserDialogFragment extends DialogFragment implements
+        AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+    private static final String TAG = "Launcher.WallpaperChooserDialogFragment";
+    private static final String EMBEDDED_KEY = "com.android.launcher2."
+            + "WallpaperChooserDialogFragment.EMBEDDED_KEY";
+
+    private boolean mEmbedded;
+    private ImageView mImageView = null;
+    private Bitmap mBitmap = null;
+
+    private ArrayList<Integer> mThumbs;
+    private ArrayList<Integer> mImages;
+    private WallpaperLoader mLoader;
+
+    public static WallpaperChooserDialogFragment newInstance() {
+        WallpaperChooserDialogFragment fragment = new WallpaperChooserDialogFragment();
+        fragment.setCancelable(true);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) {
+            mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY);
+        } else {
+            mEmbedded = isInLayout();
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(EMBEDDED_KEY, mEmbedded);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+            mLoader = null;
+        }
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        /* On orientation changes, the dialog is effectively "dismissed" so this is called
+         * when the activity is no longer associated with this dying dialog fragment. We
+         * should just safely ignore this case by checking if getActivity() returns null
+         */
+        Activity activity = getActivity();
+        if (activity != null) {
+            activity.finish();
+        }
+    }
+
+    /* This will only be called when in XLarge mode, since this Fragment is invoked like
+     * a dialog in that mode
+     */
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final View v = getActivity().getLayoutInflater().inflate(
+                R.layout.wallpaper_chooser, null, false);
+
+        GridView gridView = (GridView) v.findViewById(R.id.gallery);
+        gridView.setOnItemClickListener(this);
+        gridView.setAdapter(new ImageAdapter(getActivity()));
+
+        final int viewInset =
+                getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_inset);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setNegativeButton(R.string.wallpaper_cancel, null);
+        builder.setTitle(R.string.wallpaper_dialog_title);
+        builder.setView(gridView, viewInset, viewInset, viewInset, viewInset);
+        return builder.create();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        findWallpapers();
+
+        /* If this fragment is embedded in the layout of this activity, then we should
+         * generate a view to display. Otherwise, a dialog will be created in
+         * onCreateDialog()
+         */
+        if (mEmbedded) {
+            View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
+
+            final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+            gallery.setCallbackDuringFling(false);
+            gallery.setOnItemSelectedListener(this);
+            gallery.setAdapter(new ImageAdapter(getActivity()));
+
+            View setButton = view.findViewById(R.id.set);
+            setButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    selectWallpaper(gallery.getSelectedItemPosition());
+                }
+            });
+            mImageView = (ImageView) view.findViewById(R.id.wallpaper);
+            return view;
+        }
+        return null;
+    }
+
+    private void selectWallpaper(int position) {
+        try {
+            WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(
+                    Context.WALLPAPER_SERVICE);
+            wpm.setResource(mImages.get(position));
+            Activity activity = getActivity();
+            activity.setResult(Activity.RESULT_OK);
+            activity.finish();
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to set wallpaper: " + e);
+        }
+    }
+
+    // Click handler for the Dialog's GridView
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        selectWallpaper(position);
+    }
+
+    // Selection handler for the embedded Gallery view
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel();
+        }
+        mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+    }
+
+    private void findWallpapers() {
+        mThumbs = new ArrayList<Integer>(24);
+        mImages = new ArrayList<Integer>(24);
+
+        final Resources resources = getResources();
+        // Context.getPackageName() may return the "original" package name,
+        // com.android.launcher2; Resources needs the real package name,
+        // com.android.launcher. So we ask Resources for what it thinks the
+        // package name should be.
+        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
+
+        addWallpapers(resources, packageName, R.array.wallpapers);
+        addWallpapers(resources, packageName, R.array.extra_wallpapers);
+    }
+
+    private void addWallpapers(Resources resources, String packageName, int list) {
+        final String[] extras = resources.getStringArray(list);
+        for (String extra : extras) {
+            int res = resources.getIdentifier(extra, "drawable", packageName);
+            if (res != 0) {
+                final int thumbRes = resources.getIdentifier(extra + "_small",
+                        "drawable", packageName);
+
+                if (thumbRes != 0) {
+                    mThumbs.add(thumbRes);
+                    mImages.add(res);
+                    // Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");
+                }
+            }
+        }
+    }
+
+    private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
+        private LayoutInflater mLayoutInflater;
+
+        ImageAdapter(Activity activity) {
+            mLayoutInflater = activity.getLayoutInflater();
+        }
+
+        public int getCount() {
+            return mThumbs.size();
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ImageView image;
+
+            if (convertView == null) {
+                image = (ImageView) mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
+            } else {
+                image = (ImageView) convertView;
+            }
+
+            int thumbRes = mThumbs.get(position);
+            image.setImageResource(thumbRes);
+            Drawable thumbDrawable = image.getDrawable();
+            if (thumbDrawable != null) {
+                thumbDrawable.setDither(true);
+            } else {
+                Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
+                        + position);
+            }
+
+            return image;
+        }
+    }
+
+    class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
+        BitmapFactory.Options mOptions;
+
+        WallpaperLoader() {
+            mOptions = new BitmapFactory.Options();
+            mOptions.inDither = false;
+            mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        }
+
+        @Override
+        protected Bitmap doInBackground(Integer... params) {
+            if (isCancelled()) return null;
+            try {
+                return BitmapFactory.decodeResource(getResources(),
+                        mImages.get(params[0]), mOptions);
+            } catch (OutOfMemoryError e) {
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap b) {
+            if (b == null) return;
+
+            if (!isCancelled() && !mOptions.mCancel) {
+                // Help the GC
+                if (mBitmap != null) {
+                    mBitmap.recycle();
+                }
+
+                // This should always be the case, but check anyways
+                final ImageView view = mImageView;
+                if (view != null) {
+                    view.setImageBitmap(b);
+
+                    mBitmap = b;
+
+                    final Drawable drawable = view.getDrawable();
+                    drawable.setFilterBitmap(true);
+                    drawable.setDither(true);
+
+                    view.postInvalidate();
+                }
+
+                mLoader = null;
+            } else {
+               b.recycle();
+            }
+        }
+
+        void cancel() {
+            mOptions.requestCancelDecode();
+            super.cancel(true);
+        }
+    }
+}
\ No newline at end of file