Improve handling of external deletion in LauncherProvider.delete

When deleting a widget, ensure that we also delete the corresponding
widget from the system server

Bug 30835877

Change-Id: I7d539c2d37ef53086d09ae128f7278941f804aeb
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index eee5627..f3d9493 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -67,6 +67,7 @@
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Locale;
 
 public class LauncherProvider extends ContentProvider {
     private static final String TAG = "LauncherProvider";
@@ -313,10 +314,32 @@
         SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
 
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        int count = db.delete(args.table, args.where, args.args);
-        if (count > 0) notifyListeners();
 
-        reloadLauncherIfExternal();
+        if (Binder.getCallingPid() != Process.myPid()
+                && Favorites.TABLE_NAME.equalsIgnoreCase(args.table)) {
+            String widgetSelection = TextUtils.isEmpty(args.where) ? "1=1" : args.where;
+            widgetSelection = String.format(Locale.ENGLISH, "%1$s = %2$d AND ( %3$s )",
+                    Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET, widgetSelection);
+            try (Cursor c = db.query(Favorites.TABLE_NAME, new String[] { Favorites.APPWIDGET_ID },
+                    widgetSelection, args.args, null, null, null)) {
+                AppWidgetHost host = new AppWidgetHost(getContext(), Launcher.APPWIDGET_HOST_ID);
+                while (c.moveToNext()) {
+                    int widgetId = c.getInt(0);
+                    if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
+                        try {
+                            host.deleteAppWidgetId(widgetId);
+                        } catch (RuntimeException e) {
+                            Log.e(TAG, "Error deleting widget id " + widgetId, e);
+                        }
+                    }
+                }
+            }
+        }
+        int count = db.delete(args.table, args.where, args.args);
+        if (count > 0) {
+            notifyListeners();
+            reloadLauncherIfExternal();
+        }
         return count;
     }