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