1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey * Copyright (C) 2009 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
193418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guyimport android.graphics.ColorFilter;
20267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guyimport android.util.DisplayMetrics;
21173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport com.android.internal.app.AlertActivity;
22173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport com.android.internal.app.AlertController;
23173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
24173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.app.Activity;
25173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.Context;
26173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.DialogInterface;
27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
28173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.Intent.ShortcutIconResource;
29173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.pm.PackageManager;
30173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.pm.ResolveInfo;
31173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
32173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.res.Resources;
33173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Bitmap;
34173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Canvas;
35173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Paint;
36173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.PaintFlagsDrawFilter;
37173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.PixelFormat;
38173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Rect;
39173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.BitmapDrawable;
40173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.Drawable;
41173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.PaintDrawable;
42173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.os.Bundle;
43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Parcelable;
44173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.view.LayoutInflater;
45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View;
46173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.view.ViewGroup;
47173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.widget.BaseAdapter;
48173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.widget.TextView;
49173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
50173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport java.util.ArrayList;
51173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport java.util.Collections;
52173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport java.util.List;
53afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
54afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
55173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey * Displays a list of all activities matching the incoming
56173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey * {@link Intent#EXTRA_INTENT} query, along with any injected items.
57afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
58173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeypublic class ActivityPicker extends AlertActivity implements
59173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
60173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
61173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
62173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Adapter of items that are displayed in this dialog.
63173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
64173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    private PickAdapter mAdapter;
65173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
66173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
67173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Base {@link Intent} used when building list.
68173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
69173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    private Intent mBaseIntent;
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
71afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
72173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected void onCreate(Bundle savedInstanceState) {
73173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        super.onCreate(savedInstanceState);
74afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
75173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        final Intent intent = getIntent();
76afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
77173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Read base intent from extras, otherwise assume default
78afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Parcelable parcel = intent.getParcelableExtra(Intent.EXTRA_INTENT);
79afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (parcel instanceof Intent) {
80173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mBaseIntent = (Intent) parcel;
81173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        } else {
82173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
83173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
84afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
85173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
86173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Create dialog parameters
87173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        AlertController.AlertParams params = mAlertParams;
88173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mOnClickListener = this;
89173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mOnCancelListener = this;
90afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
91173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Use custom title if provided, otherwise default window title
92173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (intent.hasExtra(Intent.EXTRA_TITLE)) {
93173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            params.mTitle = intent.getStringExtra(Intent.EXTRA_TITLE);
94173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        } else {
95173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            params.mTitle = getTitle();
96173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
97173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
98173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Build list adapter of pickable items
99173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<PickAdapter.Item> items = getItems();
100173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        mAdapter = new PickAdapter(this, items);
101173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mAdapter = mAdapter;
102afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
103173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setupAlert();
104173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
105173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
106173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
107173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Handle clicking of dialog item by passing back
108173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link #getIntentForPosition(int)} in {@link #setResult(int, Intent)}.
109173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
110173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    public void onClick(DialogInterface dialog, int which) {
111173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        Intent intent = getIntentForPosition(which);
112173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setResult(Activity.RESULT_OK, intent);
113173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        finish();
114173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
115173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
116173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
117173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Handle canceled dialog by passing back {@link Activity#RESULT_CANCELED}.
118173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
119173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    public void onCancel(DialogInterface dialog) {
120173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setResult(Activity.RESULT_CANCELED);
121afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        finish();
122afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
123afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
124173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
125173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Build the specific {@link Intent} for a given list position. Convenience
126173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * method that calls through to {@link PickAdapter.Item#getIntent(Intent)}.
127173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
128173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected Intent getIntentForPosition(int position) {
129173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PickAdapter.Item item = (PickAdapter.Item) mAdapter.getItem(position);
130173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        return item.getIntent(mBaseIntent);
131173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
132173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
133173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
134173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Build and return list of items to be shown in dialog. Default
135173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * implementation mixes activities matching {@link #mBaseIntent} from
136173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link #putIntentItems(Intent, List)} with any injected items from
137173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link Intent#EXTRA_SHORTCUT_NAME}. Override this method in subclasses to
138173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * change the items shown.
139173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
140173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected List<PickAdapter.Item> getItems() {
141173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PackageManager packageManager = getPackageManager();
142173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
143173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
144173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Add any injected pick items
145173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        final Intent intent = getIntent();
146173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        ArrayList<String> labels =
147173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);
148173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        ArrayList<ShortcutIconResource> icons =
149173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            intent.getParcelableArrayListExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
150173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
151173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (labels != null && icons != null && labels.size() == icons.size()) {
152173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            for (int i = 0; i < labels.size(); i++) {
153173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                String label = labels.get(i);
154173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                Drawable icon = null;
155173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
156173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                try {
157173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // Try loading icon from requested package
158173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    ShortcutIconResource iconResource = icons.get(i);
159173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    Resources res = packageManager.getResourcesForApplication(
160173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                            iconResource.packageName);
161173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    icon = res.getDrawable(res.getIdentifier(
162173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                            iconResource.resourceName, null, null));
163173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                } catch (NameNotFoundException e) {
164267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    // Ignore
165173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
166173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
167173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                items.add(new PickAdapter.Item(this, label, icon));
168173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
169173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
170173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
171173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Add any intent items if base was given
172173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (mBaseIntent != null) {
173173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            putIntentItems(mBaseIntent, items);
174173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
175173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
176173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        return items;
177173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
178173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
179173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
180173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Fill the given list with any activities matching the base {@link Intent}.
181173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
182173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected void putIntentItems(Intent baseIntent, List<PickAdapter.Item> items) {
183173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PackageManager packageManager = getPackageManager();
184173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent,
185173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                0 /* no flags */);
186173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager));
187173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
188173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        final int listSize = list.size();
189173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        for (int i = 0; i < listSize; i++) {
190173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            ResolveInfo resolveInfo = list.get(i);
191173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            items.add(new PickAdapter.Item(this, packageManager, resolveInfo));
192173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
193173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
194173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
195173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
196173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Adapter which shows the set of activities that can be performed for a
197173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * given {@link Intent}.
198173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
199173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected static class PickAdapter extends BaseAdapter {
200173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
201173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
202173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Item that appears in a {@link PickAdapter} list.
203173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
2040b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public static class Item implements AppWidgetLoader.LabelledItem {
205173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            protected static IconResizer sResizer;
206173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
207173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            protected IconResizer getResizer(Context context) {
208173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (sResizer == null) {
209267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    final Resources resources = context.getResources();
210267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    int size = (int) resources.getDimension(android.R.dimen.app_icon_size);
211267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    sResizer = new IconResizer(size, size, resources.getDisplayMetrics());
212173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
213173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                return sResizer;
214173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
215173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
216173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            CharSequence label;
217173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Drawable icon;
218173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            String packageName;
219173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            String className;
220173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Bundle extras;
221173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
222173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
223173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Create a list item from given label and icon.
224173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
225173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item(Context context, CharSequence label, Drawable icon) {
226173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                this.label = label;
227173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                this.icon = getResizer(context).createIconThumbnail(icon);
228173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
229173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
230173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
231173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Create a list item and fill it with details from the given
232173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * {@link ResolveInfo} object.
233173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
234173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item(Context context, PackageManager pm, ResolveInfo resolveInfo) {
235173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                label = resolveInfo.loadLabel(pm);
236173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (label == null && resolveInfo.activityInfo != null) {
237173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    label = resolveInfo.activityInfo.name;
238173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
239267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
240173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm));
241173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                packageName = resolveInfo.activityInfo.applicationInfo.packageName;
242173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                className = resolveInfo.activityInfo.name;
243173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
244267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
245173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
246173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Build the {@link Intent} described by this item. If this item
247267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy             * can't create a valid {@link android.content.ComponentName}, it will return
248173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
249173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
250173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Intent getIntent(Intent baseIntent) {
251173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                Intent intent = new Intent(baseIntent);
252173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (packageName != null && className != null) {
253173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // Valid package and class, so fill details as normal intent
254173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.setClassName(packageName, className);
255173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    if (extras != null) {
256173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                        intent.putExtras(extras);
257173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    }
258173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                } else {
259173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // No valid package or class, so treat as shortcut with label
260173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
261173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
262173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
263173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                return intent;
264173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
2650b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
2660b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            public CharSequence getLabel() {
2670b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                return label;
2680b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
269173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
270173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
271173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        private final LayoutInflater mInflater;
272267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final List<Item> mItems;
273173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
274173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
275173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Create an adapter for the given items.
276173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
277173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public PickAdapter(Context context, List<Item> items) {
278267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
279173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mItems = items;
280173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
281173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
282173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
283173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
284173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
285173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public int getCount() {
286173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return mItems.size();
287173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
288173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
289173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
290173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
291173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
292173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public Object getItem(int position) {
293173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return mItems.get(position);
294173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
295173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
296173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
297173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
298173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
299173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public long getItemId(int position) {
300173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return position;
301173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
302173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
303173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
304173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
305173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
306173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
307173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            if (convertView == null) {
308267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                convertView = mInflater.inflate(R.layout.pick_item, parent, false);
309173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
310173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
311173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item item = (Item) getItem(position);
312173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            TextView textView = (TextView) convertView;
313173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            textView.setText(item.label);
314173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
315173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
316173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return convertView;
317173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
318173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
319173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
320173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
321173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Utility class to resize icons to match default icon size. Code is mostly
322173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * borrowed from Launcher.
323173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
324173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    private static class IconResizer {
325267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final int mIconWidth;
326267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final int mIconHeight;
327173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
328267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final DisplayMetrics mMetrics;
329173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        private final Rect mOldBounds = new Rect();
330267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final Canvas mCanvas = new Canvas();
331173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
332267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        public IconResizer(int width, int height, DisplayMetrics metrics) {
333173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
334173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    Paint.FILTER_BITMAP_FLAG));
335267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
336267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mMetrics = metrics;
337267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mIconWidth = width;
338267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mIconHeight = height;
339173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
340173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
341173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
342173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Returns a Drawable representing the thumbnail of the specified Drawable.
343173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * The size of the thumbnail is defined by the dimension
344173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * android.R.dimen.launcher_application_icon_size.
345173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
346173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * This method is not thread-safe and should be invoked on the UI thread only.
347173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
348173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * @param icon The icon to get a thumbnail of.
349173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
350173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * @return A thumbnail for the specified icon or the icon itself if the
351173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *         thumbnail could not be created.
352173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
353173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public Drawable createIconThumbnail(Drawable icon) {
354173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            int width = mIconWidth;
355173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            int height = mIconHeight;
356173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
3573418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            if (icon == null) {
3583418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                return new EmptyDrawable(width, height);
359173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
3603418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3613418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            try {
3623418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                if (icon instanceof PaintDrawable) {
3633418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    PaintDrawable painter = (PaintDrawable) icon;
3643418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    painter.setIntrinsicWidth(width);
3653418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    painter.setIntrinsicHeight(height);
3663418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                } else if (icon instanceof BitmapDrawable) {
3673418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    // Ensure the bitmap has a density.
3683418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
3693418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    Bitmap bitmap = bitmapDrawable.getBitmap();
3703418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
3713418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        bitmapDrawable.setTargetDensity(mMetrics);
372173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    }
373173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
3743418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                int iconWidth = icon.getIntrinsicWidth();
3753418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                int iconHeight = icon.getIntrinsicHeight();
3763418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3773418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                if (iconWidth > 0 && iconHeight > 0) {
3783418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    if (width < iconWidth || height < iconHeight) {
3793418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final float ratio = (float) iconWidth / iconHeight;
3803418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3813418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        if (iconWidth > iconHeight) {
3823418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                            height = (int) (width / ratio);
3833418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        } else if (iconHeight > iconWidth) {
3843418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                            width = (int) (height * ratio);
3853418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        }
3863418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3873418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
3883418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                                    Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
3893418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
3903418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Canvas canvas = mCanvas;
3913418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        canvas.setBitmap(thumb);
3923418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // Copy the old bounds to restore them later
3933418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // If we were to do oldBounds = icon.getBounds(),
3943418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // the call to setBounds() that follows would
3953418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // change the same instance and we would lose the
3963418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // old bounds
3973418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        mOldBounds.set(icon.getBounds());
3983418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int x = (mIconWidth - width) / 2;
3993418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int y = (mIconHeight - height) / 2;
4003418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(x, y, x + width, y + height);
4013418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.draw(canvas);
4023418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(mOldBounds);
4033418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        //noinspection deprecation
4043418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon = new BitmapDrawable(thumb);
4053418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        ((BitmapDrawable) icon).setTargetDensity(mMetrics);
406419740de685fecb03a996132508e3fa9d4932383Dianne Hackborn                        canvas.setBitmap(null);
4073418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    } else if (iconWidth < width && iconHeight < height) {
4083418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap.Config c = Bitmap.Config.ARGB_8888;
4093418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
4103418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Canvas canvas = mCanvas;
4113418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        canvas.setBitmap(thumb);
4123418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        mOldBounds.set(icon.getBounds());
4133418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int x = (width - iconWidth) / 2;
4143418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int y = (height - iconHeight) / 2;
4153418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(x, y, x + iconWidth, y + iconHeight);
4163418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.draw(canvas);
4173418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(mOldBounds);
4183418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        //noinspection deprecation
4193418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon = new BitmapDrawable(thumb);
4203418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        ((BitmapDrawable) icon).setTargetDensity(mMetrics);
421419740de685fecb03a996132508e3fa9d4932383Dianne Hackborn                        canvas.setBitmap(null);
4223418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    }
4233418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                }
4243418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4253418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            } catch (Throwable t) {
4263418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                icon = new EmptyDrawable(width, height);
427173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
428173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
429173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return icon;
430173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
431173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
4323418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4333418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy    private static class EmptyDrawable extends Drawable {
4343418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        private final int mWidth;
4353418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        private final int mHeight;
4363418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4373418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        EmptyDrawable(int width, int height) {
4383418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            mWidth = width;
4393418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            mHeight = height;
4403418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4413418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4423418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4433418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getIntrinsicWidth() {
4443418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mWidth;
4453418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4463418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4473418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4483418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getIntrinsicHeight() {
4493418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mHeight;
4503418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4513418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4523418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4533418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getMinimumWidth() {
4543418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mWidth;
4553418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4563418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4573418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4583418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getMinimumHeight() {
4593418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mHeight;
4603418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4613418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4623418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4633418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void draw(Canvas canvas) {
4643418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4653418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4663418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4673418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void setAlpha(int alpha) {
4683418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4693418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4703418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4713418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void setColorFilter(ColorFilter cf) {
4723418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4733418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4743418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4753418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getOpacity() {
4763418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return PixelFormat.TRANSLUCENT;
4773418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4780b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
480