DO NOT MERGE: Add support for lane guidance transparency am: 16dca10dab
am: d602116153

Change-Id: I8e62a9350e78d48bc3ebaaf5d01c466f87e6f994
diff --git a/src/android/car/cluster/ImageResolver.java b/src/android/car/cluster/ImageResolver.java
index 45fcf31..2e1ada9 100644
--- a/src/android/car/cluster/ImageResolver.java
+++ b/src/android/car/cluster/ImageResolver.java
@@ -18,7 +18,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.car.cluster.navigation.NavigationState.ImageReference;
-import android.car.cluster.renderer.InvalidSizeException;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.net.Uri;
@@ -45,7 +44,12 @@
         /**
          * Returns a {@link Bitmap} given a request Uri and dimensions
          */
-        Bitmap getBitmap(Uri uri, int width, int height) throws InvalidSizeException;
+        Bitmap getBitmap(Uri uri, int width, int height);
+
+        /**
+         * Returns a {@link Bitmap} given a request Uri, dimensions, and offLanesAlpha value
+         */
+        Bitmap getBitmap(Uri uri, int width, int height, float offLanesAlpha);
     }
 
     /**
@@ -65,6 +69,22 @@
      */
     @NonNull
     public CompletableFuture<Bitmap> getBitmap(@NonNull ImageReference img, int width, int height) {
+        return getBitmap(img, width, height, 1f);
+    }
+
+    /**
+     * Returns a {@link CompletableFuture} that provides a bitmap from a {@link ImageReference}.
+     * This image would fit inside the provided size. Either width, height or both should be greater
+     * than 0.
+     *
+     * @param width         required width, or 0 if width is flexible based on height.
+     * @param height        required height, or 0 if height is flexible based on width.
+     * @param offLanesAlpha opacity value for off lane guidance images. Only applies to lane
+     *                      guidance images. 0 (transparent) <= offLanesAlpha <= 1 (opaque).
+     */
+    @NonNull
+    public CompletableFuture<Bitmap> getBitmap(@NonNull ImageReference img, int width, int height,
+            float offLanesAlpha) {
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, String.format("Requesting image %s (width: %d, height: %d)",
                     img.getContentUri(), width, height));
@@ -81,9 +101,9 @@
             Uri uri = Uri.parse(img.getContentUri());
             Bitmap bitmap = null;
             try {
-                bitmap = mFetcher.getBitmap(uri, adjusted.x, adjusted.y);
-            } catch (InvalidSizeException e) {
-                Log.e(TAG, "Bitmap must have positive width and height");
+                bitmap = mFetcher.getBitmap(uri, adjusted.x, adjusted.y, offLanesAlpha);
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, e.getMessage());
             }
             if (bitmap == null) {
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -111,12 +131,28 @@
     @NonNull
     public CompletableFuture<Map<ImageReference, Bitmap>> getBitmaps(
             @NonNull List<ImageReference> imgs, int width, int height) {
+        return getBitmaps(imgs, width, height, 1f);
+    }
+
+    /**
+     * Same as {@link #getBitmap(ImageReference, int, int)} but it works on a list of images. The
+     * returning {@link CompletableFuture} will contain a map from each {@link ImageReference} to
+     * its bitmap. If any image fails to be fetched, the whole future completes exceptionally.
+     *
+     * @param width         required width, or 0 if width is flexible based on height.
+     * @param height        required height, or 0 if height is flexible based on width.
+     * @param offLanesAlpha opacity value for off lane guidance images. Only applies to lane
+     *                      guidance images. 0 (transparent) <= offLanesAlpha <= 1 (opaque).
+     */
+    @NonNull
+    public CompletableFuture<Map<ImageReference, Bitmap>> getBitmaps(
+            @NonNull List<ImageReference> imgs, int width, int height, float offLanesAlpha) {
         CompletableFuture<Map<ImageReference, Bitmap>> future = new CompletableFuture<>();
 
         Map<ImageReference, CompletableFuture<Bitmap>> bitmapFutures = imgs.stream().collect(
                 Collectors.toMap(
                         img -> img,
-                        img -> getBitmap(img, width, height)));
+                        img -> getBitmap(img, width, height, offLanesAlpha)));
 
         CompletableFuture.allOf(bitmapFutures.values().toArray(new CompletableFuture[0]))
                 .thenAccept(v -> {
diff --git a/tests/robotests/src/android/car/cluster/ImageResolverTest.java b/tests/robotests/src/android/car/cluster/ImageResolverTest.java
index 0c05390..9b39659 100644
--- a/tests/robotests/src/android/car/cluster/ImageResolverTest.java
+++ b/tests/robotests/src/android/car/cluster/ImageResolverTest.java
@@ -17,7 +17,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.graphics.Bitmap;
 import android.graphics.Point;
+import android.net.Uri;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -32,7 +34,17 @@
 
     @Before
     public void setup() {
-        mImageResolver = new ImageResolver((uri, w, h) -> null);
+        mImageResolver = new ImageResolver(new ImageResolver.BitmapFetcher() {
+            @Override
+            public Bitmap getBitmap(Uri uri, int width, int height) {
+                return null;
+            }
+
+            @Override
+            public Bitmap getBitmap(Uri uri, int width, int height, float offLanesAlpha) {
+                return null;
+            }
+        });
     }
 
     @Test