Using WidgetCell in the Pin Item confirmation prompt for a consistent UI
Also fixing some platform API changes in PinItemRequestCompat

Bug: 33584624
Change-Id: I255829f0079f1a3967bf8d6a337da12c890eb7ec
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index f814bb7..091ae99 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -592,7 +592,10 @@
                 // Fetch the version info before we generate the preview, so that, in-case the
                 // app was updated while we are generating the preview, we use the old version info,
                 // which would gets re-written next time.
-                mVersions = getPackageVersion(mKey.componentName.getPackageName());
+                boolean persistable = mInfo.activityInfo == null
+                        || mInfo.activityInfo.isPersistable();
+                mVersions = persistable ? getPackageVersion(mKey.componentName.getPackageName())
+                        : null;
 
                 // it's not in the db... we need to generate it
                 preview = generatePreview(mActivity, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight);
diff --git a/src/com/android/launcher3/compat/PinItemRequestCompat.java b/src/com/android/launcher3/compat/PinItemRequestCompat.java
index 956b38c..74d7765 100644
--- a/src/com/android/launcher3/compat/PinItemRequestCompat.java
+++ b/src/com/android/launcher3/compat/PinItemRequestCompat.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.compat;
 
 import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
@@ -47,8 +48,14 @@
         return (ShortcutInfo) invokeMethod("getShortcutInfo");
     }
 
-    public AppWidgetProviderInfo getAppWidgetProviderInfo() {
-        return (AppWidgetProviderInfo) invokeMethod("getAppWidgetProviderInfo");
+    public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
+        try {
+            return (AppWidgetProviderInfo) mObject.getClass()
+                    .getDeclaredMethod("getAppWidgetProviderInfo", Context.class)
+                    .invoke(mObject, context);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     public boolean isValid() {
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index dd375df..ece7759 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -50,7 +50,7 @@
     private final ComponentName mCn;
     private final UserHandle mUser;
 
-    private ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) {
+    protected ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) {
         mCn = cn;
         mUser = user;
     }
@@ -84,6 +84,14 @@
         return false;
     }
 
+    /**
+     * Returns true if various properties ({@link #getLabel()}, {@link #getFullResIcon}) can
+     * be safely persisted.
+     */
+    public boolean isPersistable() {
+        return true;
+    }
+
     static class ShortcutConfigActivityInfoVL extends ShortcutConfigActivityInfo {
 
         private final ActivityInfo mInfo;
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index c48db60..6c6f141 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -19,17 +19,12 @@
 import android.annotation.TargetApi;
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.os.Build;
 import android.os.Bundle;
-import android.text.TextUtils;
 import android.view.View;
-import android.widget.TextView;
 
 import com.android.launcher3.BaseActivity;
-import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.InstallShortcutReceiver;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.Launcher;
@@ -38,10 +33,10 @@
 import com.android.launcher3.R;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.PinItemRequestCompat;
-import com.android.launcher3.graphics.LauncherIcons;
-import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.shortcuts.ShortcutInfoCompat;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.WidgetHostViewLoader;
 
 @TargetApi(Build.VERSION_CODES.N_MR1)
@@ -54,7 +49,7 @@
     private LauncherAppState mApp;
     private InvariantDeviceProfile mIdp;
 
-    private TextView mTextView;
+    private WidgetCell mWidgetCell;
 
     // Widget request specific options.
     private AppWidgetHost mAppWidgetHost;
@@ -73,9 +68,6 @@
             return;
         }
 
-        setContentView(R.layout.add_item_confirmation_activity);
-        mTextView = (TextView) findViewById(R.id.drag_target);
-
         mApp = LauncherAppState.getInstance(this);
         mIdp = mApp.getInvariantDeviceProfile();
 
@@ -83,6 +75,9 @@
         // confirmation activity might be rotated.
         mDeviceProfile = mIdp.getDeviceProfile(getApplicationContext());
 
+        setContentView(R.layout.add_item_confirmation_activity);
+        mWidgetCell = (WidgetCell) findViewById(R.id.widget_cell);
+
         if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
             setupShortcut();
         } else {
@@ -94,20 +89,15 @@
     }
 
     private void setupShortcut() {
-        ShortcutInfoCompat shortcut = new ShortcutInfoCompat(mRequest.getShortcutInfo());
-        FastBitmapDrawable d = new FastBitmapDrawable(LauncherIcons.createIconBitmap(
-                DeepShortcutManager.getInstance(this).getShortcutIconDrawable(
-                        shortcut, mIdp.fillResIconDpi), this));
-        d.setFilterBitmap(true);
-        mTextView.setText(TextUtils.isEmpty(shortcut.getLongLabel())
-                ? shortcut.getShortLabel() : shortcut.getLongLabel());
-        mTextView.setCompoundDrawables(null, d, null, null);
+        WidgetItem item = new WidgetItem(new PinShortcutRequestActivityInfo(
+                mRequest.getShortcutInfo(), this));
+        mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
+        mWidgetCell.ensurePreview();
     }
 
     private boolean setupWidget() {
-        AppWidgetProviderInfo info = mRequest.getAppWidgetProviderInfo();
-        LauncherAppWidgetProviderInfo widgetInfo = AppWidgetManagerCompat.getInstance(this)
-                .findProvider(info.provider, info.getProfile());
+        LauncherAppWidgetProviderInfo widgetInfo = LauncherAppWidgetProviderInfo
+                .fromProviderInfo(this, mRequest.getAppWidgetProviderInfo(this));
         if (widgetInfo.minSpanX > mIdp.numColumns || widgetInfo.minSpanY > mIdp.numRows) {
             // Cannot add widget
             return false;
@@ -121,12 +111,9 @@
         mPendingWidgetInfo.spanY = Math.min(mIdp.numRows, widgetInfo.spanY);
         mWidgetOptions = WidgetHostViewLoader.getDefaultOptionsForWidget(this, mPendingWidgetInfo);
 
-        Bitmap preview = mApp.getWidgetCache().generateWidgetPreview(this, widgetInfo,
-                mPendingWidgetInfo.spanX * mDeviceProfile.cellWidthPx, null, null);
-        FastBitmapDrawable d = new FastBitmapDrawable(preview);
-        d.setFilterBitmap(true);
-        mTextView.setText(widgetInfo.getLabel(getPackageManager()));
-        mTextView.setCompoundDrawables(null, d, null, null);
+        WidgetItem item = new WidgetItem(widgetInfo, getPackageManager(), mIdp);
+        mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
+        mWidgetCell.ensurePreview();
         return true;
     }
 
@@ -151,7 +138,7 @@
 
         mPendingBindWidgetId = mAppWidgetHost.allocateAppWidgetId();
         boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
-                mPendingBindWidgetId, mRequest.getAppWidgetProviderInfo(), mWidgetOptions);
+                mPendingBindWidgetId, mRequest.getAppWidgetProviderInfo(this), mWidgetOptions);
         if (success) {
             acceptWidget(mPendingBindWidgetId);
             return;
@@ -163,12 +150,12 @@
         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
                 mPendingWidgetInfo.componentName);
         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE,
