Add support for bitmaps in wide screen IME

Bug: 172068293
Bug: 170343703
Test: Manual
Change-Id: Ibf160f65178d0a601089cf0a7b2f8dc5a369ad98
Merged-In: Ibf160f65178d0a601089cf0a7b2f8dc5a369ad98
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/imewidescreen/CarUiImeWideScreenController.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/imewidescreen/CarUiImeWideScreenController.java
index 953cf4d..65d9fc8 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/imewidescreen/CarUiImeWideScreenController.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/imewidescreen/CarUiImeWideScreenController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.ExtractEditText;
@@ -138,11 +139,23 @@
     // ArrayList<String>
     public static final String SEARCH_RESULT_SUB_TITLE_LIST = "search_result_sub_title_list";
     // Key used to provide the list of resource id for each primary image in search item.
-    // ArrayList<Integer>
+    // ArrayList<Integer>. If bitmap and res id both are provided than bitmap will take
+    // precedence over res id.
     public static final String SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST =
             "search_result_image_list";
+    // Key used to provide the list of bitmap for each primary image in search item.
+    // ArrayList<Integer>. If bitmap and res id both are provided than bitmap will take
+    // precedence over res id.
+    public static final String SEARCH_RESULT_PRIMARY_IMAGE_BITMAP_LIST =
+            "search_result_image_bitmap_list";
+    // Key used to provide the list of bitmap for each secondary image in search item.
+    // ArrayList<Integer>. If bitmap and res id both are provided than bitmap will take
+    // precedence over res id.
+    public static final String SEARCH_RESULT_SECONDARY_IMAGE_BITMAP_LIST =
+            "search_result_secondary_image_bitmap_list";
     // Key used to provide the list of id for each secondary image in search item.
-    // ArrayList<String>
+    // ArrayList<String>. If bitmap and res id both are provided than bitmap will take
+    // precedence over res id.
     public static final String SEARCH_RESULT_SECONDARY_IMAGE_ID =
             "search_result_secondary_image_id";
     // Key used to provide the list of resource id for each secondary image in search item.
@@ -388,8 +401,12 @@
         ArrayList<String> itemIdList = data.getStringArrayList(SEARCH_RESULT_ITEM_ID);
         ArrayList<String> titleList = data.getStringArrayList(SEARCH_RESULT_TITLE_LIST);
         ArrayList<String> subTitleList = data.getStringArrayList(SEARCH_RESULT_SUB_TITLE_LIST);
+        ArrayList<Bitmap> bitmapList = data.getParcelableArrayList(
+                SEARCH_RESULT_PRIMARY_IMAGE_BITMAP_LIST);
         ArrayList<Integer> primaryImageResIdList =
                 data.getIntegerArrayList(SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST);
+        ArrayList<Bitmap> secondaryBitmapList = data.getParcelableArrayList(
+                SEARCH_RESULT_SECONDARY_IMAGE_BITMAP_LIST);
         ArrayList<String> secondaryImageIdList =
                 data.getStringArrayList(SEARCH_RESULT_SECONDARY_IMAGE_ID);
         ArrayList<Integer> secondaryImageResIdList =
@@ -423,10 +440,16 @@
 
             if (primaryImageResIdList != null) {
                 searchItem.setPrimaryIconType(CarUiContentListItem.IconType.CONTENT);
-                searchItem.setIcon(loadDrawableFromPackage(primaryImageResIdList.get(i)));
+                if (bitmapList != null && bitmapList.get(i) != null) {
+                    searchItem.setIconBitmap(bitmapList.get(i));
+                } else {
+                    searchItem.setIcon(loadDrawableFromPackage(primaryImageResIdList.get(i)));
+                }
             }
 
