Loading packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,9 @@ <!-- shortcut manager --> <uses-permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING" /> <!-- launcher apps --> <uses-permission android:name="android.permission.ACCESS_SHORTCUTS" /> <uses-permission android:name="android.permission.MODIFY_THEME_OVERLAY" /> <!-- accessibility --> Loading packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +29 −1 Original line number Diff line number Diff line Loading @@ -27,9 +27,13 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; Loading Loading @@ -57,6 +61,7 @@ class Bubble { private final String mGroupId; private String mAppName; private Drawable mUserBadgedAppIcon; private ShortcutInfo mShortcutInfo; private boolean mInflated; private BubbleView mIconView; Loading Loading @@ -94,6 +99,14 @@ class Bubble { mLastUpdated = e.getSbn().getPostTime(); mGroupId = groupId(e); String shortcutId = e.getSbn().getNotification().getShortcutId(); if (BubbleExperimentConfig.useShortcutInfoToBubble(context) && shortcutId != null) { mShortcutInfo = BubbleExperimentConfig.getShortcutInfo(context, e.getSbn().getPackageName(), e.getSbn().getUser(), shortcutId); } PackageManager pm = context.getPackageManager(); ApplicationInfo info; try { Loading Loading @@ -137,6 +150,21 @@ class Bubble { return mUserBadgedAppIcon; } @Nullable public ShortcutInfo getShortcutInfo() { return mShortcutInfo; } /** * Whether shortcut information should be used to populate the bubble. * <p> * To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}. * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}. */ public boolean usingShortcutInfo() { return BubbleExperimentConfig.isShortcutIntent(getBubbleIntent()); } boolean isInflated() { return mInflated; } Loading Loading @@ -331,7 +359,7 @@ class Bubble { } @Nullable PendingIntent getBubbleIntent(Context context) { PendingIntent getBubbleIntent() { Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); if (data != null) { return data.getIntent(); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +11 −6 Original line number Diff line number Diff line Loading @@ -130,12 +130,17 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList Log.d(TAG, "onActivityViewReady: calling startActivity, " + "bubble=" + getBubbleKey()); } try { if (mBubble.usingShortcutInfo()) { mActivityView.startShortcutActivity(mBubble.getShortcutInfo(), options, null /* sourceBounds */); } else { Intent fillInIntent = new Intent(); // Apply flags to make behaviour match documentLaunchMode=always. fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); try { mActivityView.startActivity(mBubbleIntent, fillInIntent, options); } } catch (RuntimeException e) { // If there's a runtime exception here then there's something // wrong with the intent, we can't really recover / try to populate Loading Loading @@ -415,7 +420,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList + getBubbleKey()); } mBubbleIntent = mBubble.getBubbleIntent(mContext); mBubbleIntent = mBubble.getBubbleIntent(); if (mBubbleIntent != null) { setContentVisibility(false); mActivityView.setVisibility(VISIBLE); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +123 −19 Original line number Diff line number Diff line Loading @@ -16,32 +16,52 @@ package com.android.systemui.bubbles; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; import static com.android.systemui.bubbles.BubbleController.canLaunchIntentInActivityView; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.graphics.drawable.Icon; import android.os.UserHandle; import android.provider.Settings; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.Arrays; import java.util.List; /** * Common class for experiments controlled via secure settings. */ public class BubbleExperimentConfig { private static final String SHORTCUT_DUMMY_INTENT = "bubble_experiment_shortcut_intent"; private static PendingIntent sDummyShortcutIntent; private static final int BUBBLE_HEIGHT = 10000; private static final String ALLOW_ANY_NOTIF_TO_BUBBLE = "allow_any_notif_to_bubble"; private static final boolean ALLOW_ANY_NOTIF_TO_BUBBLE_DEFAULT = false; private static final String ALLOW_MESSAGE_NOTIFS_TO_BUBBLE = "allow_message_notifs_to_bubble"; private static final boolean ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT = false; private static final String ALLOW_SHORTCUTS_TO_BUBBLE = "allow_shortcuts_to_bubble"; private static final boolean ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT = false; /** * When true, if a notification has the information necessary to bubble (i.e. valid * contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata} * object will be created by the system and added to the notification. * * This does not produce a bubble, only adds the metadata. It should be used in conjunction * with {@see #allowNotifBubbleMenu} which shows an affordance to bubble notification content. * <p> * This does not produce a bubble, only adds the metadata based on the notification info. */ static boolean allowAnyNotifToBubble(Context context) { return Settings.Secure.getInt(context.getContentResolver(), Loading @@ -59,6 +79,19 @@ public class BubbleExperimentConfig { ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; } /** * When true, if the notification is able to bubble via {@link #allowAnyNotifToBubble(Context)} * or {@link #allowMessageNotifsToBubble(Context)} or via normal BubbleMetadata, then a new * BubbleMetadata object is constructed based on the shortcut info. * <p> * This does not produce a bubble, only adds the metadata based on shortcut info. */ static boolean useShortcutInfoToBubble(Context context) { return Settings.Secure.getInt(context.getContentResolver(), ALLOW_SHORTCUTS_TO_BUBBLE, ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; } /** * If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds * {@link android.app.Notification.BubbleMetadata} to the notification entry as long as Loading @@ -66,10 +99,9 @@ public class BubbleExperimentConfig { */ static void adjustForExperiments(Context context, NotificationEntry entry, Bubble previousBubble) { if (entry.getBubbleMetadata() != null) { // Has metadata, nothing to do. return; } Notification.BubbleMetadata metadata = null; boolean addedMetadata = false; Notification notification = entry.getSbn().getNotification(); boolean isMessage = Notification.MessagingStyle.class.equals( Loading @@ -77,22 +109,94 @@ public class BubbleExperimentConfig { boolean bubbleNotifForExperiment = (isMessage && allowMessageNotifsToBubble(context)) || allowAnyNotifToBubble(context); boolean useShortcutInfo = useShortcutInfoToBubble(context); String shortcutId = entry.getSbn().getNotification().getShortcutId(); if (useShortcutInfo && shortcutId != null) { // We don't actually get anything useful from ShortcutInfo so just check existence ShortcutInfo info = getShortcutInfo(context, entry.getSbn().getPackageName(), entry.getSbn().getUser(), shortcutId); if (info != null) { metadata = createForShortcut(context, entry); } // Replace existing metadata with shortcut, or we're bubbling for experiment boolean shouldBubble = entry.getBubbleMetadata() != null || bubbleNotifForExperiment; if (shouldBubble && metadata != null) { entry.setBubbleMetadata(metadata); addedMetadata = true; } } // Didn't get metadata from a shortcut & we're bubbling for experiment if (entry.getBubbleMetadata() == null && bubbleNotifForExperiment) { metadata = createFromNotif(context, entry); if (metadata != null) { entry.setBubbleMetadata(metadata); addedMetadata = true; } } if (previousBubble != null && addedMetadata) { // Update to a previously bubble, set its flag now so the update goes // to the bubble. entry.setFlagBubble(true); } } static Notification.BubbleMetadata createFromNotif(Context context, NotificationEntry entry) { Notification notification = entry.getSbn().getNotification(); final PendingIntent intent = notification.contentIntent; if (bubbleNotifForExperiment && BubbleController.canLaunchIntentInActivityView(context, entry, intent)) { final Icon smallIcon = entry.getSbn().getNotification().getSmallIcon(); Notification.BubbleMetadata.Builder metadata = new Notification.BubbleMetadata.Builder() .setDesiredHeight(10000) if (canLaunchIntentInActivityView(context, entry, intent)) { return new Notification.BubbleMetadata.Builder() .setDesiredHeight(BUBBLE_HEIGHT) .setIcon(smallIcon) .setIntent(intent); entry.setBubbleMetadata(metadata.build()); .setIntent(intent) .build(); } return null; } if (previousBubble != null) { // Update to a previously user-created bubble, set its flag now so the update goes // to the bubble. entry.setFlagBubble(true); static Notification.BubbleMetadata createForShortcut(Context context, NotificationEntry entry) { // ShortcutInfo does not return an icon, instead a Drawable, lets just use // notification icon for BubbleMetadata. Icon icon = entry.getSbn().getNotification().getSmallIcon(); // ShortcutInfo does not return the intent, lets make a fake but identifiable // intent so we can still add bubbleMetadata if (sDummyShortcutIntent == null) { Intent i = new Intent(SHORTCUT_DUMMY_INTENT); sDummyShortcutIntent = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); } return new Notification.BubbleMetadata.Builder() .setDesiredHeight(BUBBLE_HEIGHT) .setIcon(icon) .setIntent(sDummyShortcutIntent) .build(); } static ShortcutInfo getShortcutInfo(Context context, String packageName, UserHandle user, String shortcutId) { LauncherApps launcherAppService = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery(); if (packageName != null) { query.setPackage(packageName); } if (shortcutId != null) { query.setShortcutIds(Arrays.asList(shortcutId)); } query.setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST); List<ShortcutInfo> shortcuts = launcherAppService.getShortcuts(query, user); return shortcuts != null && shortcuts.size() > 0 ? shortcuts.get(0) : null; } static boolean isShortcutIntent(PendingIntent intent) { return intent.equals(sDummyShortcutIntent); } } packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +11 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.bubbles; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.content.pm.LauncherApps; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -243,10 +244,17 @@ public class BubbleView extends FrameLayout { } Drawable getBubbleDrawable(Context context) { if (mBubble.getShortcutInfo() != null && mBubble.usingShortcutInfo()) { LauncherApps launcherApps = (LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE); int density = getContext().getResources().getConfiguration().densityDpi; return launcherApps.getShortcutIconDrawable(mBubble.getShortcutInfo(), density); } else { Notification.BubbleMetadata metadata = getEntry().getBubbleMetadata(); Icon ic = metadata.getIcon(); return ic.loadDrawable(context); } } BitmapInfo getBadgedBitmap() { Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap( Loading Loading
packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,9 @@ <!-- shortcut manager --> <uses-permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING" /> <!-- launcher apps --> <uses-permission android:name="android.permission.ACCESS_SHORTCUTS" /> <uses-permission android:name="android.permission.MODIFY_THEME_OVERLAY" /> <!-- accessibility --> Loading
packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +29 −1 Original line number Diff line number Diff line Loading @@ -27,9 +27,13 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; Loading Loading @@ -57,6 +61,7 @@ class Bubble { private final String mGroupId; private String mAppName; private Drawable mUserBadgedAppIcon; private ShortcutInfo mShortcutInfo; private boolean mInflated; private BubbleView mIconView; Loading Loading @@ -94,6 +99,14 @@ class Bubble { mLastUpdated = e.getSbn().getPostTime(); mGroupId = groupId(e); String shortcutId = e.getSbn().getNotification().getShortcutId(); if (BubbleExperimentConfig.useShortcutInfoToBubble(context) && shortcutId != null) { mShortcutInfo = BubbleExperimentConfig.getShortcutInfo(context, e.getSbn().getPackageName(), e.getSbn().getUser(), shortcutId); } PackageManager pm = context.getPackageManager(); ApplicationInfo info; try { Loading Loading @@ -137,6 +150,21 @@ class Bubble { return mUserBadgedAppIcon; } @Nullable public ShortcutInfo getShortcutInfo() { return mShortcutInfo; } /** * Whether shortcut information should be used to populate the bubble. * <p> * To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}. * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}. */ public boolean usingShortcutInfo() { return BubbleExperimentConfig.isShortcutIntent(getBubbleIntent()); } boolean isInflated() { return mInflated; } Loading Loading @@ -331,7 +359,7 @@ class Bubble { } @Nullable PendingIntent getBubbleIntent(Context context) { PendingIntent getBubbleIntent() { Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); if (data != null) { return data.getIntent(); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +11 −6 Original line number Diff line number Diff line Loading @@ -130,12 +130,17 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList Log.d(TAG, "onActivityViewReady: calling startActivity, " + "bubble=" + getBubbleKey()); } try { if (mBubble.usingShortcutInfo()) { mActivityView.startShortcutActivity(mBubble.getShortcutInfo(), options, null /* sourceBounds */); } else { Intent fillInIntent = new Intent(); // Apply flags to make behaviour match documentLaunchMode=always. fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); try { mActivityView.startActivity(mBubbleIntent, fillInIntent, options); } } catch (RuntimeException e) { // If there's a runtime exception here then there's something // wrong with the intent, we can't really recover / try to populate Loading Loading @@ -415,7 +420,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList + getBubbleKey()); } mBubbleIntent = mBubble.getBubbleIntent(mContext); mBubbleIntent = mBubble.getBubbleIntent(); if (mBubbleIntent != null) { setContentVisibility(false); mActivityView.setVisibility(VISIBLE); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +123 −19 Original line number Diff line number Diff line Loading @@ -16,32 +16,52 @@ package com.android.systemui.bubbles; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; import static com.android.systemui.bubbles.BubbleController.canLaunchIntentInActivityView; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; import android.graphics.drawable.Icon; import android.os.UserHandle; import android.provider.Settings; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.Arrays; import java.util.List; /** * Common class for experiments controlled via secure settings. */ public class BubbleExperimentConfig { private static final String SHORTCUT_DUMMY_INTENT = "bubble_experiment_shortcut_intent"; private static PendingIntent sDummyShortcutIntent; private static final int BUBBLE_HEIGHT = 10000; private static final String ALLOW_ANY_NOTIF_TO_BUBBLE = "allow_any_notif_to_bubble"; private static final boolean ALLOW_ANY_NOTIF_TO_BUBBLE_DEFAULT = false; private static final String ALLOW_MESSAGE_NOTIFS_TO_BUBBLE = "allow_message_notifs_to_bubble"; private static final boolean ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT = false; private static final String ALLOW_SHORTCUTS_TO_BUBBLE = "allow_shortcuts_to_bubble"; private static final boolean ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT = false; /** * When true, if a notification has the information necessary to bubble (i.e. valid * contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata} * object will be created by the system and added to the notification. * * This does not produce a bubble, only adds the metadata. It should be used in conjunction * with {@see #allowNotifBubbleMenu} which shows an affordance to bubble notification content. * <p> * This does not produce a bubble, only adds the metadata based on the notification info. */ static boolean allowAnyNotifToBubble(Context context) { return Settings.Secure.getInt(context.getContentResolver(), Loading @@ -59,6 +79,19 @@ public class BubbleExperimentConfig { ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; } /** * When true, if the notification is able to bubble via {@link #allowAnyNotifToBubble(Context)} * or {@link #allowMessageNotifsToBubble(Context)} or via normal BubbleMetadata, then a new * BubbleMetadata object is constructed based on the shortcut info. * <p> * This does not produce a bubble, only adds the metadata based on shortcut info. */ static boolean useShortcutInfoToBubble(Context context) { return Settings.Secure.getInt(context.getContentResolver(), ALLOW_SHORTCUTS_TO_BUBBLE, ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; } /** * If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds * {@link android.app.Notification.BubbleMetadata} to the notification entry as long as Loading @@ -66,10 +99,9 @@ public class BubbleExperimentConfig { */ static void adjustForExperiments(Context context, NotificationEntry entry, Bubble previousBubble) { if (entry.getBubbleMetadata() != null) { // Has metadata, nothing to do. return; } Notification.BubbleMetadata metadata = null; boolean addedMetadata = false; Notification notification = entry.getSbn().getNotification(); boolean isMessage = Notification.MessagingStyle.class.equals( Loading @@ -77,22 +109,94 @@ public class BubbleExperimentConfig { boolean bubbleNotifForExperiment = (isMessage && allowMessageNotifsToBubble(context)) || allowAnyNotifToBubble(context); boolean useShortcutInfo = useShortcutInfoToBubble(context); String shortcutId = entry.getSbn().getNotification().getShortcutId(); if (useShortcutInfo && shortcutId != null) { // We don't actually get anything useful from ShortcutInfo so just check existence ShortcutInfo info = getShortcutInfo(context, entry.getSbn().getPackageName(), entry.getSbn().getUser(), shortcutId); if (info != null) { metadata = createForShortcut(context, entry); } // Replace existing metadata with shortcut, or we're bubbling for experiment boolean shouldBubble = entry.getBubbleMetadata() != null || bubbleNotifForExperiment; if (shouldBubble && metadata != null) { entry.setBubbleMetadata(metadata); addedMetadata = true; } } // Didn't get metadata from a shortcut & we're bubbling for experiment if (entry.getBubbleMetadata() == null && bubbleNotifForExperiment) { metadata = createFromNotif(context, entry); if (metadata != null) { entry.setBubbleMetadata(metadata); addedMetadata = true; } } if (previousBubble != null && addedMetadata) { // Update to a previously bubble, set its flag now so the update goes // to the bubble. entry.setFlagBubble(true); } } static Notification.BubbleMetadata createFromNotif(Context context, NotificationEntry entry) { Notification notification = entry.getSbn().getNotification(); final PendingIntent intent = notification.contentIntent; if (bubbleNotifForExperiment && BubbleController.canLaunchIntentInActivityView(context, entry, intent)) { final Icon smallIcon = entry.getSbn().getNotification().getSmallIcon(); Notification.BubbleMetadata.Builder metadata = new Notification.BubbleMetadata.Builder() .setDesiredHeight(10000) if (canLaunchIntentInActivityView(context, entry, intent)) { return new Notification.BubbleMetadata.Builder() .setDesiredHeight(BUBBLE_HEIGHT) .setIcon(smallIcon) .setIntent(intent); entry.setBubbleMetadata(metadata.build()); .setIntent(intent) .build(); } return null; } if (previousBubble != null) { // Update to a previously user-created bubble, set its flag now so the update goes // to the bubble. entry.setFlagBubble(true); static Notification.BubbleMetadata createForShortcut(Context context, NotificationEntry entry) { // ShortcutInfo does not return an icon, instead a Drawable, lets just use // notification icon for BubbleMetadata. Icon icon = entry.getSbn().getNotification().getSmallIcon(); // ShortcutInfo does not return the intent, lets make a fake but identifiable // intent so we can still add bubbleMetadata if (sDummyShortcutIntent == null) { Intent i = new Intent(SHORTCUT_DUMMY_INTENT); sDummyShortcutIntent = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); } return new Notification.BubbleMetadata.Builder() .setDesiredHeight(BUBBLE_HEIGHT) .setIcon(icon) .setIntent(sDummyShortcutIntent) .build(); } static ShortcutInfo getShortcutInfo(Context context, String packageName, UserHandle user, String shortcutId) { LauncherApps launcherAppService = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery(); if (packageName != null) { query.setPackage(packageName); } if (shortcutId != null) { query.setShortcutIds(Arrays.asList(shortcutId)); } query.setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST); List<ShortcutInfo> shortcuts = launcherAppService.getShortcuts(query, user); return shortcuts != null && shortcuts.size() > 0 ? shortcuts.get(0) : null; } static boolean isShortcutIntent(PendingIntent intent) { return intent.equals(sDummyShortcutIntent); } }
packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +11 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.bubbles; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.content.pm.LauncherApps; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -243,10 +244,17 @@ public class BubbleView extends FrameLayout { } Drawable getBubbleDrawable(Context context) { if (mBubble.getShortcutInfo() != null && mBubble.usingShortcutInfo()) { LauncherApps launcherApps = (LauncherApps) getContext().getSystemService(Context.LAUNCHER_APPS_SERVICE); int density = getContext().getResources().getConfiguration().densityDpi; return launcherApps.getShortcutIconDrawable(mBubble.getShortcutInfo(), density); } else { Notification.BubbleMetadata metadata = getEntry().getBubbleMetadata(); Icon ic = metadata.getIcon(); return ic.loadDrawable(context); } } BitmapInfo getBadgedBitmap() { Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap( Loading