public static View createImageTileView(
      LayoutInflater layoutInflater,
      int position,
      View convertView,
      ViewGroup parent,
      Drawable thumb) {
    View view;

    if (convertView == null) {
      view = layoutInflater.inflate(R.layout.wallpaper_picker_item, parent, false);
    } else {
      view = convertView;
    }

    setWallpaperItemPaddingToZero((FrameLayout) view);

    ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);

    if (thumb != null) {
      image.setImageDrawable(thumb);
      thumb.setDither(true);
    }

    return view;
  }
  private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) {
    mTempWallpaperTiles.add(uri);
    // Add a tile for the image picked from Gallery
    final FrameLayout pickedImageThumbnail =
        (FrameLayout)
            getLayoutInflater().inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
    pickedImageThumbnail.setVisibility(View.GONE);
    setWallpaperItemPaddingToZero(pickedImageThumbnail);
    mWallpapersView.addView(pickedImageThumbnail, 0);

    // Load the thumbnail
    final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
    final Point defaultSize = getDefaultThumbnailSize(this.getResources());
    final Context context = this;
    new AsyncTask<Void, Bitmap, Bitmap>() {
      protected Bitmap doInBackground(Void... args) {
        int rotation = WallpaperCropActivity.getRotationFromExif(context, uri);
        return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
      }

      protected void onPostExecute(Bitmap thumb) {
        if (thumb != null) {
          image.setImageBitmap(thumb);
          Drawable thumbDrawable = image.getDrawable();
          thumbDrawable.setDither(true);
          pickedImageThumbnail.setVisibility(View.VISIBLE);
        } else {
          Log.e(TAG, "Error loading thumbnail for uri=" + uri);
        }
      }
    }.execute();

    UriWallpaperInfo info = new UriWallpaperInfo(uri);
    pickedImageThumbnail.setTag(info);
    info.setView(pickedImageThumbnail);
    addLongPressHandler(pickedImageThumbnail);
    updateTileIndices();
    pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener);
    if (!fromRestore) {
      mThumbnailOnClickListener.onClick(pickedImageThumbnail);
    }
  }
  // called by onCreate; this is subclassed to overwrite WallpaperCropActivity
  protected void init() {
    setContentView(R.layout.wallpaper_picker);

    mCropView = (CropView) findViewById(R.id.cropView);
    mCropView.setVisibility(View.INVISIBLE);

    mWallpaperStrip = findViewById(R.id.wallpaper_strip);
    mCropView.setTouchCallback(
        new CropView.TouchCallback() {
          ViewPropertyAnimator mAnim;

          @Override
          public void onTouchDown() {
            if (mAnim != null) {
              mAnim.cancel();
            }
            if (mWallpaperStrip.getAlpha() == 1f) {
              mIgnoreNextTap = true;
            }
            mAnim = mWallpaperStrip.animate();
            mAnim
                .alpha(0f)
                .setDuration(150)
                .withEndAction(
                    new Runnable() {
                      public void run() {
                        mWallpaperStrip.setVisibility(View.INVISIBLE);
                      }
                    });
            mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
            mAnim.start();
          }

          @Override
          public void onTouchUp() {
            mIgnoreNextTap = false;
          }

          @Override
          public void onTap() {
            boolean ignoreTap = mIgnoreNextTap;
            mIgnoreNextTap = false;
            if (!ignoreTap) {
              if (mAnim != null) {
                mAnim.cancel();
              }
              mWallpaperStrip.setVisibility(View.VISIBLE);
              mAnim = mWallpaperStrip.animate();
              mAnim.alpha(1f).setDuration(150).setInterpolator(new DecelerateInterpolator(0.75f));
              mAnim.start();
            }
          }
        });

    mThumbnailOnClickListener =
        new OnClickListener() {
          public void onClick(View v) {
            if (mActionMode != null) {
              // When CAB is up, clicking toggles the item instead
              if (v.isLongClickable()) {
                mLongClickListener.onLongClick(v);
              }
              return;
            }
            mSetWallpaperButton.setEnabled(true);
            WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
            if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
              selectTile(v);
            }
            info.onClick(WallpaperPickerActivity.this);
          }
        };
    mLongClickListener =
        new View.OnLongClickListener() {
          // Called when the user long-clicks on someView
          public boolean onLongClick(View view) {
            CheckableFrameLayout c = (CheckableFrameLayout) view;
            c.toggle();

            if (mActionMode != null) {
              mActionMode.invalidate();
            } else {
              // Start the CAB using the ActionMode.Callback defined below
              mActionMode = startActionMode(mActionModeCallback);
              int childCount = mWallpapersView.getChildCount();
              for (int i = 0; i < childCount; i++) {
                mWallpapersView.getChildAt(i).setSelected(false);
              }
            }
            return true;
          }
        };

    // Populate the built-in wallpapers
    ArrayList<ResourceWallpaperInfo> wallpapers = findBundledWallpapers();
    mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
    BuiltInWallpapersAdapter ia = new BuiltInWallpapersAdapter(this, wallpapers);
    populateWallpapersFromAdapter(mWallpapersView, ia, false);

    // Populate the saved wallpapers
    mSavedImages = new SavedWallpaperImages(this);
    mSavedImages.loadThumbnailsAndImageIdList();
    populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);

    // Populate the live wallpapers
    final LinearLayout liveWallpapersView = (LinearLayout) findViewById(R.id.live_wallpaper_list);
    final LiveWallpaperListAdapter a = new LiveWallpaperListAdapter(this);
    a.registerDataSetObserver(
        new DataSetObserver() {
          public void onChanged() {
            liveWallpapersView.removeAllViews();
            populateWallpapersFromAdapter(liveWallpapersView, a, false);
            initializeScrollForRtl();
            updateTileIndices();
          }
        });

    // Populate the third-party wallpaper pickers
    final LinearLayout thirdPartyWallpapersView =
        (LinearLayout) findViewById(R.id.third_party_wallpaper_list);
    final ThirdPartyWallpaperPickerListAdapter ta = new ThirdPartyWallpaperPickerListAdapter(this);
    populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false);

    // Add a tile for the Gallery
    LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
    FrameLayout pickImageTile =
        (FrameLayout)
            getLayoutInflater()
                .inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false);
    setWallpaperItemPaddingToZero(pickImageTile);
    masterWallpaperList.addView(pickImageTile, 0);

    // Make its background the last photo taken on external storage
    Bitmap lastPhoto = getThumbnailOfLastPhoto();
    if (lastPhoto != null) {
      ImageView galleryThumbnailBg = (ImageView) pickImageTile.findViewById(R.id.wallpaper_image);
      galleryThumbnailBg.setImageBitmap(getThumbnailOfLastPhoto());
      int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray);
      galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP);
    }

    PickImageInfo pickImageInfo = new PickImageInfo();
    pickImageTile.setTag(pickImageInfo);
    pickImageInfo.setView(pickImageTile);
    pickImageTile.setOnClickListener(mThumbnailOnClickListener);

    // Add a tile for the default wallpaper
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      DefaultWallpaperInfo defaultWallpaperInfo = getDefaultWallpaper();
      if (defaultWallpaperInfo != null) {
        FrameLayout defaultWallpaperTile =
            (FrameLayout)
                createImageTileView(
                    getLayoutInflater(), 0, null, mWallpapersView, defaultWallpaperInfo.mThumb);
        setWallpaperItemPaddingToZero(defaultWallpaperTile);
        defaultWallpaperTile.setTag(defaultWallpaperInfo);
        mWallpapersView.addView(defaultWallpaperTile, 0);
        defaultWallpaperTile.setOnClickListener(mThumbnailOnClickListener);
        defaultWallpaperInfo.setView(defaultWallpaperTile);
      }
    }

    // Select the first item; wait for a layout pass so that we initialize the dimensions of
    // cropView or the defaultWallpaperView first
    mCropView.addOnLayoutChangeListener(
        new OnLayoutChangeListener() {
          @Override
          public void onLayoutChange(
              View v,
              int left,
              int top,
              int right,
              int bottom,
              int oldLeft,
              int oldTop,
              int oldRight,
              int oldBottom) {
            if ((right - left) > 0 && (bottom - top) > 0) {
              if (mSelectedIndex >= 0 && mSelectedIndex < mWallpapersView.getChildCount()) {
                mThumbnailOnClickListener.onClick(mWallpapersView.getChildAt(mSelectedIndex));
                setSystemWallpaperVisiblity(false);
              }
              v.removeOnLayoutChangeListener(this);
            }
          }
        });

    updateTileIndices();

    // Update the scroll for RTL
    initializeScrollForRtl();

    // Create smooth layout transitions for when items are deleted
    final LayoutTransition transitioner = new LayoutTransition();
    transitioner.setDuration(200);
    transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
    transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
    mWallpapersView.setLayoutTransition(transitioner);

    // Action bar
    // Show the custom action bar view
    final ActionBar actionBar = getActionBar();
    actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
    actionBar
        .getCustomView()
        .setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                if (mSelectedTile != null) {
                  WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
                  info.onSave(WallpaperPickerActivity.this);
                } else {
                  // no tile was selected, so we just finish the activity and go back
                  setResult(Activity.RESULT_OK);
                  finish();
                }
              }
            });
    mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);

    // CAB for deleting items
    mActionModeCallback =
        new ActionMode.Callback() {
          // Called when the action mode is created; startActionMode() was called
          @Override
          public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate a menu resource providing context menu items
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.cab_delete_wallpapers, menu);
            return true;
          }

          private int numCheckedItems() {
            int childCount = mWallpapersView.getChildCount();
            int numCheckedItems = 0;
            for (int i = 0; i < childCount; i++) {
              CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
              if (c.isChecked()) {
                numCheckedItems++;
              }
            }
            return numCheckedItems;
          }

          // Called each time the action mode is shown. Always called after onCreateActionMode,
          // but may be called multiple times if the mode is invalidated.
          @Override
          public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            int numCheckedItems = numCheckedItems();
            if (numCheckedItems == 0) {
              mode.finish();
              return true;
            } else {
              mode.setTitle(
                  getResources()
                      .getQuantityString(
                          R.plurals.number_of_items_selected, numCheckedItems, numCheckedItems));
              return true;
            }
          }

          // Called when the user selects a contextual menu item
          @Override
          public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            int itemId = item.getItemId();
            if (itemId == R.id.menu_delete) {
              int childCount = mWallpapersView.getChildCount();
              ArrayList<View> viewsToRemove = new ArrayList<View>();
              boolean selectedTileRemoved = false;
              for (int i = 0; i < childCount; i++) {
                CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
                if (c.isChecked()) {
                  WallpaperTileInfo info = (WallpaperTileInfo) c.getTag();
                  info.onDelete(WallpaperPickerActivity.this);
                  viewsToRemove.add(c);
                  if (i == mSelectedIndex) {
                    selectedTileRemoved = true;
                  }
                }
              }
              for (View v : viewsToRemove) {
                mWallpapersView.removeView(v);
              }
              if (selectedTileRemoved) {
                mSelectedIndex = -1;
                mSelectedTile = null;
                setSystemWallpaperVisiblity(true);
              }
              updateTileIndices();
              mode.finish(); // Action picked, so close the CAB
              return true;
            } else {
              return false;
            }
          }

          // Called when the user exits the action mode
          @Override
          public void onDestroyActionMode(ActionMode mode) {
            int childCount = mWallpapersView.getChildCount();
            for (int i = 0; i < childCount; i++) {
              CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
              c.setChecked(false);
            }
            if (mSelectedTile != null) {
              mSelectedTile.setSelected(true);
            }
            mActionMode = null;
          }
        };
  }