Allow Launcher to automatically restore widgets

This replaces PendingAppWidgetHostView with configured widget view when
OPTION_APPWIDGET_RESTORE_COMPLETED is set to True by a widget provider.

Bug: 63667276
Test: Manual
Change-Id: Ide21f5e9a7dac7e3d6a745660a38ad0b951b47d3
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 33f5a95..d6e8710 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2305,6 +2305,13 @@
                     item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                     getModelWriter().updateItemInDatabase(item);
                 }
+                else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
+                        && appWidgetInfo.configure != null) {
+                    if (mAppWidgetManager.isAppWidgetRestored(item.appWidgetId)) {
+                        item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
+                        getModelWriter().updateItemInDatabase(item);
+                    }
+                }
             }
 
             if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
@@ -2318,6 +2325,11 @@
                 item.minSpanX = appWidgetInfo.minSpanX;
                 item.minSpanY = appWidgetInfo.minSpanY;
                 view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
+            } else if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)
+                    && appWidgetInfo != null) {
+                mAppWidgetHost.addPendingView(item.appWidgetId,
+                        new PendingAppWidgetHostView(this, item, mIconCache, false));
+                view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
             } else {
                 view = new PendingAppWidgetHostView(this, item, mIconCache, false);
             }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 4e29a95..9921f76 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -32,6 +32,7 @@
 import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.widget.DeferredAppWidgetHostView;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.PendingAppWidgetHostView;
 import com.android.launcher3.widget.custom.CustomWidgetManager;
 
 import java.util.ArrayList;
@@ -53,12 +54,14 @@
 
     private final ArrayList<ProviderChangedListener> mProviderChangeListeners = new ArrayList<>();
     private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
+    private final SparseArray<PendingAppWidgetHostView> mPendingViews = new SparseArray<>();
 
     private final Context mContext;
     private int mFlags = FLAG_RESUMED;
 
     private IntConsumer mAppWidgetRemovedCallback = null;
 
+
     public LauncherAppWidgetHost(Context context) {
         this(context, null);
     }
@@ -73,7 +76,13 @@
     @Override
     protected LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
-        LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
+        final LauncherAppWidgetHostView view;
+        if (mPendingViews.get(appWidgetId) != null) {
+            view = mPendingViews.get(appWidgetId);
+            mPendingViews.remove(appWidgetId);
+        } else {
+            view = new LauncherAppWidgetHostView(context);
+        }
         mViews.put(appWidgetId, view);
         return view;
     }
@@ -189,6 +198,10 @@
         }
     }
 
+    void addPendingView(int appWidgetId, PendingAppWidgetHostView view) {
+        mPendingViews.put(appWidgetId, view);
+    }
+
     public AppWidgetHostView createView(Context context, int appWidgetId,
             LauncherAppWidgetProviderInfo appWidget) {
         if (appWidget.isCustomWidget()) {
@@ -238,8 +251,8 @@
 
     /**
      * Called on an appWidget is removed for a widgetId
-     * @param appWidgetId
-     * TODO: make this override when SDK is updated
+     *
+     * @param appWidgetId TODO: make this override when SDK is updated
      */
     public void onAppWidgetRemoved(int appWidgetId) {
         if (mAppWidgetRemovedCallback == null) {
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 6038873..895f8de 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -33,6 +33,7 @@
 import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.widget.RemoteViews;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.FastBitmapDrawable;
@@ -94,6 +95,15 @@
     }
 
     @Override
+    public void updateAppWidget(RemoteViews remoteViews) {
+        super.updateAppWidget(remoteViews);
+        WidgetManagerHelper widgetManagerHelper = new WidgetManagerHelper(getContext());
+        if (widgetManagerHelper.isAppWidgetRestored(mInfo.appWidgetId)) {
+            reInflate();
+        }
+    }
+
+    @Override
     public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
             int maxHeight) {
         // No-op
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index 8b08d77..f3c7822 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -49,6 +49,9 @@
  */
 public class WidgetManagerHelper {
 
+    //TODO: replace this with OPTION_APPWIDGET_RESTORE_COMPLETED b/63667276
+    public static final String WIDGET_OPTION_RESTORE_COMPLETED = "appWidgetRestoreCompleted";
+
     final AppWidgetManager mAppWidgetManager;
     final Context mContext;
 
@@ -127,6 +130,14 @@
         return null;
     }
 
+    /**
+     * Returns if a AppWidgetProvider has marked a widget restored
+     */
+    public boolean isAppWidgetRestored(int appWidgetId) {
+        return !WidgetsModel.GO_DISABLE_WIDGETS && mAppWidgetManager.getAppWidgetOptions(
+                appWidgetId).getBoolean(WIDGET_OPTION_RESTORE_COMPLETED);
+    }
+
     public static Map<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap(Context context) {
         if (WidgetsModel.GO_DISABLE_WIDGETS) {
             return Collections.emptyMap();