diff options
| author | 2020-04-21 19:57:09 +0000 | |
|---|---|---|
| committer | 2020-04-21 19:57:09 +0000 | |
| commit | 9f4b4c23e794e79bb1fe96e1cfcd9609fcac1efc (patch) | |
| tree | 822e0d2afb778f3b386f44dfbb8c2a46c95eddf1 | |
| parent | 126b567a6e3868267eb1847edfe3a73d144ce68e (diff) | |
| parent | d3ad81d4a61a85a7d1df170c70754a647ae5c07f (diff) | |
Merge "Improve album art handling" into rvc-dev
5 files changed, 100 insertions, 23 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index f25de6a553e8..233d24b17d44 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -26,14 +26,18 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.ColorStateList; import android.graphics.Bitmap; +import android.graphics.ImageDecoder; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.Icon; import android.graphics.drawable.RippleDrawable; import android.media.MediaDescription; import android.media.MediaMetadata; +import android.media.ThumbnailUtils; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; +import android.net.Uri; import android.service.media.MediaBrowserService; import android.util.Log; import android.view.LayoutInflater; @@ -59,6 +63,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSMediaBrowser; import com.android.systemui.util.Assert; +import java.io.IOException; import java.util.List; import java.util.concurrent.Executor; @@ -99,6 +104,13 @@ public class MediaControlPanel { com.android.internal.R.id.action4 }; + // URI fields to try loading album art from + private static final String[] ART_URIS = { + MediaMetadata.METADATA_KEY_ALBUM_ART_URI, + MediaMetadata.METADATA_KEY_ART_URI, + MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI + }; + private final MediaController.Callback mSessionCallback = new MediaController.Callback() { @Override public void onSessionDestroyed() { @@ -205,14 +217,16 @@ public class MediaControlPanel { * Update the media panel view for the given media session * @param token * @param iconDrawable + * @param largeIcon * @param iconColor * @param bgColor * @param contentIntent * @param appNameString * @param key */ - public void setMediaSession(MediaSession.Token token, Drawable iconDrawable, int iconColor, - int bgColor, PendingIntent contentIntent, String appNameString, String key) { + public void setMediaSession(MediaSession.Token token, Drawable iconDrawable, Icon largeIcon, + int iconColor, int bgColor, PendingIntent contentIntent, String appNameString, + String key) { // Ensure that component names are updated if token has changed if (mToken == null || !mToken.equals(token)) { mToken = token; @@ -303,7 +317,7 @@ public class MediaControlPanel { ImageView albumView = mMediaNotifView.findViewById(R.id.album_art); if (albumView != null) { // Resize art in a background thread - mBackgroundExecutor.execute(() -> processAlbumArt(mediaMetadata, albumView)); + mBackgroundExecutor.execute(() -> processAlbumArt(mediaMetadata, largeIcon, albumView)); } // Song name @@ -396,30 +410,82 @@ public class MediaControlPanel { * @param albumView view to hold the album art */ protected void processAlbumArt(MediaDescription description, ImageView albumView) { - Bitmap albumArt = description.getIconBitmap(); - //TODO check other fields (b/151054111, b/152067055) + Bitmap albumArt = null; + + // First try loading from URI + albumArt = loadBitmapFromUri(description.getIconUri()); + + // Then check bitmap + if (albumArt == null) { + albumArt = description.getIconBitmap(); + } + processAlbumArtInternal(albumArt, albumView); } /** * Process album art for layout * @param metadata media metadata + * @param largeIcon from notification, checked as a fallback if metadata does not have art * @param albumView view to hold the album art */ - private void processAlbumArt(MediaMetadata metadata, ImageView albumView) { - Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); - //TODO check other fields (b/151054111, b/152067055) + private void processAlbumArt(MediaMetadata metadata, Icon largeIcon, ImageView albumView) { + Bitmap albumArt = null; + + // First look in URI fields + for (String field : ART_URIS) { + String uriString = metadata.getString(field); + if (uriString != null) { + albumArt = loadBitmapFromUri(Uri.parse(uriString)); + if (albumArt != null) { + Log.d(TAG, "loaded art from " + field); + break; + } + } + } + + // Then check bitmap field + if (albumArt == null) { + albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); + } + + // Finally try the notification's largeIcon + if (albumArt == null && largeIcon != null) { + albumArt = largeIcon.getBitmap(); + } + processAlbumArtInternal(albumArt, albumView); } - private void processAlbumArtInternal(Bitmap albumArt, ImageView albumView) { - float radius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius); + /** + * Load a bitmap from a URI + * @param uri + * @return bitmap, or null if couldn't be loaded + */ + private Bitmap loadBitmapFromUri(Uri uri) { + ImageDecoder.Source source = ImageDecoder.createSource(mContext.getContentResolver(), uri); + try { + return ImageDecoder.decodeBitmap(source); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Resize and crop the image if provided and update the control view + * @param albumArt Bitmap of art to display, or null to hide view + * @param albumView View that will hold the art + */ + private void processAlbumArtInternal(@Nullable Bitmap albumArt, ImageView albumView) { + // Resize RoundedBitmapDrawable roundedDrawable = null; if (albumArt != null) { + float radius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius); Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true); int albumSize = (int) mContext.getResources().getDimension( R.dimen.qs_media_album_size); - Bitmap scaled = Bitmap.createScaledBitmap(original, albumSize, albumSize, false); + Bitmap scaled = ThumbnailUtils.extractThumbnail(original, albumSize, albumSize); roundedDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), scaled); roundedDrawable.setCornerRadius(radius); } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java index 0f065661a470..9e574a1fa621 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.media.MediaDescription; import android.media.session.MediaController; import android.media.session.MediaSession; @@ -115,8 +116,8 @@ public class QSMediaPlayer extends MediaControlPanel { } // Set what we can normally - super.setMediaSession(token, icon, iconColor, bgColor, contentIntent, appName.toString(), - null); + super.setMediaSession(token, icon, null, iconColor, bgColor, contentIntent, + appName.toString(), null); // Then add info from MediaDescription ImageView albumView = mMediaNotifView.findViewById(R.id.album_art); @@ -149,6 +150,7 @@ public class QSMediaPlayer extends MediaControlPanel { * Update media panel view for the given media session * @param token token for this media session * @param icon app notification icon + * @param largeIcon notification's largeIcon, used as a fallback for album art * @param iconColor foreground color (for text, icons) * @param bgColor background color * @param actionsContainer a LinearLayout containing the media action buttons @@ -156,11 +158,12 @@ public class QSMediaPlayer extends MediaControlPanel { * @param appName Application title * @param key original notification's key */ - public void setMediaSession(MediaSession.Token token, Drawable icon, int iconColor, - int bgColor, View actionsContainer, PendingIntent contentIntent, String appName, - String key) { + public void setMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon, + int iconColor, int bgColor, View actionsContainer, PendingIntent contentIntent, + String appName, String key) { - super.setMediaSession(token, icon, iconColor, bgColor, contentIntent, appName, key); + super.setMediaSession(token, icon, largeIcon, iconColor, bgColor, contentIntent, appName, + key); // Media controls if (actionsContainer != null) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 1eb577852a71..1252008755a7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -32,6 +32,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.media.MediaDescription; import android.media.session.MediaSession; import android.metrics.LogMaker; @@ -225,14 +226,16 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne * Add or update a player for the associated media session * @param token * @param icon + * @param largeIcon * @param iconColor * @param bgColor * @param actionsContainer * @param notif * @param key */ - public void addMediaSession(MediaSession.Token token, Drawable icon, int iconColor, int bgColor, - View actionsContainer, StatusBarNotification notif, String key) { + public void addMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon, + int iconColor, int bgColor, View actionsContainer, StatusBarNotification notif, + String key) { if (!useQsMediaPlayer(mContext)) { // Shouldn't happen, but just in case Log.e(TAG, "Tried to add media session without player!"); @@ -296,7 +299,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne Log.d(TAG, "setting player session"); String appName = Notification.Builder.recoverBuilder(getContext(), notif.getNotification()) .loadHeaderAppName(); - player.setMediaSession(token, icon, iconColor, bgColor, actionsContainer, + player.setMediaSession(token, icon, largeIcon, iconColor, bgColor, actionsContainer, notif.getNotification().contentIntent, appName, key); if (mMediaPlayers.size() > 0) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java index 7ba7c5fe499e..89b36da0c834 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java @@ -19,6 +19,7 @@ package com.android.systemui.qs; import android.app.PendingIntent; import android.content.Context; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.media.session.MediaController; import android.media.session.MediaSession; import android.view.View; @@ -58,6 +59,7 @@ public class QuickQSMediaPlayer extends MediaControlPanel { * Update media panel view for the given media session * @param token token for this media session * @param icon app notification icon + * @param largeIcon notification's largeIcon, used as a fallback for album art * @param iconColor foreground color (for text, icons) * @param bgColor background color * @param actionsContainer a LinearLayout containing the media action buttons @@ -66,8 +68,9 @@ public class QuickQSMediaPlayer extends MediaControlPanel { * @param contentIntent Intent to send when user taps on the view * @param key original notification's key */ - public void setMediaSession(MediaSession.Token token, Drawable icon, int iconColor, int bgColor, - View actionsContainer, int[] actionsToShow, PendingIntent contentIntent, String key) { + public void setMediaSession(MediaSession.Token token, Drawable icon, Icon largeIcon, + int iconColor, int bgColor, View actionsContainer, int[] actionsToShow, + PendingIntent contentIntent, String key) { // Only update if this is a different session and currently playing String oldPackage = ""; if (getController() != null) { @@ -82,7 +85,7 @@ public class QuickQSMediaPlayer extends MediaControlPanel { return; } - super.setMediaSession(token, icon, iconColor, bgColor, contentIntent, null, key); + super.setMediaSession(token, icon, largeIcon, iconColor, bgColor, contentIntent, null, key); LinearLayout parentActionsLayout = (LinearLayout) actionsContainer; int i = 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 796f22cbb3cb..b96cff830f31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -191,6 +191,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi Drawable iconDrawable = notif.getSmallIcon().loadDrawable(mContext); panel.getMediaPlayer().setMediaSession(token, iconDrawable, + notif.getLargeIcon(), tintColor, mBackgroundColor, mActions, @@ -201,6 +202,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi com.android.systemui.R.id.quick_settings_panel); bigPanel.addMediaSession(token, iconDrawable, + notif.getLargeIcon(), tintColor, mBackgroundColor, mActions, |