Updating widget preview generation to not embed any badge.
Instead drawing badge in the view directly.

This will allow us to reuse the same preview when we do not want to draw
badges. This also simplified badging of shortcut config activities.

Change-Id: I9c07c33bf9c2b8ef81a00026b1d42587868c906f
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 83c978e..81341cb 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -70,7 +70,6 @@
     private final UserManagerCompat mUserManager;
     private final AppWidgetManagerCompat mWidgetManager;
     private final CacheDb mDb;
-    private final int mProfileBadgeMargin;
 
     private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
     @Thunk final Handler mWorkerHandler;
@@ -82,8 +81,6 @@
         mUserManager = UserManagerCompat.getInstance(context);
         mDb = new CacheDb(context);
         mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
-        mProfileBadgeMargin = context.getResources()
-                .getDimensionPixelSize(R.dimen.profile_badge_margin);
     }
 
     /**
@@ -107,7 +104,7 @@
      * sizes (landscape vs portrait).
      */
     private static class CacheDb extends SQLiteCacheHelper {
-        private static final int DB_VERSION = 4;
+        private static final int DB_VERSION = 5;
 
         private static final String TABLE_NAME = "shortcut_and_widget_previews";
         private static final String COLUMN_COMPONENT = "componentName";
@@ -344,7 +341,7 @@
             preScaledWidthOut[0] = previewWidth;
         }
         if (previewWidth > maxPreviewWidth) {
-            scale = (maxPreviewWidth - 2 * mProfileBadgeMargin) / (float) (previewWidth);
+            scale = maxPreviewWidth / (float) (previewWidth);
         }
         if (scale != 1f) {
             previewWidth = (int) (scale * previewWidth);
@@ -357,6 +354,12 @@
             preview = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888);
             c.setBitmap(preview);
         } else {
+            // We use the preview bitmap height to determine where the badge will be drawn in the
+            // UI. If its larger than what we need, resize the preview bitmap so that there are
+            // no transparent pixels between the preview and the badge.
+            if (preview.getHeight() > previewHeight) {
+                preview.reconfigure(preview.getWidth(), previewHeight, preview.getConfig());
+            }
             // Reusing bitmap. Clear it.
             c.setBitmap(preview);
             c.drawColor(0, PorterDuff.Mode.CLEAR);
@@ -409,9 +412,7 @@
             }
             c.setBitmap(null);
         }
-        int imageWidth = Math.min(preview.getWidth(), previewWidth + mProfileBadgeMargin);
-        int imageHeight = Math.min(preview.getHeight(), previewHeight + mProfileBadgeMargin);
-        return mWidgetManager.getBadgeBitmap(info, preview, imageWidth, imageHeight);
+        return preview;
     }
 
     private Bitmap generateShortcutPreview(
@@ -538,6 +539,7 @@
         private final int mPreviewHeight;
         private final int mPreviewWidth;
         private final WidgetCell mCaller;
+        private final BaseActivity mActivity;
         @Thunk long[] mVersions;
         @Thunk Bitmap mBitmapToRecycle;
 
@@ -548,6 +550,7 @@
             mPreviewHeight = previewHeight;
             mPreviewWidth = previewWidth;
             mCaller = caller;
+            mActivity = BaseActivity.fromContext(mCaller.getContext());
             if (DEBUG) {
                 Log.d(TAG, String.format("%s, %s, %d, %d",
                         mKey, mInfo, mPreviewHeight, mPreviewWidth));
@@ -591,10 +594,8 @@
                 // which would gets re-written next time.
                 mVersions = getPackageVersion(mKey.componentName.getPackageName());
 
-                BaseActivity launcher = BaseActivity.fromContext(mCaller.getContext());
-
                 // it's not in the db... we need to generate it
-                preview = generatePreview(launcher, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight);
+                preview = generatePreview(mActivity, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight);
             }
             return preview;
         }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
index af43c02..7911bb2 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -71,9 +71,6 @@
     public abstract void startConfigActivity(AppWidgetProviderInfo info, int widgetId,
             Activity activity, AppWidgetHost host, int requestCode);
 
