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
19173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.app.Activity;
20173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.Context;
21173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.DialogInterface;
22afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
23173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.Intent.ShortcutIconResource;
24173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.pm.PackageManager;
25173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
2639b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.content.pm.ResolveInfo;
27173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.content.res.Resources;
28173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Bitmap;
29173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Canvas;
3039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.graphics.ColorFilter;
31173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Paint;
32173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.PaintFlagsDrawFilter;
33173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.PixelFormat;
34173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.Rect;
35173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.BitmapDrawable;
36173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.Drawable;
37173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.graphics.drawable.PaintDrawable;
38173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.os.Bundle;
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Parcelable;
4039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.util.DisplayMetrics;
41173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.view.LayoutInflater;
42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View;
43173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.view.ViewGroup;
44173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.widget.BaseAdapter;
45173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkeyimport android.widget.TextView;
46173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
4739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.internal.app.AlertActivity;
4839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.internal.app.AlertController;
4939b467482d1bf256a111c757e9b7621c6f523271Jason Monk
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;
813f218e8431cb5648bcb46131551c133ba53ef870Jeff Sharkey            mBaseIntent.setFlags(mBaseIntent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
823f218e8431cb5648bcb46131551c133ba53ef870Jeff Sharkey                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
833f218e8431cb5648bcb46131551c133ba53ef870Jeff Sharkey                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
843f218e8431cb5648bcb46131551c133ba53ef870Jeff Sharkey                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION));
85173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        } else {
86173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
87173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
88afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
89173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
90173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Create dialog parameters
91173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        AlertController.AlertParams params = mAlertParams;
92173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mOnClickListener = this;
93173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mOnCancelListener = this;
94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
95173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Use custom title if provided, otherwise default window title
96173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (intent.hasExtra(Intent.EXTRA_TITLE)) {
97173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            params.mTitle = intent.getStringExtra(Intent.EXTRA_TITLE);
98173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        } else {
99173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            params.mTitle = getTitle();
100173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
101173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
102173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Build list adapter of pickable items
103173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<PickAdapter.Item> items = getItems();
104173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        mAdapter = new PickAdapter(this, items);
105173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        params.mAdapter = mAdapter;
106afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
107173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setupAlert();
108173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
109173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
110173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
111173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Handle clicking of dialog item by passing back
112173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link #getIntentForPosition(int)} in {@link #setResult(int, Intent)}.
113173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
114173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    public void onClick(DialogInterface dialog, int which) {
115173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        Intent intent = getIntentForPosition(which);
116173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setResult(Activity.RESULT_OK, intent);
117173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        finish();
118173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
119173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
120173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
121173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Handle canceled dialog by passing back {@link Activity#RESULT_CANCELED}.
122173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
123173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    public void onCancel(DialogInterface dialog) {
124173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        setResult(Activity.RESULT_CANCELED);
125afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        finish();
126afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
127afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
128173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
129173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Build the specific {@link Intent} for a given list position. Convenience
130173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * method that calls through to {@link PickAdapter.Item#getIntent(Intent)}.
131173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
132173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected Intent getIntentForPosition(int position) {
133173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PickAdapter.Item item = (PickAdapter.Item) mAdapter.getItem(position);
134173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        return item.getIntent(mBaseIntent);
135173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
136173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
137173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
138173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Build and return list of items to be shown in dialog. Default
139173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * implementation mixes activities matching {@link #mBaseIntent} from
140173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link #putIntentItems(Intent, List)} with any injected items from
141173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * {@link Intent#EXTRA_SHORTCUT_NAME}. Override this method in subclasses to
142173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * change the items shown.
143173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
144173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected List<PickAdapter.Item> getItems() {
145173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PackageManager packageManager = getPackageManager();
146173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
147173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
148173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Add any injected pick items
149173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        final Intent intent = getIntent();
150173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        ArrayList<String> labels =
151173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);
152173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        ArrayList<ShortcutIconResource> icons =
153173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            intent.getParcelableArrayListExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
154173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
155173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (labels != null && icons != null && labels.size() == icons.size()) {
156173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            for (int i = 0; i < labels.size(); i++) {
157173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                String label = labels.get(i);
158173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                Drawable icon = null;
159173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
160173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                try {
161173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // Try loading icon from requested package
162173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    ShortcutIconResource iconResource = icons.get(i);
163173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    Resources res = packageManager.getResourcesForApplication(
164173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                            iconResource.packageName);
165173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    icon = res.getDrawable(res.getIdentifier(
1660ba89bd54c4b44b3803342da10b0c08b0bf76ad4Alan Viverette                            iconResource.resourceName, null, null), null);
167173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                } catch (NameNotFoundException e) {
168267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    // Ignore
169173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
170173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
171173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                items.add(new PickAdapter.Item(this, label, icon));
172173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
173173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
174173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
175173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        // Add any intent items if base was given
176173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        if (mBaseIntent != null) {
177173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            putIntentItems(mBaseIntent, items);
178173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
179173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
180173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        return items;
181173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
182173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
183173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
184173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Fill the given list with any activities matching the base {@link Intent}.
185173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
186173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected void putIntentItems(Intent baseIntent, List<PickAdapter.Item> items) {
187173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        PackageManager packageManager = getPackageManager();
188173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent,
189173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                0 /* no flags */);
190173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager));
191173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
192173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        final int listSize = list.size();
193173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        for (int i = 0; i < listSize; i++) {
194173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            ResolveInfo resolveInfo = list.get(i);
195173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            items.add(new PickAdapter.Item(this, packageManager, resolveInfo));
196173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
197173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
198173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
199173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
200173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Adapter which shows the set of activities that can be performed for a
201173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * given {@link Intent}.
202173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
203173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    protected static class PickAdapter extends BaseAdapter {
204173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
205173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
206173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Item that appears in a {@link PickAdapter} list.
207173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
2080b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public static class Item implements AppWidgetLoader.LabelledItem {
209173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            protected static IconResizer sResizer;
210173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
211173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            protected IconResizer getResizer(Context context) {
212173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (sResizer == null) {
213267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    final Resources resources = context.getResources();
214267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    int size = (int) resources.getDimension(android.R.dimen.app_icon_size);
215267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                    sResizer = new IconResizer(size, size, resources.getDisplayMetrics());
216173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
217173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                return sResizer;
218173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
219173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
220173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            CharSequence label;
221173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Drawable icon;
222173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            String packageName;
223173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            String className;
224173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Bundle extras;
225173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
226173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
227173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Create a list item from given label and icon.
228173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
229173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item(Context context, CharSequence label, Drawable icon) {
230173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                this.label = label;
231173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                this.icon = getResizer(context).createIconThumbnail(icon);
232173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
233173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
234173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
235173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Create a list item and fill it with details from the given
236173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * {@link ResolveInfo} object.
237173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
238173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item(Context context, PackageManager pm, ResolveInfo resolveInfo) {
239173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                label = resolveInfo.loadLabel(pm);
240173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (label == null && resolveInfo.activityInfo != null) {
241173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    label = resolveInfo.activityInfo.name;
242173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
243267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
244173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm));
245173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                packageName = resolveInfo.activityInfo.applicationInfo.packageName;
246173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                className = resolveInfo.activityInfo.name;
247173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
248267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
249173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            /**
250173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * Build the {@link Intent} described by this item. If this item
251267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy             * can't create a valid {@link android.content.ComponentName}, it will return
252173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
253173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey             */
254173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Intent getIntent(Intent baseIntent) {
255173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                Intent intent = new Intent(baseIntent);
256173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                if (packageName != null && className != null) {
257173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // Valid package and class, so fill details as normal intent
258173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.setClassName(packageName, className);
259173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    if (extras != null) {
260173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                        intent.putExtras(extras);
261173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    }
262173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                } else {
263173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    // No valid package or class, so treat as shortcut with label
264173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
265173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
266173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
267173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                return intent;
268173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
2690b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
2700b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            public CharSequence getLabel() {
2710b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                return label;
2720b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
273173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
274173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
275173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        private final LayoutInflater mInflater;
276267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final List<Item> mItems;
277173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
278173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
279173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Create an adapter for the given items.
280173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
281173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public PickAdapter(Context context, List<Item> items) {
282267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
283173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mItems = items;
284173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
285173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
286173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
287173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
288173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
289173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public int getCount() {
290173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return mItems.size();
291173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
292173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
293173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
294173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
295173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
296173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public Object getItem(int position) {
297173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return mItems.get(position);
298173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
299173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
300173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
301173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
302173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
303173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public long getItemId(int position) {
304173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return position;
305173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
306173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
307173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
308173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * {@inheritDoc}
309173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
310173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
311173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            if (convertView == null) {
312267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy                convertView = mInflater.inflate(R.layout.pick_item, parent, false);
313173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
314173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
315173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            Item item = (Item) getItem(position);
316173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            TextView textView = (TextView) convertView;
317173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            textView.setText(item.label);
318173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
319173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
320173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return convertView;
321173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
322173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
323173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
324173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    /**
325173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * Utility class to resize icons to match default icon size. Code is mostly
326173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     * borrowed from Launcher.
327173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey     */
328173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    private static class IconResizer {
329267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final int mIconWidth;
330267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final int mIconHeight;
331173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
332267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final DisplayMetrics mMetrics;
333173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        private final Rect mOldBounds = new Rect();
334267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        private final Canvas mCanvas = new Canvas();
335173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
336267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy        public IconResizer(int width, int height, DisplayMetrics metrics) {
337173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
338173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    Paint.FILTER_BITMAP_FLAG));
339267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy
340267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mMetrics = metrics;
341267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mIconWidth = width;
342267a47e683f744e4d77b9aa6aec017e5068bb443Romain Guy            mIconHeight = height;
343173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
344173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
345173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        /**
346173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * Returns a Drawable representing the thumbnail of the specified Drawable.
347173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * The size of the thumbnail is defined by the dimension
348173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * android.R.dimen.launcher_application_icon_size.
349173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
350173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * This method is not thread-safe and should be invoked on the UI thread only.
351173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
352173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * @param icon The icon to get a thumbnail of.
353173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *
354173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         * @return A thumbnail for the specified icon or the icon itself if the
355173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         *         thumbnail could not be created.
356173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey         */
357173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        public Drawable createIconThumbnail(Drawable icon) {
358173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            int width = mIconWidth;
359173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            int height = mIconHeight;
360173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
3613418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            if (icon == null) {
3623418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                return new EmptyDrawable(width, height);
363173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
3643418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3653418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            try {
3663418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                if (icon instanceof PaintDrawable) {
3673418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    PaintDrawable painter = (PaintDrawable) icon;
3683418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    painter.setIntrinsicWidth(width);
3693418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    painter.setIntrinsicHeight(height);
3703418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                } else if (icon instanceof BitmapDrawable) {
3713418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    // Ensure the bitmap has a density.
3723418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
3733418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    Bitmap bitmap = bitmapDrawable.getBitmap();
3743418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
3753418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        bitmapDrawable.setTargetDensity(mMetrics);
376173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                    }
377173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey                }
3783418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                int iconWidth = icon.getIntrinsicWidth();
3793418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                int iconHeight = icon.getIntrinsicHeight();
3803418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3813418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                if (iconWidth > 0 && iconHeight > 0) {
3823418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    if (width < iconWidth || height < iconHeight) {
3833418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final float ratio = (float) iconWidth / iconHeight;
3843418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3853418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        if (iconWidth > iconHeight) {
3863418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                            height = (int) (width / ratio);
3873418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        } else if (iconHeight > iconWidth) {
3883418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                            width = (int) (height * ratio);
3893418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        }
3903418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
3913418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
3923418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                                    Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
3933418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
3943418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Canvas canvas = mCanvas;
3953418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        canvas.setBitmap(thumb);
3963418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // Copy the old bounds to restore them later
3973418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // If we were to do oldBounds = icon.getBounds(),
3983418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // the call to setBounds() that follows would
3993418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // change the same instance and we would lose the
4003418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        // old bounds
4013418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        mOldBounds.set(icon.getBounds());
4023418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int x = (mIconWidth - width) / 2;
4033418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int y = (mIconHeight - height) / 2;
4043418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(x, y, x + width, y + height);
4053418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.draw(canvas);
4063418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(mOldBounds);
4073418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        //noinspection deprecation
4083418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon = new BitmapDrawable(thumb);
4093418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        ((BitmapDrawable) icon).setTargetDensity(mMetrics);
410419740de685fecb03a996132508e3fa9d4932383Dianne Hackborn                        canvas.setBitmap(null);
4113418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    } else if (iconWidth < width && iconHeight < height) {
4123418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap.Config c = Bitmap.Config.ARGB_8888;
4133418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
4143418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final Canvas canvas = mCanvas;
4153418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        canvas.setBitmap(thumb);
4163418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        mOldBounds.set(icon.getBounds());
4173418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int x = (width - iconWidth) / 2;
4183418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        final int y = (height - iconHeight) / 2;
4193418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(x, y, x + iconWidth, y + iconHeight);
4203418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.draw(canvas);
4213418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon.setBounds(mOldBounds);
4223418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        //noinspection deprecation
4233418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        icon = new BitmapDrawable(thumb);
4243418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                        ((BitmapDrawable) icon).setTargetDensity(mMetrics);
425419740de685fecb03a996132508e3fa9d4932383Dianne Hackborn                        canvas.setBitmap(null);
4263418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                    }
4273418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                }
4283418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4293418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            } catch (Throwable t) {
4303418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy                icon = new EmptyDrawable(width, height);
431173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            }
432173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey
433173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey            return icon;
434173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey        }
435173545e63b5078d9d0e194552e39bb5e9f358082Jeffrey Sharkey    }
4363418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4373418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy    private static class EmptyDrawable extends Drawable {
4383418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        private final int mWidth;
4393418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        private final int mHeight;
4403418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4413418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        EmptyDrawable(int width, int height) {
4423418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            mWidth = width;
4433418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            mHeight = height;
4443418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4453418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4463418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4473418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getIntrinsicWidth() {
4483418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mWidth;
4493418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4503418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4513418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4523418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getIntrinsicHeight() {
4533418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mHeight;
4543418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4553418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4563418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4573418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getMinimumWidth() {
4583418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mWidth;
4593418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4603418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4613418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4623418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getMinimumHeight() {
4633418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return mHeight;
4643418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4653418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4663418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4673418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void draw(Canvas canvas) {
4683418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4693418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4703418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4713418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void setAlpha(int alpha) {
4723418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4733418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4743418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4753418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public void setColorFilter(ColorFilter cf) {
4763418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4773418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy
4783418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        @Override
4793418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        public int getOpacity() {
4803418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy            return PixelFormat.TRANSLUCENT;
4813418cb4df5c1ada031ca06d84374abe6a16e6dd3Romain Guy        }
4820b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
483afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
484