-            if (secondaryImageResIdList != null && secondaryImageIdList != null) {
+            if (secondaryBitmapList != null && secondaryBitmapList.get(i) != null) {
+                searchItem.setSupplementalIconBitmap(secondaryBitmapList.get(i));
+            } else if (secondaryImageResIdList != null && secondaryImageIdList != null) {
                 searchItem.setSupplementalIcon(
                         loadDrawableFromPackage(secondaryImageResIdList.get(i)), v -> {
                             Bundle bundle = new Bundle();
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java
index e6a14d7..149252c 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiContentListItem.java
@@ -16,6 +16,7 @@
 
 package com.android.car.ui.recyclerview;
 
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 
 import androidx.annotation.NonNull;
@@ -101,8 +102,10 @@
     }
 
     private Drawable mIcon;
+    private Bitmap mIconBitmap;
     @Nullable
     private Drawable mSupplementalIcon;
+    private Bitmap mSupplementalIconBitmap;
     private CharSequence mTitle;
     private CharSequence mBody;
     private final Action mAction;
@@ -173,6 +176,23 @@
     }
 
     /**
+     * Returns the bitmap of the icon if provided.
+     */
+    @Nullable
+    public Bitmap getIconBitmap() {
+        return mIconBitmap;
+    }
+
+    /**
+     * Sets the bitmap of the icon.
+     *
+     * @param iconBitmap the bitmap of icon to display.
+     */
+    public void setIconBitmap(Bitmap iconBitmap) {
+        mIconBitmap = iconBitmap;
+    }
+
+    /**
      * Returns the primary icon type for the item.
      */
     public IconType getPrimaryIconType() {
@@ -272,6 +292,24 @@
         return mAction;
     }
 
+
+    /**
+     * Returns the bitmap of the supplemental icon if provided.
+     */
+    @Nullable
+    public Bitmap getSupplementalIconBitmap() {
+        return mSupplementalIconBitmap;
+    }
+
+    /**
+     * Sets the bitmap of the supplemental icon.
+     *
+     * @param supplementalIconBitmap the bitmap of icon to display.
+     */
+    public void setSupplementalIconBitmap(Bitmap supplementalIconBitmap) {
+        mSupplementalIconBitmap = supplementalIconBitmap;
+    }
+
     /**
      * Returns the supplemental icon for the item.
      */
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
index b737e92..e9955b9 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/CarUiListItemAdapter.java
@@ -18,6 +18,7 @@
 
 import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
 
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
@@ -192,6 +193,10 @@
             CharSequence title = item.getTitle();
             CharSequence body = item.getBody();
             Drawable icon = item.getIcon();
+            Bitmap iconBitmap = null;
+            if (icon == null) {
+                iconBitmap = item.getIconBitmap();
+            }
 
             if (!TextUtils.isEmpty(title)) {
                 mTitle.setText(title);
@@ -211,21 +216,33 @@
             mContentIcon.setVisibility(View.GONE);
             mAvatarIcon.setVisibility(View.GONE);
 
-            if (icon != null) {
+            if (icon != null || iconBitmap != null) {
                 mIconContainer.setVisibility(View.VISIBLE);
 
                 switch (item.getPrimaryIconType()) {
                     case CONTENT:
                         mContentIcon.setVisibility(View.VISIBLE);
-                        mContentIcon.setImageDrawable(icon);
+                        if (icon != null) {
+                            mContentIcon.setImageDrawable(icon);
+                        } else {
+                            mContentIcon.setImageBitmap(iconBitmap);
+                        }
                         break;
                     case STANDARD:
                         mIcon.setVisibility(View.VISIBLE);
-                        mIcon.setImageDrawable(icon);
+                        if (icon != null) {
+                            mIcon.setImageDrawable(icon);
+                        } else {
+                            mIcon.setImageBitmap(iconBitmap);
+                        }
                         break;
                     case AVATAR:
                         mAvatarIcon.setVisibility(View.VISIBLE);
-                        mAvatarIcon.setImageDrawable(icon);
+                        if (icon != null) {
+                            mAvatarIcon.setImageDrawable(icon);
+                        } else {
+                            mAvatarIcon.setImageBitmap(iconBitmap);
+                        }
                         mAvatarIcon.setClipToOutline(true);
                         break;
                 }
@@ -282,7 +299,12 @@
                     break;
                 case ICON:
                     mSupplementalIcon.setVisibility(View.VISIBLE);
-                    mSupplementalIcon.setImageDrawable(item.getSupplementalIcon());
+                    if (item.getSupplementalIcon() != null) {
+                        mSupplementalIcon.setImageDrawable(item.getSupplementalIcon());
+                    } else {
+                        mSupplementalIcon.setImageBitmap(item.getSupplementalIconBitmap());
+                    }
+
                     mActionContainer.setVisibility(View.VISIBLE);
 
                     // If the icon has a click listener, use a reduced touch interceptor to create
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java
index 7b0fe0a..a41bf14 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/SearchView.java
@@ -19,7 +19,9 @@
 
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.CONTENT_AREA_SURFACE_PACKAGE;
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_ITEM_ID;
+import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_PRIMARY_IMAGE_BITMAP_LIST;
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST;
+import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SECONDARY_IMAGE_BITMAP_LIST;
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SECONDARY_IMAGE_ID;
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SECONDARY_IMAGE_RES_ID_LIST;
 import static com.android.car.ui.imewidescreen.CarUiImeWideScreenController.SEARCH_RESULT_SUB_TITLE_LIST;
@@ -28,6 +30,7 @@
 import static com.android.car.ui.utils.CarUiUtils.requireViewByRefId;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.os.Build;
@@ -281,7 +284,9 @@
         ArrayList<String> itemIdList = new ArrayList<>();
         ArrayList<String> titleList = new ArrayList<>();
         ArrayList<String> subTitleList = new ArrayList<>();
+        ArrayList<Bitmap> primaryImageBitmapList = new ArrayList<>();
         ArrayList<Integer> primaryImageResId = new ArrayList<>();
+        ArrayList<Bitmap> secondaryImageBitmapList = new ArrayList<>();
         ArrayList<String> secondaryItemId = new ArrayList<>();
         ArrayList<Integer> secondaryImageResId = new ArrayList<>();
         int id = 0;
@@ -293,6 +298,8 @@
             primaryImageResId.add(item.getIconResId());
             secondaryItemId.add(idString);
             secondaryImageResId.add(item.getSupplementalIconResId());
+            primaryImageBitmapList.add(item.getIconBitmap());
+            secondaryImageBitmapList.add(item.getSupplementalIconBitmap());
 
             mIdToListItem.put(idString, item);
             id++;
@@ -302,6 +309,10 @@
         bundle.putStringArrayList(SEARCH_RESULT_ITEM_ID, itemIdList);
         bundle.putStringArrayList(SEARCH_RESULT_TITLE_LIST, titleList);
         bundle.putStringArrayList(SEARCH_RESULT_SUB_TITLE_LIST, subTitleList);
+        bundle.putParcelableArrayList(SEARCH_RESULT_PRIMARY_IMAGE_BITMAP_LIST,
+                primaryImageBitmapList);
+        bundle.putParcelableArrayList(SEARCH_RESULT_SECONDARY_IMAGE_BITMAP_LIST,
+                secondaryImageBitmapList);
         bundle.putIntegerArrayList(SEARCH_RESULT_PRIMARY_IMAGE_RES_ID_LIST, primaryImageResId);
         bundle.putStringArrayList(SEARCH_RESULT_SECONDARY_IMAGE_ID, secondaryItemId);
         bundle.putIntegerArrayList(SEARCH_RESULT_SECONDARY_IMAGE_RES_ID_LIST, secondaryImageResId);
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java
index e9ad2ae..ffa191b 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/utils/CarUiUtils.java
@@ -23,6 +23,9 @@
 import android.content.ContextWrapper;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.text.TextUtils;
@@ -300,4 +303,31 @@
             return null;
         }
     }
+
+    /**
+     * Converts a drawable to bitmap. This value should not be null.
+     */
+    public static Bitmap drawableToBitmap(@NonNull Drawable drawable) {
+        Bitmap bitmap;
+
+        if (drawable instanceof BitmapDrawable) {
+            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+            if (bitmapDrawable.getBitmap() != null) {
+                return bitmapDrawable.getBitmap();
+            }
+        }
+
+        if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
+            bitmap = Bitmap.createBitmap(1, 1,
+                    Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
+        } else {
+            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+        }
+
+        Canvas canvas = new Canvas(bitmap);
+        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+        drawable.draw(canvas);
+        return bitmap;
+    }
 }