-    public abstract Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
-            int imageWidth, int imageHeight);
-
     public abstract LauncherAppWidgetProviderInfo findProvider(
             ComponentName provider, UserHandle user);
 
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
index 56a7f46..61dd1a5 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -23,17 +23,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.view.View;
 import android.widget.Toast;
 
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
@@ -82,47 +74,6 @@
     }
 
     @Override
-    public Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
-            int imageWidth, int imageHeight) {
-        if (info.isCustomWidget || info.getProfile().equals(android.os.Process.myUserHandle())) {
-            return bitmap;
-        }
-
-        // Add a user badge in the bottom right of the image.
-        final Resources res = mContext.getResources();
-        final int badgeMinTop = res.getDimensionPixelSize(R.dimen.profile_badge_minimum_top);
-
-        // choose min between badge size defined for widget tray versus width, height of the image.
-        // Width, height of the image can be smaller than widget tray badge size when being dropped
-        // to the workspace.
-        final int badgeSize = Math.min(res.getDimensionPixelSize(R.dimen.profile_badge_size),
-                Math.min(imageWidth, imageHeight - badgeMinTop));
-        final Rect badgeLocation = new Rect(0, 0, badgeSize, badgeSize);
-
-        final int top = Math.max(imageHeight - badgeSize, badgeMinTop);
-
-        if (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
-            badgeLocation.offset(0, top);
-        } else {
-            badgeLocation.offset(bitmap.getWidth() - badgeSize, top);
-        }
-
-        Drawable drawable = mPm.getUserBadgedDrawableForDensity(
-                new BitmapDrawable(res, bitmap), info.getProfile(), badgeLocation, 0);
-
-        if (drawable instanceof BitmapDrawable) {
-            return ((BitmapDrawable) drawable).getBitmap();
-        }
-
-        bitmap.eraseColor(Color.TRANSPARENT);
-        Canvas c = new Canvas(bitmap);
-        drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
-        drawable.draw(c);
-        c.setBitmap(null);
-        return bitmap;
-    }
-
-    @Override
     public LauncherAppWidgetProviderInfo findProvider(ComponentName provider, UserHandle user) {
         for (AppWidgetProviderInfo info : mAppWidgetManager
                 .getInstalledProvidersForProfile(user)) {
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 693df7a..4d4d508 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -17,7 +17,16 @@
 package com.android.launcher3.graphics;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Process;
+import android.os.UserHandle;
+import android.support.annotation.UiThread;
 
 import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.ItemInfo;
@@ -25,6 +34,8 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.AllAppsBackgroundDrawable;
 
+import java.util.HashMap;
+
 /**
  * Factory for creating new drawables.
  */
@@ -43,6 +54,9 @@
         }
     }
 
+    protected final UserHandle mMyUser = Process.myUserHandle();
+    protected final HashMap<UserHandle, Bitmap> mUserBadges = new HashMap<>();
+
     /**
      * Returns a FastBitmapDrawable with the icon.
      */
@@ -55,4 +69,47 @@
     public AllAppsBackgroundDrawable getAllAppsBackground(Context context) {
         return new AllAppsBackgroundDrawable(context);
     }
+
+    /**
+     * Returns a drawable that can be used as a badge for the user or null.
+     */
+    @UiThread
+    public Drawable getBadgeForUser(UserHandle user, Context context) {
+        if (mMyUser.equals(user)) {
+            return null;
+        }
+
+        Bitmap badgeBitmap = getUserBadge(user, context);
+        FastBitmapDrawable d = new FastBitmapDrawable(badgeBitmap);
+        d.setFilterBitmap(true);
+        d.setBounds(0, 0, badgeBitmap.getWidth(), badgeBitmap.getHeight());
+        return d;
+    }
+
+    protected synchronized Bitmap getUserBadge(UserHandle user, Context context) {
+        Bitmap badgeBitmap = mUserBadges.get(user);
+        if (badgeBitmap != null) {
+            return badgeBitmap;
+        }
+
+        final Resources res = context.getApplicationContext().getResources();
+        int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size);
+        badgeBitmap = Bitmap.createBitmap(badgeSize, badgeSize, Bitmap.Config.ARGB_8888);
+
+        Drawable drawable = context.getPackageManager().getUserBadgedDrawableForDensity(
+                new BitmapDrawable(res, badgeBitmap), user, new Rect(0, 0, badgeSize, badgeSize),
+                0);
+        if (drawable instanceof BitmapDrawable) {
+            badgeBitmap = ((BitmapDrawable) drawable).getBitmap();
+        } else {
+            badgeBitmap.eraseColor(Color.TRANSPARENT);
+            Canvas c = new Canvas(badgeBitmap);
+            drawable.setBounds(0, 0, badgeSize, badgeSize);
+            drawable.draw(c);
+            c.setBitmap(null);
+        }
+
+        mUserBadges.put(user, badgeBitmap);
+        return badgeBitmap;
+    }
 }
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 9e2091b..d07139d 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -34,6 +34,7 @@
 import com.android.launcher3.StylusEventHelper;
 import com.android.launcher3.WidgetPreviewLoader;
 import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
