Merge "Render RemoteViews in LauncherAppWidgetHostView" into sc-dev
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index fc635a9..d5a04a6 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -59,6 +59,7 @@
 import com.android.launcher3.views.BaseDragLayer;
 import com.android.launcher3.widget.LauncherAppWidgetHost;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.NavigableAppWidgetHostView;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.WidgetCell;
@@ -147,20 +148,31 @@
     public boolean onLongClick(View view) {
         // Find the position of the preview relative to the touch location.
         WidgetImageView img = mWidgetCell.getWidgetView();
+        NavigableAppWidgetHostView appWidgetHostView = mWidgetCell.getAppWidgetHostViewPreview();
 
         // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
         // we abort the drag.
-        if (img.getDrawable() == null) {
+        if (img.getDrawable() == null && appWidgetHostView == null) {
             return false;
         }
 
-        Rect bounds = img.getBitmapBounds();
-        bounds.offset(img.getLeft() - (int) mLastTouchPos.x, img.getTop() - (int) mLastTouchPos.y);
-
+        final Rect bounds;
         // Start home and pass the draw request params
-        PinItemDragListener listener = new PinItemDragListener(mRequest, bounds,
-                img.getDrawable().getIntrinsicWidth(), img.getWidth());
-
+        final PinItemDragListener listener;
+        if (appWidgetHostView != null) {
+            bounds = new Rect();
+            appWidgetHostView.getSourceVisualDragBounds(bounds);
+            bounds.offset(appWidgetHostView.getLeft() - (int) mLastTouchPos.x,
+                    appWidgetHostView.getTop() - (int) mLastTouchPos.y);
+            listener = new PinItemDragListener(mRequest, bounds,
+                    appWidgetHostView.getMeasuredWidth(), appWidgetHostView.getMeasuredWidth());
+        } else {
+            bounds = img.getBitmapBounds();
+            bounds.offset(img.getLeft() - (int) mLastTouchPos.x,
+                    img.getTop() - (int) mLastTouchPos.y);
+            listener = new PinItemDragListener(mRequest, bounds,
+                    img.getDrawable().getIntrinsicWidth(), img.getWidth());
+        }
 
         // Start a system drag and drop. We use a transparent bitmap as preview for system drag
         // as the preview is handled internally by launcher.
@@ -214,7 +226,7 @@
             // Cannot add widget
             return false;
         }
-        mWidgetCell.setPreview(PinItemDragListener.getPreview(mRequest));
+        mWidgetCell.setRemoteViewsPreview(PinItemDragListener.getPreview(mRequest));
 
         mAppWidgetManager = new WidgetManagerHelper(this);
         mAppWidgetHost = new LauncherAppWidgetHost(this);
@@ -238,6 +250,7 @@
 
             @Override
             protected void onPostExecute(WidgetItem item) {
+                mWidgetCell.setPreviewSize(item.spanX, item.spanY);
                 mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
                 mWidgetCell.ensurePreview();
             }
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 95b887c..415f48d 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -114,7 +114,7 @@
         }
 
         PendingItemDragHelper dragHelper = new PendingItemDragHelper(v);
