Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings;
     18 
     19 import android.app.Activity;
     20 import android.app.ActivityManager;
     21 import android.app.LauncherActivity.IconResizer;
     22 import android.appwidget.AppWidgetHost;
     23 import android.appwidget.AppWidgetManager;
     24 import android.appwidget.AppWidgetProviderInfo;
     25 import android.content.ActivityNotFoundException;
     26 import android.content.ComponentName;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.pm.PackageManager;
     30 import android.content.res.Resources;
     31 import android.graphics.Bitmap;
     32 import android.graphics.Bitmap.Config;
     33 import android.graphics.Canvas;
     34 import android.graphics.Paint;
     35 import android.graphics.Rect;
     36 import android.graphics.drawable.Drawable;
     37 import android.os.AsyncTask;
     38 import android.os.Bundle;
     39 import android.os.IBinder;
     40 import android.os.RemoteException;
     41 import android.os.ServiceManager;
     42 import android.os.UserHandle;
     43 import android.util.DisplayMetrics;
     44 import android.util.Log;
     45 import android.view.IWindowManager;
     46 import android.view.LayoutInflater;
     47 import android.view.View;
     48 import android.view.ViewGroup;
     49 import android.view.WindowManager;
     50 import android.widget.AdapterView;
     51 import android.widget.BaseAdapter;
     52 import android.widget.GridView;
     53 import android.widget.ImageView;
     54 import android.widget.TextView;
     55 import android.widget.Toast;
     56 
     57 import com.android.internal.widget.LockPatternUtils;
     58 
     59 import java.lang.ref.WeakReference;
     60 import java.util.List;
     61 
     62 /**
     63  * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any
     64  * injected special widgets specified through
     65  * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and
     66  * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}.
     67  * <p>
     68  * When an installed {@link AppWidgetProviderInfo} is selected, this activity
     69  * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID},
     70  * otherwise it will return the requested extras.
     71  */
     72 public class KeyguardAppWidgetPickActivity extends Activity
     73     implements GridView.OnItemClickListener,
     74         AppWidgetLoader.ItemConstructor<KeyguardAppWidgetPickActivity.Item> {
     75     private static final String TAG = "KeyguardAppWidgetPickActivity";
     76     private static final int REQUEST_PICK_APPWIDGET = 126;
     77     private static final int REQUEST_CREATE_APPWIDGET = 127;
     78 
     79     private AppWidgetLoader<Item> mAppWidgetLoader;
     80     private List<Item> mItems;
     81     private GridView mGridView;
     82     private AppWidgetAdapter mAppWidgetAdapter;
     83     private AppWidgetManager mAppWidgetManager;
     84     private int mAppWidgetId;
     85     // Might make it possible to make this be false in future
     86     private boolean mAddingToKeyguard = true;
     87     private Intent mResultData;
     88     private LockPatternUtils mLockPatternUtils;
     89     private Bundle mExtraConfigureOptions;
     90 
     91     @Override
     92     protected void onCreate(Bundle savedInstanceState) {
     93         getWindow().addPrivateFlags(
     94                 WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR);
     95         setContentView(R.layout.keyguard_appwidget_picker_layout);
     96         super.onCreate(savedInstanceState);
     97 
     98         // Set default return data
     99         setResultData(RESULT_CANCELED, null);
    100 
    101         // Read the appWidgetId passed our direction, otherwise bail if not found
    102         final Intent intent = getIntent();
    103         if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
    104             mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
    105                     AppWidgetManager.INVALID_APPWIDGET_ID);
    106         } else {
    107             finish();
    108         }
    109         mExtraConfigureOptions = intent.getBundleExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
    110 
    111         mGridView = (GridView) findViewById(R.id.widget_list);
    112         DisplayMetrics dm = new DisplayMetrics();
    113         getWindowManager().getDefaultDisplay().getMetrics(dm);
    114         int maxGridWidth = getResources().getDimensionPixelSize(
    115                 R.dimen.keyguard_appwidget_picker_max_width);
    116 
    117         if (maxGridWidth < dm.widthPixels) {
    118             mGridView.getLayoutParams().width = maxGridWidth;
    119         }
    120         mAppWidgetManager = AppWidgetManager.getInstance(this);
    121         mAppWidgetLoader = new AppWidgetLoader<Item>(this, mAppWidgetManager, this);
    122         mItems = mAppWidgetLoader.getItems(getIntent());
    123         mAppWidgetAdapter = new AppWidgetAdapter(this, mItems);
    124         mGridView.setAdapter(mAppWidgetAdapter);
    125         mGridView.setOnItemClickListener(this);
    126 
    127         mLockPatternUtils = new LockPatternUtils(this); // TEMP-- we want to delete this
    128     }
    129 
    130     /**
    131      * Convenience method for setting the result code and intent. This method
    132      * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that
    133      * most hosts expect returned.
    134      */
    135     void setResultData(int code, Intent intent) {
    136         Intent result = intent != null ? intent : new Intent();
    137         result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
    138         mResultData = result;
    139         setResult(code, result);
    140     }
    141 
    142     /**
    143      * Item that appears in the AppWidget picker grid.
    144      */
    145     public static class Item implements AppWidgetLoader.LabelledItem {
    146         protected static IconResizer sResizer;
    147 
    148 
    149         CharSequence label;
    150         int appWidgetPreviewId;
    151         int iconId;
    152         String packageName;
    153         String className;
    154         Bundle extras;
    155         private WidgetPreviewLoader mWidgetPreviewLoader;
    156         private Context mContext;
    157 
    158         /**
    159          * Create a list item from given label and icon.
    160          */
    161         Item(Context context, CharSequence label) {
    162             this.label = label;
    163             mContext = context;
    164         }
    165 
    166         void loadWidgetPreview(ImageView v) {
    167             mWidgetPreviewLoader = new WidgetPreviewLoader(mContext, v);
    168             mWidgetPreviewLoader.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
    169         }
    170 
    171         void cancelLoadingWidgetPreview() {
    172             if (mWidgetPreviewLoader != null) {
    173                 mWidgetPreviewLoader.cancel(false);
    174                 mWidgetPreviewLoader = null;
    175             }
    176         }
    177 
    178         /**
    179          * Build the {@link Intent} described by this item. If this item
    180          * can't create a valid {@link android.content.ComponentName}, it will return
    181          * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
    182          */
    183         Intent getIntent() {
    184             Intent intent = new Intent();
    185             if (packageName != null && className != null) {
    186                 // Valid package and class, so fill details as normal intent
    187                 intent.setClassName(packageName, className);
    188                 if (extras != null) {
    189                     intent.putExtras(extras);
    190                 }
    191             } else {
    192                 // No valid package or class, so treat as shortcut with label
    193                 intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
    194                 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
    195             }
    196             return intent;
    197         }
    198 
    199         public CharSequence getLabel() {
    200             return label;
    201         }
    202 
    203         class WidgetPreviewLoader extends AsyncTask<Void, Bitmap, Void> {
    204             private Resources mResources;
    205             private PackageManager mPackageManager;
    206             private int mIconDpi;
    207             private ImageView mView;
    208             public WidgetPreviewLoader(Context context, ImageView v) {
    209                 super();
    210                 mResources = context.getResources();
    211                 mPackageManager = context.getPackageManager();
    212                 ActivityManager activityManager =
    213                         (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    214                 mIconDpi = activityManager.getLauncherLargeIconDensity();
    215                 mView = v;
    216             }
    217             public Void doInBackground(Void... params) {
    218                 if (!isCancelled()) {
    219                     int appWidgetPreviewWidth =
    220                             mResources.getDimensionPixelSize(R.dimen.appwidget_preview_width);
    221                     int appWidgetPreviewHeight =
    222                             mResources.getDimensionPixelSize(R.dimen.appwidget_preview_height);
    223                     Bitmap b = getWidgetPreview(new ComponentName(packageName, className),
    224                             appWidgetPreviewId, iconId,
    225                             appWidgetPreviewWidth, appWidgetPreviewHeight);
    226                     publishProgress(b);
    227                 }
    228                 return null;
    229             }
    230             public void onProgressUpdate(Bitmap... values) {
    231                 if (!isCancelled()) {
    232                     Bitmap b = values[0];
    233                     mView.setImageBitmap(b);
    234                 }
    235             }
    236             abstract class WeakReferenceThreadLocal<T> {
    237                 private ThreadLocal<WeakReference<T>> mThreadLocal;
    238                 public WeakReferenceThreadLocal() {
    239                     mThreadLocal = new ThreadLocal<WeakReference<T>>();
    240                 }
    241 
    242                 abstract T initialValue();
    243 
    244                 public void set(T t) {
    245                     mThreadLocal.set(new WeakReference<T>(t));
    246                 }
    247 
    248                 public T get() {
    249                     WeakReference<T> reference = mThreadLocal.get();
    250                     T obj;
    251                     if (reference == null) {
    252                         obj = initialValue();
    253                         mThreadLocal.set(new WeakReference<T>(obj));
    254                         return obj;
    255                     } else {
    256                         obj = reference.get();
    257                         if (obj == null) {
    258                             obj = initialValue();
    259                             mThreadLocal.set(new WeakReference<T>(obj));
    260                         }
    261                         return obj;
    262                     }
    263                 }
    264             }
    265 
    266             class CanvasCache extends WeakReferenceThreadLocal<Canvas> {
    267                 @Override
    268                 protected Canvas initialValue() {
    269                     return new Canvas();
    270                 }
    271             }
    272 
    273             class PaintCache extends WeakReferenceThreadLocal<Paint> {
    274                 @Override
    275                 protected Paint initialValue() {
    276                     return null;
    277                 }
    278             }
    279 
    280             class BitmapCache extends WeakReferenceThreadLocal<Bitmap> {
    281                 @Override
    282                 protected Bitmap initialValue() {
    283                     return null;
    284                 }
    285             }
    286 
    287             class RectCache extends WeakReferenceThreadLocal<Rect> {
    288                 @Override
    289                 protected Rect initialValue() {
    290                     return new Rect();
    291                 }
    292             }
    293 
    294             // Used for drawing widget previews
    295             CanvasCache sCachedAppWidgetPreviewCanvas = new CanvasCache();
    296             RectCache sCachedAppWidgetPreviewSrcRect = new RectCache();
    297             RectCache sCachedAppWidgetPreviewDestRect = new RectCache();
    298             PaintCache sCachedAppWidgetPreviewPaint = new PaintCache();
    299 
    300             private Bitmap getWidgetPreview(ComponentName provider, int previewImage,
    301                     int iconId, int maxWidth, int maxHeight) {
    302                 // Load the preview image if possible
    303                 String packageName = provider.getPackageName();
    304                 if (maxWidth < 0) maxWidth = Integer.MAX_VALUE;
    305                 if (maxHeight < 0) maxHeight = Integer.MAX_VALUE;
    306 
    307 
    308                 int appIconSize = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
    309 
    310                 Drawable drawable = null;
    311                 if (previewImage != 0) {
    312                     drawable = mPackageManager.getDrawable(packageName, previewImage, null);
    313                     if (drawable == null) {
    314                         Log.w(TAG, "Can't load widget preview drawable 0x" +
    315                                 Integer.toHexString(previewImage) + " for provider: " + provider);
    316                     }
    317                 }
    318 
    319                 int bitmapWidth;
    320                 int bitmapHeight;
    321                 Bitmap defaultPreview = null;
    322                 boolean widgetPreviewExists = (drawable != null);
    323                 if (widgetPreviewExists) {
    324                     bitmapWidth = drawable.getIntrinsicWidth();
    325                     bitmapHeight = drawable.getIntrinsicHeight();
    326                 } else {
    327                     // Generate a preview image if we couldn't load one
    328                     bitmapWidth = appIconSize;
    329                     bitmapHeight = appIconSize;
    330                     defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
    331                             Config.ARGB_8888);
    332 
    333                     try {
    334                         Drawable icon = null;
    335                         if (iconId > 0)
    336                             icon = getFullResIcon(packageName, iconId);
    337                         if (icon != null) {
    338                             renderDrawableToBitmap(icon, defaultPreview, 0,
    339                                     0, appIconSize, appIconSize);
    340                         }
    341                     } catch (Resources.NotFoundException e) {
    342                     }
    343                 }
    344 
    345                 // Scale to fit width only - let the widget preview be clipped in the
    346                 // vertical dimension
    347                 float scale = 1f;
    348                 if (bitmapWidth > maxWidth) {
    349                     scale = maxWidth / (float) bitmapWidth;
    350                 }
    351                 int finalPreviewWidth = (int) (scale * bitmapWidth);
    352                 int finalPreviewHeight = (int) (scale * bitmapHeight);
    353 
    354                 bitmapWidth = finalPreviewWidth;
    355                 bitmapHeight = Math.min(finalPreviewHeight, maxHeight);
    356 
    357                 Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
    358                         Config.ARGB_8888);
    359 
    360                 // Draw the scaled preview into the final bitmap
    361                 if (widgetPreviewExists) {
    362                     renderDrawableToBitmap(drawable, preview, 0, 0, finalPreviewWidth,
    363                             finalPreviewHeight);
    364                 } else {
    365                     final Canvas c = sCachedAppWidgetPreviewCanvas.get();
    366                     final Rect src = sCachedAppWidgetPreviewSrcRect.get();
    367                     final Rect dest = sCachedAppWidgetPreviewDestRect.get();
    368                     c.setBitmap(preview);
    369                     src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight());
    370                     dest.set(0, 0, finalPreviewWidth, finalPreviewHeight);
    371 
    372                     Paint p = sCachedAppWidgetPreviewPaint.get();
    373                     if (p == null) {
    374                         p = new Paint();
    375                         p.setFilterBitmap(true);
    376                         sCachedAppWidgetPreviewPaint.set(p);
    377                     }
    378                     c.drawBitmap(defaultPreview, src, dest, p);
    379                     c.setBitmap(null);
    380                 }
    381                 return preview;
    382             }
    383             public Drawable getFullResDefaultActivityIcon() {
    384                 return getFullResIcon(Resources.getSystem(),
    385                         android.R.mipmap.sym_def_app_icon);
    386             }
    387 
    388             public Drawable getFullResIcon(Resources resources, int iconId) {
    389                 Drawable d;
    390                 try {
    391                     d = resources.getDrawableForDensity(iconId, mIconDpi);
    392                 } catch (Resources.NotFoundException e) {
    393                     d = null;
    394                 }
    395 
    396                 return (d != null) ? d : getFullResDefaultActivityIcon();
    397             }
    398 
    399             public Drawable getFullResIcon(String packageName, int iconId) {
    400                 Resources resources;
    401                 try {
    402                     resources = mPackageManager.getResourcesForApplication(packageName);
    403                 } catch (PackageManager.NameNotFoundException e) {
    404                     resources = null;
    405                 }
    406                 if (resources != null) {
    407                     if (iconId != 0) {
    408                         return getFullResIcon(resources, iconId);
    409                     }
    410                 }
    411                 return getFullResDefaultActivityIcon();
    412             }
    413 
    414             private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
    415                 renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
    416             }
    417 
    418             private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
    419                     float scale) {
    420                 if (bitmap != null) {
    421                     Canvas c = new Canvas(bitmap);
    422                     c.scale(scale, scale);
    423                     Rect oldBounds = d.copyBounds();
    424                     d.setBounds(x, y, x + w, y + h);
    425                     d.draw(c);
    426                     d.setBounds(oldBounds); // Restore the bounds
    427                     c.setBitmap(null);
    428                 }
    429             }
    430         }
    431     }
    432 
    433     @Override
    434     public Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) {
    435         CharSequence label = info.label;
    436 
    437         Item item = new Item(context, label);
    438         item.appWidgetPreviewId = info.previewImage;
    439         item.iconId = info.icon;
    440         item.packageName = info.provider.getPackageName();
    441         item.className = info.provider.getClassName();
    442         item.extras = extras;
    443         return item;
    444     }
    445 
    446     protected static class AppWidgetAdapter extends BaseAdapter {
    447         private final LayoutInflater mInflater;
    448         private final List<Item> mItems;
    449 
    450         /**
    451          * Create an adapter for the given items.
    452          */
    453         public AppWidgetAdapter(Context context, List<Item> items) {
    454             mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    455             mItems = items;
    456         }
    457 
    458         /**
    459          * {@inheritDoc}
    460          */
    461         public int getCount() {
    462             return mItems.size();
    463         }
    464 
    465         /**
    466          * {@inheritDoc}
    467          */
    468         public Object getItem(int position) {
    469             return mItems.get(position);
    470         }
    471 
    472         /**
    473          * {@inheritDoc}
    474          */
    475         public long getItemId(int position) {
    476             return position;
    477         }
    478 
    479         /**
    480          * {@inheritDoc}
    481          */
    482         public View getView(int position, View convertView, ViewGroup parent) {
    483             if (convertView == null) {
    484                 convertView = mInflater.inflate(R.layout.keyguard_appwidget_item, parent, false);
    485             }
    486 
    487             Item item = (Item) getItem(position);
    488             TextView textView = (TextView) convertView.findViewById(R.id.label);
    489             textView.setText(item.label);
    490             ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
    491             iconView.setImageDrawable(null);
    492             item.loadWidgetPreview(iconView);
    493             return convertView;
    494         }
    495 
    496         public void cancelAllWidgetPreviewLoaders() {
    497             for (int i = 0; i < mItems.size(); i++) {
    498                 mItems.get(i).cancelLoadingWidgetPreview();
    499             }
    500         }
    501     }
    502 
    503     /**
    504      * {@inheritDoc}
    505      */
    506     @Override
    507     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    508         Item item = mItems.get(position);
    509         Intent intent = item.getIntent();
    510 
    511         int result;
    512         if (item.extras != null) {
    513             // If these extras are present it's because this entry is custom.
    514             // Don't try to bind it, just pass it back to the app.
    515             result = RESULT_OK;
    516             setResultData(result, intent);
    517         } else {
    518             try {
    519                 if (mAddingToKeyguard && mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
    520                     // Found in KeyguardHostView.java
    521                     final int KEYGUARD_HOST_ID = 0x4B455947;
    522                     int userId = ActivityManager.getCurrentUser();
    523                     mAppWidgetId = AppWidgetHost.allocateAppWidgetIdForPackage(KEYGUARD_HOST_ID,
    524                             userId, "com.android.keyguard");
    525                 }
    526                 mAppWidgetManager.bindAppWidgetId(
    527                         mAppWidgetId, intent.getComponent(), mExtraConfigureOptions);
    528                 result = RESULT_OK;
    529             } catch (IllegalArgumentException e) {
    530                 // This is thrown if they're already bound, or otherwise somehow
    531                 // bogus.  Set the result to canceled, and exit.  The app *should*
    532                 // clean up at this point.  We could pass the error along, but
    533                 // it's not clear that that's useful -- the widget will simply not
    534                 // appear.
    535                 result = RESULT_CANCELED;
    536             }
    537             setResultData(result, null);
    538         }
    539         if (mAddingToKeyguard) {
    540             onActivityResult(REQUEST_PICK_APPWIDGET, result, mResultData);
    541         } else {
    542             finish();
    543         }
    544     }
    545 
    546     protected void onDestroy() {
    547         if (mAppWidgetAdapter != null) {
    548             mAppWidgetAdapter.cancelAllWidgetPreviewLoaders();
    549         }
    550         super.onDestroy();
    551     }
    552 
    553     @Override
    554     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    555         super.onActivityResult(requestCode, resultCode, data);
    556         if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) {
    557             int appWidgetId;
    558             if  (data == null) {
    559                 appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID ;
    560             } else {
    561                 appWidgetId = data.getIntExtra(
    562                         AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    563             }
    564             if (requestCode == REQUEST_PICK_APPWIDGET && resultCode == Activity.RESULT_OK) {
    565                 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
    566 
    567                 AppWidgetProviderInfo appWidget = null;
    568                 appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
    569 
    570                 if (appWidget.configure != null) {
    571                     // Launch over to configure widget, if needed
    572                     Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
    573                     intent.setComponent(appWidget.configure);
    574                     intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    575                     intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    576 
    577                     startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
    578                 } else {
    579                     // Otherwise just add it
    580                     onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);
    581                 }
    582             } else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) {
    583                 mLockPatternUtils.addAppWidget(appWidgetId, 0);
    584                 finishDelayedAndShowLockScreen(appWidgetId);
    585             } else {
    586                 if (mAddingToKeyguard &&
    587                         mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
    588                     int userId = ActivityManager.getCurrentUser();
    589                     AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId, userId);
    590                 }
    591                 finishDelayedAndShowLockScreen(AppWidgetManager.INVALID_APPWIDGET_ID);
    592             }
    593         }
    594     }
    595 
    596     private void finishDelayedAndShowLockScreen(int appWidgetId) {
    597         IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
    598         IWindowManager iWm = IWindowManager.Stub.asInterface(b);
    599         Bundle opts = null;
    600         if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
    601             opts = new Bundle();
    602             opts.putInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET, appWidgetId);
    603         }
    604         try {
    605             iWm.lockNow(opts);
    606         } catch (RemoteException e) {
    607         }
    608 
    609         // Change background to all black
    610         ViewGroup root = (ViewGroup) findViewById(R.id.layout_root);
    611         root.setBackgroundColor(0xFF000000);
    612         // Hide all children
    613         final int childCount = root.getChildCount();
    614         for (int i = 0; i < childCount; i++) {
    615             root.getChildAt(i).setVisibility(View.INVISIBLE);
    616         }
    617         mGridView.postDelayed(new Runnable() {
    618             public void run() {
    619                 finish();
    620             }
    621         }, 500);
    622     }
    623 
    624     void startActivityForResultSafely(Intent intent, int requestCode) {
    625         try {
    626             startActivityForResult(intent, requestCode);
    627         } catch (ActivityNotFoundException e) {
    628             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
    629         } catch (SecurityException e) {
    630             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
    631             Log.e(TAG, "Settings does not have the permission to launch " + intent, e);
    632         }
    633     }
    634 }
    635