10b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka/*
20b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * Copyright (C) 2012 The Android Open Source Project
30b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka *
40b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
50b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * you may not use this file except in compliance with the License.
60b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * You may obtain a copy of the License at
70b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka *
80b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
90b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka *
100b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * Unless required by applicable law or agreed to in writing, software
110b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
120b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * See the License for the specific language governing permissions and
140b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * limitations under the License.
150b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka */
160b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
170b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkapackage com.android.settings;
180b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
190b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.app.Activity;
204119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.app.ActivityManager;
214119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.app.LauncherActivity.IconResizer;
220b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.appwidget.AppWidgetHost;
230b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.appwidget.AppWidgetManager;
240b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.appwidget.AppWidgetProviderInfo;
250b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.content.ActivityNotFoundException;
264119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.content.ComponentName;
270b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.content.Context;
280b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.content.Intent;
290b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.content.pm.PackageManager;
300b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.content.res.Resources;
310b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.graphics.Bitmap;
324119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.graphics.Bitmap.Config;
330b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.graphics.Canvas;
340b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.graphics.Paint;
350b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.graphics.Rect;
360b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.graphics.drawable.Drawable;
374119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.os.AsyncTask;
380b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.os.Bundle;
390b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.os.IBinder;
400b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.os.RemoteException;
410b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.os.ServiceManager;
420b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.util.DisplayMetrics;
430b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.util.Log;
440b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.view.IWindowManager;
450b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.view.LayoutInflater;
460b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.view.View;
470b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.view.ViewGroup;
480b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.widget.AdapterView;
490b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.widget.BaseAdapter;
500b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.widget.GridView;
514119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport android.widget.ImageView;
520b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.widget.TextView;
530b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport android.widget.Toast;
540b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
550b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport com.android.internal.widget.LockPatternUtils;
560b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
574119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurkaimport java.lang.ref.WeakReference;
580b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkaimport java.util.List;
590b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
600b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka/**
610b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any
620b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * injected special widgets specified through
630b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and
640b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}.
650b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * <p>
660b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * When an installed {@link AppWidgetProviderInfo} is selected, this activity
670b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID},
680b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka * otherwise it will return the requested extras.
690b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka */
700b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurkapublic class KeyguardAppWidgetPickActivity extends Activity
710b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    implements GridView.OnItemClickListener,
720b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        AppWidgetLoader.ItemConstructor<KeyguardAppWidgetPickActivity.Item> {
730b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private static final String TAG = "KeyguardAppWidgetPickActivity";
740b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private static final int REQUEST_PICK_APPWIDGET = 126;
750b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private static final int REQUEST_CREATE_APPWIDGET = 127;
760b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
770b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private AppWidgetLoader<Item> mAppWidgetLoader;
780b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private List<Item> mItems;
790b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private GridView mGridView;
804119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka    private AppWidgetAdapter mAppWidgetAdapter;
810b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private AppWidgetManager mAppWidgetManager;
820b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private int mAppWidgetId;
830b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    // Might make it possible to make this be false in future
840b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private boolean mAddingToKeyguard = true;
850b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private Intent mResultData;
860b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    private LockPatternUtils mLockPatternUtils;
87ab3472f5946c5dc3193c29513e31be7309ece378Michael Jurka    private Bundle mExtraConfigureOptions;
880b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
890b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    @Override
900b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    protected void onCreate(Bundle savedInstanceState) {
91a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        setContentView(R.layout.keyguard_appwidget_picker_layout);
920b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        super.onCreate(savedInstanceState);
930b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
940b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        // Set default return data
950b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        setResultData(RESULT_CANCELED, null);
960b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
970b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        // Read the appWidgetId passed our direction, otherwise bail if not found
980b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        final Intent intent = getIntent();
990b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
1000b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
1010b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    AppWidgetManager.INVALID_APPWIDGET_ID);
1020b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } else {
1030b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            finish();
1040b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
105ab3472f5946c5dc3193c29513e31be7309ece378Michael Jurka        mExtraConfigureOptions = intent.getBundleExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
1060b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1070b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mGridView = (GridView) findViewById(R.id.widget_list);
108a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        DisplayMetrics dm = new DisplayMetrics();
109a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        getWindowManager().getDefaultDisplay().getMetrics(dm);
110a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        int maxGridWidth = getResources().getDimensionPixelSize(
111a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka                R.dimen.keyguard_appwidget_picker_max_width);
112a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka
113a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        if (maxGridWidth < dm.widthPixels) {
114a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka            mGridView.getLayoutParams().width = maxGridWidth;
115a487bca4700a9dbd5d5d72913d0265ae86815edfMichael Jurka        }
1160b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mAppWidgetManager = AppWidgetManager.getInstance(this);
1170b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mAppWidgetLoader = new AppWidgetLoader<Item>(this, mAppWidgetManager, this);
1180b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mItems = mAppWidgetLoader.getItems(getIntent());
1194119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        mAppWidgetAdapter = new AppWidgetAdapter(this, mItems);
1204119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        mGridView.setAdapter(mAppWidgetAdapter);
1210b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mGridView.setOnItemClickListener(this);
1220b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1230b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mLockPatternUtils = new LockPatternUtils(this); // TEMP-- we want to delete this
1240b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
1250b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1260b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    /**
1270b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     * Convenience method for setting the result code and intent. This method
1280b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that
1290b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     * most hosts expect returned.
1300b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     */
1310b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    void setResultData(int code, Intent intent) {
1320b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        Intent result = intent != null ? intent : new Intent();
1330b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
1340b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mResultData = result;
1350b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        setResult(code, result);
1360b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
1370b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1380b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    /**
1390b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     * Item that appears in the AppWidget picker grid.
1400b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     */
1410b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    public static class Item implements AppWidgetLoader.LabelledItem {
1420b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        protected static IconResizer sResizer;
1430b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1444119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
1450b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        CharSequence label;
1464119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        int appWidgetPreviewId;
1474119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        int iconId;
1480b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        String packageName;
1490b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        String className;
1500b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        Bundle extras;
1514119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        private WidgetPreviewLoader mWidgetPreviewLoader;
1524119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        private Context mContext;
1530b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1540b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
1550b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * Create a list item from given label and icon.
1560b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
1574119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        Item(Context context, CharSequence label) {
1580b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            this.label = label;
1594119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            mContext = context;
1600b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
1610b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1624119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        void loadWidgetPreview(ImageView v) {
1634119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            mWidgetPreviewLoader = new WidgetPreviewLoader(mContext, v);
1644119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            mWidgetPreviewLoader.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
1654119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        }
1660b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1674119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        void cancelLoadingWidgetPreview() {
1684119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            if (mWidgetPreviewLoader != null) {
1694119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mWidgetPreviewLoader.cancel(false);
1704119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mWidgetPreviewLoader = null;
1714119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
1720b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
1730b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1740b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
1750b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * Build the {@link Intent} described by this item. If this item
1760b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * can't create a valid {@link android.content.ComponentName}, it will return
1770b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
1780b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
1790b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        Intent getIntent() {
1800b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            Intent intent = new Intent();
1810b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            if (packageName != null && className != null) {
1820b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // Valid package and class, so fill details as normal intent
1830b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                intent.setClassName(packageName, className);
1840b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                if (extras != null) {
1850b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    intent.putExtras(extras);
1860b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                }
1870b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            } else {
1880b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // No valid package or class, so treat as shortcut with label
1890b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
1900b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
1910b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
1920b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return intent;
1930b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
1940b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1950b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public CharSequence getLabel() {
1960b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return label;
1970b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
1980b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
1994119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        class WidgetPreviewLoader extends AsyncTask<Void, Bitmap, Void> {
2004119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private Resources mResources;
2014119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private PackageManager mPackageManager;
2024119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private int mIconDpi;
2034119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private ImageView mView;
2044119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public WidgetPreviewLoader(Context context, ImageView v) {
2054119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                super();
2064119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mResources = context.getResources();
2074119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mPackageManager = context.getPackageManager();
2084119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                ActivityManager activityManager =
2094119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
2104119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mIconDpi = activityManager.getLauncherLargeIconDensity();
2114119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mView = v;
2124119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2134119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public Void doInBackground(Void... params) {
2144119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (!isCancelled()) {
2154119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    int appWidgetPreviewWidth =
2164119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            mResources.getDimensionPixelSize(R.dimen.appwidget_preview_width);
2174119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    int appWidgetPreviewHeight =
2184119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            mResources.getDimensionPixelSize(R.dimen.appwidget_preview_height);
2194119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    Bitmap b = getWidgetPreview(new ComponentName(packageName, className),
2204119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            appWidgetPreviewId, iconId,
2214119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            appWidgetPreviewWidth, appWidgetPreviewHeight);
2224119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    publishProgress(b);
2234119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2244119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                return null;
2254119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2264119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public void onProgressUpdate(Bitmap... values) {
2274119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (!isCancelled()) {
2284119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    Bitmap b = values[0];
2294119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    mView.setImageBitmap(b);
2304119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2314119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2324119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            abstract class WeakReferenceThreadLocal<T> {
2334119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                private ThreadLocal<WeakReference<T>> mThreadLocal;
2344119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                public WeakReferenceThreadLocal() {
2354119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    mThreadLocal = new ThreadLocal<WeakReference<T>>();
2364119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2370b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
2384119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                abstract T initialValue();
2394119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2404119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                public void set(T t) {
2414119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    mThreadLocal.set(new WeakReference<T>(t));
2424119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2434119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2444119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                public T get() {
2454119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    WeakReference<T> reference = mThreadLocal.get();
2464119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    T obj;
2474119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    if (reference == null) {
2484119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        obj = initialValue();
2494119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        mThreadLocal.set(new WeakReference<T>(obj));
2504119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        return obj;
2514119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    } else {
2524119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        obj = reference.get();
2534119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        if (obj == null) {
2544119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            obj = initialValue();
2554119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            mThreadLocal.set(new WeakReference<T>(obj));
2564119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        }
2574119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        return obj;
2584119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    }
2594119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2604119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2614119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2624119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            class CanvasCache extends WeakReferenceThreadLocal<Canvas> {
2634119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                @Override
2644119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                protected Canvas initialValue() {
2654119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    return new Canvas();
2664119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2674119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2684119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2694119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            class PaintCache extends WeakReferenceThreadLocal<Paint> {
2704119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                @Override
2714119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                protected Paint initialValue() {
2724119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    return null;
2734119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2744119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2754119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2764119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            class BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
2774119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                @Override
2784119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                protected Bitmap initialValue() {
2794119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    return null;
2800b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                }
2810b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
2824119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2834119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            class RectCache extends WeakReferenceThreadLocal<Rect> {
2844119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                @Override
2854119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                protected Rect initialValue() {
2864119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    return new Rect();
2874119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
2884119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
2894119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2904119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            // Used for drawing widget previews
2914119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            CanvasCache sCachedAppWidgetPreviewCanvas = new CanvasCache();
2924119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            RectCache sCachedAppWidgetPreviewSrcRect = new RectCache();
2934119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            RectCache sCachedAppWidgetPreviewDestRect = new RectCache();
2944119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            PaintCache sCachedAppWidgetPreviewPaint = new PaintCache();
2954119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
2964119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
2974119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    int iconId, int maxWidth, int maxHeight) {
2984119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                // Load the preview image if possible
2994119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                String packageName = provider.getPackageName();
3004119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
3014119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (maxHeight < 0) maxHeight = Integer.MAX_VALUE;
3024119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3034119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3044119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                int appIconSize = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
3054119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3064119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                Drawable drawable = null;
3074119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (previewImage != 0) {
3084119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    drawable = mPackageManager.getDrawable(packageName, previewImage, null);
3094119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    if (drawable == null) {
3104119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        Log.w(TAG, "Can't load widget preview drawable 0x" +
3114119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                                Integer.toHexString(previewImage) + " for provider: " + provider);
3124119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    }
3134119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
3144119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3154119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                int bitmapWidth;
3164119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                int bitmapHeight;
3174119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                Bitmap defaultPreview = null;
3184119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                boolean widgetPreviewExists = (drawable != null);
3194119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (widgetPreviewExists) {
3204119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    bitmapWidth = drawable.getIntrinsicWidth();
3214119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    bitmapHeight = drawable.getIntrinsicHeight();
3224119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                } else {
3234119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    // Generate a preview image if we couldn't load one
324a108d9fc0edd3b4f741fae595e35a246fbc700ffMichael Jurka                    bitmapWidth = appIconSize;
325a108d9fc0edd3b4f741fae595e35a246fbc700ffMichael Jurka                    bitmapHeight = appIconSize;
3264119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
3274119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            Config.ARGB_8888);
3284119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3294119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    try {
3304119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        Drawable icon = null;
3314119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        if (iconId > 0)
3324119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            icon = getFullResIcon(packageName, iconId);
3334119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        if (icon != null) {
334a108d9fc0edd3b4f741fae595e35a246fbc700ffMichael Jurka                            renderDrawableToBitmap(icon, defaultPreview, 0,
335a108d9fc0edd3b4f741fae595e35a246fbc700ffMichael Jurka                                    0, appIconSize, appIconSize);
3364119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        }
3374119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    } catch (Resources.NotFoundException e) {
3384119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    }
3394119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
3404119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3414119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                // Scale to fit width only - let the widget preview be clipped in the
3424119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                // vertical dimension
3434119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                float scale = 1f;
3444119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (bitmapWidth > maxWidth) {
3454119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    scale = maxWidth / (float) bitmapWidth;
3464119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
3474119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                int finalPreviewWidth = (int) (scale * bitmapWidth);
3484119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                int finalPreviewHeight = (int) (scale * bitmapHeight);
3494119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3504119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                bitmapWidth = finalPreviewWidth;
3514119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                bitmapHeight = Math.min(finalPreviewHeight, maxHeight);
3524119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3534119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
3544119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        Config.ARGB_8888);
3554119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3564119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                // Draw the scaled preview into the final bitmap
3574119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (widgetPreviewExists) {
3584119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    renderDrawableToBitmap(drawable, preview, 0, 0, finalPreviewWidth,
3594119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                            finalPreviewHeight);
3604119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                } else {
3614119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    final Canvas c = sCachedAppWidgetPreviewCanvas.get();
3624119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    final Rect src = sCachedAppWidgetPreviewSrcRect.get();
3634119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    final Rect dest = sCachedAppWidgetPreviewDestRect.get();
3644119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    c.setBitmap(preview);
3654119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
3664119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    dest.set(0, 0, finalPreviewWidth, finalPreviewHeight);
3674119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3684119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    Paint p = sCachedAppWidgetPreviewPaint.get();
3694119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    if (p == null) {
3704119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        p = new Paint();
3714119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        p.setFilterBitmap(true);
3724119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        sCachedAppWidgetPreviewPaint.set(p);
3734119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    }
3744119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    c.drawBitmap(defaultPreview, src, dest, p);
3754119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    c.setBitmap(null);
3764119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
3774119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                return preview;
3784119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
3794119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public Drawable getFullResDefaultActivityIcon() {
3804119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                return getFullResIcon(Resources.getSystem(),
3814119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        android.R.mipmap.sym_def_app_icon);
3824119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
3834119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3844119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public Drawable getFullResIcon(Resources resources, int iconId) {
3854119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                Drawable d;
3864119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                try {
3874119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    d = resources.getDrawableForDensity(iconId, mIconDpi);
3884119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                } catch (Resources.NotFoundException e) {
3894119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    d = null;
3904119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
3914119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3924119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                return (d != null) ? d : getFullResDefaultActivityIcon();
3934119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
3944119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
3954119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            public Drawable getFullResIcon(String packageName, int iconId) {
3964119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                Resources resources;
3974119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                try {
3984119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    resources = mPackageManager.getResourcesForApplication(packageName);
3994119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                } catch (PackageManager.NameNotFoundException e) {
4004119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    resources = null;
4014119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
4024119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (resources != null) {
4034119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    if (iconId != 0) {
4044119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                        return getFullResIcon(resources, iconId);
4054119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    }
4064119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
4074119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                return getFullResDefaultActivityIcon();
4084119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
4094119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
4104119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
4114119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
4124119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
4134119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
4144119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
4154119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    float scale) {
4164119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                if (bitmap != null) {
4174119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    Canvas c = new Canvas(bitmap);
4184119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    c.scale(scale, scale);
4194119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    Rect oldBounds = d.copyBounds();
4204119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    d.setBounds(x, y, x + w, y + h);
4214119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    d.draw(c);
4224119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    d.setBounds(oldBounds); // Restore the bounds
4234119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                    c.setBitmap(null);
4244119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                }
4250b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
4260b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4274119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka    }
4284119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
4294119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka    @Override
4304119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka    public Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) {
4314119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        CharSequence label = info.label;
4320b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4334119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        Item item = new Item(context, label);
4344119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        item.appWidgetPreviewId = info.previewImage;
4354119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        item.iconId = info.icon;
4360b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        item.packageName = info.provider.getPackageName();
4370b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        item.className = info.provider.getClassName();
4380b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        item.extras = extras;
4390b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        return item;
4400b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
4410b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4420b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    protected static class AppWidgetAdapter extends BaseAdapter {
4430b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        private final LayoutInflater mInflater;
4440b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        private final List<Item> mItems;
4450b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4460b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
4470b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * Create an adapter for the given items.
4480b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
4490b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public AppWidgetAdapter(Context context, List<Item> items) {
4500b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
4510b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            mItems = items;
4520b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4530b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4540b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
4550b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * {@inheritDoc}
4560b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
4570b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public int getCount() {
4580b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return mItems.size();
4590b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4600b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4610b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
4620b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * {@inheritDoc}
4630b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
4640b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public Object getItem(int position) {
4650b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return mItems.get(position);
4660b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4670b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4680b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
4690b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * {@inheritDoc}
4700b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
4710b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public long getItemId(int position) {
4720b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return position;
4730b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4740b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4750b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        /**
4760b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         * {@inheritDoc}
4770b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka         */
4780b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        public View getView(int position, View convertView, ViewGroup parent) {
4790b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            if (convertView == null) {
4800b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                convertView = mInflater.inflate(R.layout.keyguard_appwidget_item, parent, false);
4810b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
4820b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4830b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            Item item = (Item) getItem(position);
4844119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            TextView textView = (TextView) convertView.findViewById(R.id.label);
4850b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            textView.setText(item.label);
4864119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
4874119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            iconView.setImageDrawable(null);
4884119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            item.loadWidgetPreview(iconView);
4890b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            return convertView;
4900b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
4914119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka
4924119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        public void cancelAllWidgetPreviewLoaders() {
4934119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            for (int i = 0; i < mItems.size(); i++) {
4944119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka                mItems.get(i).cancelLoadingWidgetPreview();
4954119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            }
4964119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        }
4970b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
4980b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
4990b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    /**
5000b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     * {@inheritDoc}
5010b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka     */
5020b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    @Override
5030b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
5040b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        Item item = mItems.get(position);
5050b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        Intent intent = item.getIntent();
5060b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5070b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        int result;
5080b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        if (item.extras != null) {
5090b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            // If these extras are present it's because this entry is custom.
5100b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            // Don't try to bind it, just pass it back to the app.
5110b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            result = RESULT_OK;
5120b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            setResultData(result, intent);
5130b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } else {
5140b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            try {
515f5336fd114e557fce06197041aab70217308fe90Michael Jurka                if (mAddingToKeyguard && mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
516f5336fd114e557fce06197041aab70217308fe90Michael Jurka                    // Found in KeyguardHostView.java
517f5336fd114e557fce06197041aab70217308fe90Michael Jurka                    final int KEYGUARD_HOST_ID = 0x4B455947;
518f5336fd114e557fce06197041aab70217308fe90Michael Jurka                    mAppWidgetId = AppWidgetHost.allocateAppWidgetIdForSystem(KEYGUARD_HOST_ID);
519f5336fd114e557fce06197041aab70217308fe90Michael Jurka                }
520ab3472f5946c5dc3193c29513e31be7309ece378Michael Jurka                mAppWidgetManager.bindAppWidgetId(
521ab3472f5946c5dc3193c29513e31be7309ece378Michael Jurka                        mAppWidgetId, intent.getComponent(), mExtraConfigureOptions);
5220b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                result = RESULT_OK;
5230b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            } catch (IllegalArgumentException e) {
5240b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // This is thrown if they're already bound, or otherwise somehow
5250b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // bogus.  Set the result to canceled, and exit.  The app *should*
5260b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // clean up at this point.  We could pass the error along, but
5270b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // it's not clear that that's useful -- the widget will simply not
5280b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                // appear.
5290b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                result = RESULT_CANCELED;
5300b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
5310b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            setResultData(result, null);
5320b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
5330b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        if (mAddingToKeyguard) {
5340b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            onActivityResult(REQUEST_PICK_APPWIDGET, result, mResultData);
5350b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } else {
5360b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            finish();
5370b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
5380b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
5390b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5400b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    protected void onDestroy() {
5414119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        if (mAppWidgetAdapter != null) {
5424119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka            mAppWidgetAdapter.cancelAllWidgetPreviewLoaders();
5434119788b1be5d9b51e3c5cfe4e32f2aacc5a2f8fMichael Jurka        }
5440b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        super.onDestroy();
5450b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
5460b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5470b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    @Override
5480b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5490b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        super.onActivityResult(requestCode, resultCode, data);
5500b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) {
551f5336fd114e557fce06197041aab70217308fe90Michael Jurka            int appWidgetId;
552f5336fd114e557fce06197041aab70217308fe90Michael Jurka            if  (data == null) {
553f5336fd114e557fce06197041aab70217308fe90Michael Jurka                appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID ;
554f5336fd114e557fce06197041aab70217308fe90Michael Jurka            } else {
555f5336fd114e557fce06197041aab70217308fe90Michael Jurka                appWidgetId = data.getIntExtra(
556f5336fd114e557fce06197041aab70217308fe90Michael Jurka                        AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
557f5336fd114e557fce06197041aab70217308fe90Michael Jurka            }
558f5336fd114e557fce06197041aab70217308fe90Michael Jurka            if (requestCode == REQUEST_PICK_APPWIDGET && resultCode == Activity.RESULT_OK) {
5590b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
5600b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5610b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                AppWidgetProviderInfo appWidget = null;
562f5336fd114e557fce06197041aab70217308fe90Michael Jurka                appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
5630b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
564f5336fd114e557fce06197041aab70217308fe90Michael Jurka                if (appWidget.configure != null) {
5650b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    // Launch over to configure widget, if needed
5660b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
5670b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    intent.setComponent(appWidget.configure);
5680b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
5690b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
5700b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5710b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
5720b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                } else {
5730b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    // Otherwise just add it
5740b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                    onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);
5750b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                }
5760b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            } else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) {
5770b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                mLockPatternUtils.addAppWidget(appWidgetId, 0);
5785c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka                finishDelayedAndShowLockScreen(appWidgetId);
5790b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            } else {
580f5336fd114e557fce06197041aab70217308fe90Michael Jurka                if (mAddingToKeyguard &&
581f5336fd114e557fce06197041aab70217308fe90Michael Jurka                        mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
582f5336fd114e557fce06197041aab70217308fe90Michael Jurka                    AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId);
583f5336fd114e557fce06197041aab70217308fe90Michael Jurka                }
5845c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka                finishDelayedAndShowLockScreen(AppWidgetManager.INVALID_APPWIDGET_ID);
5850b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
5860b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
5870b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
5880b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
5895c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka    private void finishDelayedAndShowLockScreen(int appWidgetId) {
5900b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
5910b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        IWindowManager iWm = IWindowManager.Stub.asInterface(b);
5925c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka        Bundle opts = null;
5935c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka        if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
5945c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka            opts = new Bundle();
5955c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka            opts.putInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET, appWidgetId);
5965c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka        }
5970b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        try {
5985c5eff45e97a2bb1b55befb87eb535a438a7bbf8Michael Jurka            iWm.lockNow(opts);
5990b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } catch (RemoteException e) {
6000b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
6010b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
6020b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        // Change background to all black
6030b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        ViewGroup root = (ViewGroup) findViewById(R.id.layout_root);
6040b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        root.setBackgroundColor(0xFF000000);
6050b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        // Hide all children
6060b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        final int childCount = root.getChildCount();
6070b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        for (int i = 0; i < childCount; i++) {
6080b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            root.getChildAt(i).setVisibility(View.INVISIBLE);
6090b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
6100b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        mGridView.postDelayed(new Runnable() {
6110b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            public void run() {
6120b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka                finish();
6130b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            }
6140b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }, 500);
6150b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
6160b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka
6170b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    void startActivityForResultSafely(Intent intent, int requestCode) {
6180b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        try {
6190b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            startActivityForResult(intent, requestCode);
6200b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } catch (ActivityNotFoundException e) {
6210b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
6220b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        } catch (SecurityException e) {
6230b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
6240b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka            Log.e(TAG, "Settings does not have the permission to launch " + intent, e);
6250b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka        }
6260b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka    }
6270b2bd8d11d6947a6ce71db0691ba341aec7a2964Michael Jurka}
628