-        dragHelper.setRemoteViewsPreview(v.getPreview());
+        dragHelper.setRemoteViewsPreview(v.getRemoteViewsPreview());
         dragHelper.setAppWidgetHostViewPreview(v.getAppWidgetHostViewPreview());
 
         if (image.getDrawable() != null) {
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index df368cd..cea4de7 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -23,6 +23,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.widget.RemoteViews;
 
 import androidx.annotation.Nullable;
@@ -53,7 +54,7 @@
     private int[] mEstimatedCellSize;
 
     @Nullable private RemoteViews mRemoteViewsPreview;
-    @Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
+    @Nullable private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
     private final float mEnforcedRoundedCornersForWidget;
 
     public PendingItemDragHelper(View view) {
@@ -71,9 +72,9 @@
         mRemoteViewsPreview = remoteViewsPreview;
     }
 
-    /** Sets a {@link LauncherAppWidgetHostView} which shows a preview layout of an app widget. */
+    /** Sets a {@link NavigableAppWidgetHostView} which shows a preview layout of an app widget. */
     public void setAppWidgetHostViewPreview(
-            @Nullable LauncherAppWidgetHostView appWidgetHostViewPreview) {
+            @Nullable NavigableAppWidgetHostView appWidgetHostViewPreview) {
         mAppWidgetHostViewPreview = appWidgetHostViewPreview;
     }
 
@@ -110,9 +111,22 @@
             int[] previewSizeBeforeScale = new int[1];
 
             if (mRemoteViewsPreview != null) {
-                preview = new FastBitmapDrawable(
-                        WidgetCell.generateFromRemoteViews(launcher, mRemoteViewsPreview,
-                                createWidgetInfo.info, maxWidth, previewSizeBeforeScale));
+                mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(launcher);
+                mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1,
+                        ((PendingAddWidgetInfo) mAddInfo).info);
+                DeviceProfile deviceProfile = launcher.getDeviceProfile();
+                Rect padding = new Rect();
+                mAppWidgetHostViewPreview.getWidgetInset(deviceProfile, padding);
+                mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
+                        padding.bottom);
+                mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
+                int width =
+                        deviceProfile.cellWidthPx * mAddInfo.spanX + padding.left + padding.right;
+                int height =
+                        deviceProfile.cellHeightPx * mAddInfo.spanY + padding.top + padding.bottom;
+                mAppWidgetHostViewPreview.measure(
+                        MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
             }
             if (mAppWidgetHostViewPreview != null) {
                 previewSizeBeforeScale[0] = mAppWidgetHostViewPreview.getMeasuredWidth();
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index c08160b..3fcd3f7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -46,7 +46,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.WidgetPreviewLoader;
 import com.android.launcher3.icons.BaseIconFactory;
-import com.android.launcher3.icons.BitmapRenderer;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.RoundDrawableWrapper;
 import com.android.launcher3.model.WidgetItem;
@@ -100,8 +99,8 @@
     private final CheckLongPressHelper mLongPressHelper;
     private final float mEnforcedCornerRadius;
 
-    private RemoteViews mPreview;
-    private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
+    private RemoteViews mRemoteViewsPreview;
+    private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
 
     public WidgetCell(Context context) {
         this(context, null);
@@ -143,12 +142,13 @@
         mWidgetDescription = findViewById(R.id.widget_description);
     }
 
-    public void setPreview(RemoteViews view) {
-        mPreview = view;
+    public void setRemoteViewsPreview(RemoteViews view) {
+        mRemoteViewsPreview = view;
     }
 
-    public RemoteViews getPreview() {
-        return mPreview;
+    @Nullable
+    public RemoteViews getRemoteViewsPreview() {
+        return mRemoteViewsPreview;
     }
 
     /**
@@ -172,7 +172,7 @@
             mActiveRequest.cancel();
             mActiveRequest = null;
         }
-        mPreview = null;
+        mRemoteViewsPreview = null;
         if (mAppWidgetHostViewPreview != null) {
             mWidgetImageContainer.removeView(mAppWidgetHostViewPreview);
         }
@@ -180,7 +180,7 @@
     }
 
     public void applyFromCellItem(WidgetItem item, WidgetPreviewLoader loader) {
-        applyPreviewLayout(item);
+        applyPreviewOnAppWidgetHostView(item);
 
         mItem = item;
         mWidgetName.setText(mItem.label);
@@ -206,9 +206,26 @@
         }
     }
 
-    private void applyPreviewLayout(WidgetItem item) {
+
+    private void applyPreviewOnAppWidgetHostView(WidgetItem item) {
+        if (mRemoteViewsPreview != null) {
+            mAppWidgetHostViewPreview = new NavigableAppWidgetHostView(getContext()) {
+                @Override
+                protected boolean shouldAllowDirectClick() {
+                    return false;
+                }
+            };
+            mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, item.widgetInfo);
+            Rect padding = new Rect();
+            mAppWidgetHostViewPreview.getWidgetInset(mActivity.getDeviceProfile(), padding);
+            mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
+                    padding.bottom);
+            mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
+            return;
+        }
+
         if (ATLEAST_S
-                && mPreview == null
+                && mRemoteViewsPreview == null
                 && item.widgetInfo != null
                 && item.widgetInfo.previewLayout != Resources.ID_NULL) {
             mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(getContext());
@@ -234,7 +251,7 @@
     }
 
     @Nullable
-    public LauncherAppWidgetHostView getAppWidgetHostViewPreview() {
+    public NavigableAppWidgetHostView getAppWidgetHostViewPreview() {
         return mAppWidgetHostViewPreview;
     }
 
@@ -303,15 +320,6 @@
     }
 
     public void ensurePreview() {
-        if (mPreview != null && mActiveRequest == null) {
-            Bitmap preview = generateFromRemoteViews(
-                    mActivity, mPreview, mItem.widgetInfo, mPresetPreviewSize, new int[1]);
-            if (preview != null) {
-                applyPreview(new FastBitmapDrawable(preview));
-                return;
-            }
-        }
-
         if (mAppWidgetHostViewPreview != null) {
             setContainerSize(mPreviewWidth, mPreviewHeight);
             FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
@@ -385,53 +393,4 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
     }
-
-    /**
-     * Generates a bitmap by inflating {@param views}.
-     * @see com.android.launcher3.WidgetPreviewLoader#generateWidgetPreview
-     *
-     * TODO: Consider moving this to the background thread.
-     */
-    public static Bitmap generateFromRemoteViews(BaseActivity activity, RemoteViews views,
-            LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
-        try {
-            return generateFromView(activity, views.apply(activity, new FrameLayout(activity)),
-                    info, previewSize, preScaledWidthOut);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    private static Bitmap generateFromView(BaseActivity activity, View v,
-            LauncherAppWidgetProviderInfo info, int previewSize, int[] preScaledWidthOut) {
-
-        DeviceProfile dp = activity.getDeviceProfile();
-        int viewWidth = dp.cellWidthPx * info.spanX;
-        int viewHeight = dp.cellHeightPx * info.spanY;
-
-        v.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY));
-
-        viewWidth = v.getMeasuredWidth();
-        viewHeight = v.getMeasuredHeight();
-        v.layout(0, 0, viewWidth, viewHeight);
-
-        preScaledWidthOut[0] = viewWidth;
-        final int bitmapWidth, bitmapHeight;
-        final float scale;
-        if (viewWidth > previewSize) {
-            scale = ((float) previewSize) / viewWidth;
-            bitmapWidth = previewSize;
-            bitmapHeight = (int) (viewHeight * scale);
-        } else {
-            scale = 1;
-            bitmapWidth = viewWidth;
-            bitmapHeight = viewHeight;
-        }
-
-        return BitmapRenderer.createSoftwareBitmap(bitmapWidth, bitmapHeight, c -> {
-            c.scale(scale, scale);
-            v.draw(c);
-        });
-    }
 }