From 77fafa55c81879c5715b74d212eed76d971db184 Mon Sep 17 00:00:00 2001 From: Anthony Chen Date: Mon, 24 Oct 2016 14:45:10 -0700 Subject: Fix bug where phone icon does not show up in stream cards. Using BitmapFactory.decodeResources() does not work for a VectorDrawable; null is returned. Instead, need to manually create the Bitmap. Test: manually tested Bug: 32379767 Change-Id: Iecdb6af431bcd6703d8dfb289c1f013272be22ef --- src/com/android/car/stream/BitmapUtils.java | 48 ++++++++++++++++++ src/com/android/car/stream/StreamProducer.java | 57 ++++++++++++++++++++-- .../car/stream/telecom/CurrentCallConverter.java | 8 +-- .../car/stream/telecom/RecentCallConverter.java | 7 +-- 4 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/com/android/car/stream/BitmapUtils.java diff --git a/src/com/android/car/stream/BitmapUtils.java b/src/com/android/car/stream/BitmapUtils.java new file mode 100644 index 0000000..e68b2ae --- /dev/null +++ b/src/com/android/car/stream/BitmapUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, 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.car.stream; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.VectorDrawable; +import android.support.annotation.Nullable; + +/** + * Utility class for manipulating Bitmaps. + */ +public class BitmapUtils { + private BitmapUtils() {} + + /** + * Returns a {@link Bitmap} from a {@link VectorDrawable}. + * {@link android.graphics.BitmapFactory#decodeResource(Resources, int)} cannot be used to + * retrieve a bitmap from a VectorDrawable, so this method works around that. + */ + @Nullable + public static Bitmap getBitmap(VectorDrawable vectorDrawable) { + if (vectorDrawable == null) { + return null; + } + + Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), + vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + vectorDrawable.draw(canvas); + return bitmap; + } +} diff --git a/src/com/android/car/stream/StreamProducer.java b/src/com/android/car/stream/StreamProducer.java index 0cb5212..d4971fc 100644 --- a/src/com/android/car/stream/StreamProducer.java +++ b/src/com/android/car/stream/StreamProducer.java @@ -23,38 +23,82 @@ import android.os.IBinder; import android.support.annotation.CallSuper; import android.util.Log; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Queue; + /** * A base class that produces {@link StreamCard} for the StreamService */ public abstract class StreamProducer { private static final String TAG = "StreamProducer"; + protected final Context mContext; + + /** + * A queue that holds {@link StreamCard}s that were added before this {@link StreamProducer} + * has connected to the {@link StreamService}. After connecting, these cards are posted to + * the StreamService. + */ + private final Queue mQueuedCards = new LinkedList<>(); + private StreamService mStreamService; - protected Context mContext; public StreamProducer(Context context) { mContext = context; } + /** + * Posts the given card to the {@link StreamService} for rendering by stream consumers. + * + * @return {@code true} if the card was successfully posted. {@code false} is returned if the + * {@link StreamService} is not available. The given card will be queued and posted when the + * {@link StreamService} becomes available. + */ public final boolean postCard(StreamCard card) { if (mStreamService != null) { mStreamService.addStreamCard(card); return true; } + if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "StreamService not found, unable to post card"); + Log.d(TAG, "StreamService not found, adding card to queue for later addition."); } + + mQueuedCards.add(card); return false; } + /** + * Removes the given card from the {@link StreamService}. If this {@link StreamProducer} has not + * connected to the {@link StreamService}, then {@link #mQueuedCards} is checked to see if it + * contains the given card. + * + * @return {@code true} if the card is successfully removed from either the + * {@link StreamService} or {@link #mQueuedCards}. + */ public final boolean removeCard(StreamCard card) { + if (card == null) { + return false; + } + if (mStreamService != null) { mStreamService.removeStreamCard(card); return true; } + if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "StreamService not found, unable to remove card"); + Log.d(TAG, "StreamService not found, checking if it exists in the queue."); } + + for (Iterator iterator = mQueuedCards.iterator(); iterator.hasNext();) { + StreamCard queuedCard = iterator.next(); + if (queuedCard.getType() == card.getType() && queuedCard.getId() == card.getId()) { + iterator.remove(); + return true; + } + } + return false; } @@ -81,6 +125,7 @@ public abstract class StreamProducer { @CallSuper public void stop() { mContext.unbindService(mServiceConnection); + mQueuedCards.clear(); } private ServiceConnection mServiceConnection = new ServiceConnection() { @@ -89,6 +134,10 @@ public abstract class StreamProducer { StreamService.StreamProducerBinder binder = (StreamService.StreamProducerBinder) service; mStreamService = binder.getService(); + + while (!mQueuedCards.isEmpty()) { + mStreamService.addStreamCard(mQueuedCards.remove()); + } } @Override @@ -96,4 +145,4 @@ public abstract class StreamProducer { mStreamService = null; } }; -} \ No newline at end of file +} diff --git a/src/com/android/car/stream/telecom/CurrentCallConverter.java b/src/com/android/car/stream/telecom/CurrentCallConverter.java index 39c07fd..8c29919 100644 --- a/src/com/android/car/stream/telecom/CurrentCallConverter.java +++ b/src/com/android/car/stream/telecom/CurrentCallConverter.java @@ -19,10 +19,10 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.graphics.drawable.VectorDrawable; import android.telecom.Call; +import com.android.car.stream.BitmapUtils; import com.android.car.stream.CurrentCallExtension; - import com.android.car.stream.R; import com.android.car.stream.StreamCard; import com.android.car.stream.StreamConstants; @@ -87,8 +87,8 @@ public class CurrentCallConverter { builder.setPrimaryText(displayName); builder.setSecondaryText(getCallState(context, callState)); - Bitmap phoneIcon = BitmapFactory.decodeResource(context.getResources(), - R.drawable.ic_phone); + Bitmap phoneIcon = BitmapUtils.getBitmap( + (VectorDrawable) context.getDrawable(R.drawable.ic_phone)); builder.setPrimaryIcon(phoneIcon); builder.setSecondaryIcon(TelecomUtils.createStreamCardSecondaryIcon(context, number)); builder.setClickAction(dialerPendingIntent); diff --git a/src/com/android/car/stream/telecom/RecentCallConverter.java b/src/com/android/car/stream/telecom/RecentCallConverter.java index 57c65bc..77bcec8 100644 --- a/src/com/android/car/stream/telecom/RecentCallConverter.java +++ b/src/com/android/car/stream/telecom/RecentCallConverter.java @@ -19,8 +19,9 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.graphics.drawable.VectorDrawable; import android.net.Uri; +import com.android.car.stream.BitmapUtils; import com.android.car.stream.R; import com.android.car.stream.StreamCard; import com.android.car.stream.StreamConstants; @@ -39,8 +40,8 @@ public class RecentCallConverter { builder.setPrimaryText(displayName); builder.setSecondaryText(context.getString(R.string.recent_call)); builder.setDescription(context.getString(R.string.recent_call)); - Bitmap phoneIcon = BitmapFactory.decodeResource(context.getResources(), - R.drawable.ic_phone); + Bitmap phoneIcon = BitmapUtils.getBitmap( + (VectorDrawable) context.getDrawable(R.drawable.ic_phone)); builder.setPrimaryIcon(phoneIcon); builder.setSecondaryIcon(TelecomUtils.createStreamCardSecondaryIcon(context, number)); -- cgit v1.2.3