Loading packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +77 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 { Loading packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +9 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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) { Loading packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +6 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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!"); Loading Loading @@ -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) { Loading packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java +6 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading @@ -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; Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +2 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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, Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +77 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 { Loading
packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +9 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 Loading @@ -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) { Loading
packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +6 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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!"); Loading Loading @@ -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) { Loading
packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java +6 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading @@ -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; Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +2 −0 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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, Loading