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