1 package com.android.launcher3;
2 
3 import android.appwidget.AppWidgetHost;
4 import android.appwidget.AppWidgetManager;
5 import android.appwidget.AppWidgetProviderInfo;
6 import android.content.BroadcastReceiver;
7 import android.content.ContentResolver;
8 import android.content.ContentValues;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.database.Cursor;
12 import android.os.AsyncTask;
13 import android.util.Log;
14 
15 import com.android.launcher3.LauncherSettings.Favorites;
16 
17 import java.util.ArrayList;
18 import java.util.List;
19 
20 public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
21 
22     private static final String TAG = "AppWidgetsRestoredReceiver";
23 
24     @Override
onReceive(Context context, Intent intent)25     public void onReceive(Context context, Intent intent) {
26         if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) {
27             int[] oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS);
28             int[] newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
29             if (oldIds.length == newIds.length) {
30                 restoreAppWidgetIds(context, oldIds, newIds);
31             } else {
32                 Log.e(TAG, "Invalid host restored received");
33             }
34         }
35     }
36 
37     /**
38      * Updates the app widgets whose id has changed during the restore process.
39      */
restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds)40     static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
41         final ContentResolver cr = context.getContentResolver();
42         final List<Integer> idsToRemove = new ArrayList<Integer>();
43         final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
44 
45         for (int i = 0; i < oldWidgetIds.length; i++) {
46             Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
47 
48             final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
49             final int state;
50             if (LauncherModel.isValidProvider(provider)) {
51                 // This will ensure that we show 'Click to setup' UI if required.
52                 state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
53             } else {
54                 state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
55             }
56 
57             ContentValues values = new ContentValues();
58             values.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]);
59             values.put(LauncherSettings.Favorites.RESTORED, state);
60 
61             String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) };
62 
63             int result = cr.update(Favorites.CONTENT_URI, values,
64                     "appWidgetId=? and (restored & 1) = 1", widgetIdParams);
65             if (result == 0) {
66                 Cursor cursor = cr.query(Favorites.CONTENT_URI,
67                         new String[] {Favorites.APPWIDGET_ID},
68                         "appWidgetId=?", widgetIdParams, null);
69                 try {
70                     if (!cursor.moveToFirst()) {
71                         // The widget no long exists.
72                         idsToRemove.add(newWidgetIds[i]);
73                     }
74                 } finally {
75                     cursor.close();
76                 }
77             }
78         }
79         // Unregister the widget IDs which are not present on the workspace. This could happen
80         // when a widget place holder is removed from workspace, before this method is called.
81         if (!idsToRemove.isEmpty()) {
82             final AppWidgetHost appWidgetHost =
83                     new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
84             new AsyncTask<Void, Void, Void>() {
85                 public Void doInBackground(Void ... args) {
86                     for (Integer id : idsToRemove) {
87                         appWidgetHost.deleteAppWidgetId(id);
88                         Log.e(TAG, "Widget no longer present, appWidgetId=" + id);
89                     }
90                     return null;
91                 }
92             }.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
93         }
94 
95         LauncherAppState app = LauncherAppState.getInstanceNoCreate();
96         if (app != null) {
97             app.reloadWorkspace();
98         }
99     }
100 }
101