+import com.android.launcher3.graphics.DrawableFactory;
 import com.android.launcher3.model.WidgetItem;
 
 /**
@@ -116,7 +117,7 @@
             Log.d(TAG, "reset called on:" + mWidgetName.getText());
         }
         mWidgetImage.animate().cancel();
-        mWidgetImage.setBitmap(null);
+        mWidgetImage.setBitmap(null, null);
         mWidgetName.setText(null);
         mWidgetDims.setText(null);
 
@@ -152,7 +153,8 @@
 
     public void applyPreview(Bitmap bitmap) {
         if (bitmap != null) {
-            mWidgetImage.setBitmap(bitmap);
+            mWidgetImage.setBitmap(bitmap,
+                    DrawableFactory.get(getContext()).getBadgeForUser(mItem.user, getContext()));
             mWidgetImage.setAlpha(0f);
             ViewPropertyAnimator anim = mWidgetImage.animate();
             anim.alpha(1.0f).setDuration(FADE_IN_DURATION_MS);
diff --git a/src/com/android/launcher3/widget/WidgetImageView.java b/src/com/android/launcher3/widget/WidgetImageView.java
index b0fbe1e..1211c08 100644
--- a/src/com/android/launcher3/widget/WidgetImageView.java
+++ b/src/com/android/launcher3/widget/WidgetImageView.java
@@ -22,9 +22,13 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
 /**
  * View that draws a bitmap horizontally centered. If the image width is greater than the view
  * width, the image is scaled down appropriately.
@@ -33,22 +37,29 @@
 
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
     private final RectF mDstRectF = new RectF();
+    private final int mBadgeMargin;
+
     private Bitmap mBitmap;
+    private Drawable mBadge;
 
     public WidgetImageView(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public WidgetImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public WidgetImageView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+
+        mBadgeMargin = context.getResources()
+                .getDimensionPixelSize(R.dimen.profile_badge_margin);
     }
 
-    public void setBitmap(Bitmap bitmap) {
+    public void setBitmap(Bitmap bitmap, Drawable badge) {
         mBitmap = bitmap;
+        mBadge = badge;
         invalidate();
     }
 
@@ -61,6 +72,11 @@
         if (mBitmap != null) {
             updateDstRectF();
             canvas.drawBitmap(mBitmap, null, mDstRectF, mPaint);
+
+            // Only draw the badge if a preview was drawn.
+            if (mBadge != null) {
+                mBadge.draw(canvas);
+            }
         }
     }
 
@@ -83,6 +99,16 @@
                     (getWidth() + mBitmap.getWidth()) * 0.5f,
                     mBitmap.getHeight());
         }
+        if (mBadge != null) {
+            Rect bounds = mBadge.getBounds();
+            int left = Utilities.boundToRange(
+                    (int) (mDstRectF.right + mBadgeMargin - bounds.width()),
+                    mBadgeMargin, getWidth() - bounds.width());
+            int top = Utilities.boundToRange(
+                    (int) (mDstRectF.bottom + mBadgeMargin - bounds.height()),
+                    mBadgeMargin, getHeight() - bounds.height());
+            mBadge.setBounds(left, top, bounds.width() + left, bounds.height() + top);
+        }
     }
 
     /**