-                mRequest.getAppWidgetProviderInfo().getProfile());
+                mRequest.getAppWidgetProviderInfo(this).getProfile());
         startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
     }
 
     private void acceptWidget(int widgetId) {
-        InstallShortcutReceiver.queueWidget(mRequest.getAppWidgetProviderInfo(), widgetId, this);
+        InstallShortcutReceiver.queueWidget(mRequest.getAppWidgetProviderInfo(this), widgetId, this);
         mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
         mRequest.accept(mWidgetOptions);
         finish();
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
new file mode 100644
index 0000000..d1f878a
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.dragndrop;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+
+import com.android.launcher3.IconCache;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.compat.ShortcutConfigActivityInfo;
+
+/**
+ * Extension of ShortcutConfigActivityInfo to be used in the confirmation prompt for pin item
+ * request.
+ */
+@TargetApi(Build.VERSION_CODES.N_MR1)
+class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
+
+    // Class name used in the target component, such that it will never represent an
+    // actual existing class.
+    private static final String DUMMY_COMPONENT_CLASS = "pinned-shortcut";
+
+    private final ShortcutInfo mInfo;
+    private final Context mContext;
+
+    public PinShortcutRequestActivityInfo(ShortcutInfo info, Context context) {
+        super(new ComponentName(info.getPackage(), DUMMY_COMPONENT_CLASS), info.getUserHandle());
+        mInfo = info;
+        mContext = context;
+    }
+
+    @Override
+    public CharSequence getLabel() {
+        return mInfo.getShortLabel();
+    }
+
+    @Override
+    public Drawable getFullResIcon(IconCache cache) {
+        return mContext.getSystemService(LauncherApps.class)
+                .getShortcutIconDrawable(mInfo, LauncherAppState.getIDP(mContext).fillResIconDpi);
+    }
+
+    @Override
+    public boolean startConfigActivity(Activity activity, int requestCode) {
+        throw new RuntimeException("Not supported");
+    }
+
+    @Override
+    public boolean isPersistable() {
+        return false;
+    }
+}
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index d07139d..87247f4 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -23,6 +23,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -60,7 +61,7 @@
     private static final float PREVIEW_SCALE = 0.8f;
 
     private int mPresetPreviewSize;
-    int cellSize;
+    private int mCellSize;
 
     private WidgetImageView mWidgetImage;
     private TextView mWidgetName;
@@ -96,8 +97,8 @@
 
     private void setContainerWidth() {
         DeviceProfile profile = mActivity.getDeviceProfile();
-        cellSize = (int) (profile.cellWidthPx * WIDTH_SCALE);
-        mPresetPreviewSize = (int) (cellSize * PREVIEW_SCALE);
+        mCellSize = (int) (profile.cellWidthPx * WIDTH_SCALE);
+        mPresetPreviewSize = (int) (mCellSize * PREVIEW_SCALE);
     }
 
     @Override
@@ -201,6 +202,12 @@
     }
 
     @Override
+    public void setLayoutParams(ViewGroup.LayoutParams params) {
+        params.width = params.height = mCellSize;
+        super.setLayoutParams(params);
+    }
+
+    @Override
     public CharSequence getAccessibilityClassName() {
         return WidgetCell.class.getName();
     }
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index 2d746d7..60e6e2a 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -22,7 +22,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.LauncherAppState;
@@ -124,11 +123,6 @@
                 // set up touch.
                 widget.setOnClickListener(mIconClickListener);
                 widget.setOnLongClickListener(mIconLongClickListener);
-                LayoutParams lp = widget.getLayoutParams();
-                lp.height = widget.cellSize;
-                lp.width = widget.cellSize;
-                widget.setLayoutParams(lp);
-
                 row.addView(widget);
             }
         } else if (diff < 0) {