Loading core/java/android/app/Notification.java +87 −12 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.graphics.drawable.Icon.TYPE_URI; import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP; import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast; import static com.android.internal.widget.ConversationLayout.CONVERSATION_LAYOUT_ENABLED; import android.annotation.ColorInt; import android.annotation.DimenRes; Loading Loading @@ -1229,6 +1228,9 @@ public class Notification implements Parcelable */ public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle"; /** @hide */ public static final String EXTRA_CONVERSATION_ICON = "android.conversationIcon"; /** * {@link #extras} key: an array of {@link android.app.Notification.MessagingStyle.Message} * bundles provided by a Loading Loading @@ -3576,7 +3578,6 @@ public class Notification implements Parcelable } } } } } Loading Loading @@ -6118,9 +6119,11 @@ public class Notification implements Parcelable } private int getMessagingLayoutResource() { return CONVERSATION_LAYOUT_ENABLED ? R.layout.notification_template_material_conversation : R.layout.notification_template_material_messaging; return R.layout.notification_template_material_messaging; } private int getConversationLayoutResource() { return R.layout.notification_template_material_conversation; } private int getActionLayoutResource() { Loading Loading @@ -7078,11 +7081,28 @@ public class Notification implements Parcelable */ public static final int MAXIMUM_RETAINED_MESSAGES = 25; /** @hide */ public static final int CONVERSATION_TYPE_LEGACY = 0; /** @hide */ public static final int CONVERSATION_TYPE_NORMAL = 1; /** @hide */ public static final int CONVERSATION_TYPE_IMPORTANT = 2; /** @hide */ @IntDef(prefix = {"CONVERSATION_TYPE_"}, value = { CONVERSATION_TYPE_LEGACY, CONVERSATION_TYPE_NORMAL, CONVERSATION_TYPE_IMPORTANT }) @Retention(RetentionPolicy.SOURCE) public @interface ConversationType {} @NonNull Person mUser; @Nullable CharSequence mConversationTitle; @Nullable Icon mShortcutIcon; List<Message> mMessages = new ArrayList<>(); List<Message> mHistoricMessages = new ArrayList<>(); boolean mIsGroupConversation; @ConversationType int mConversationType = CONVERSATION_TYPE_LEGACY; MessagingStyle() { } Loading Loading @@ -7160,6 +7180,11 @@ public class Notification implements Parcelable /** * Sets the title to be displayed on this conversation. May be set to {@code null}. * * <p>Starting in {@link Build.VERSION_CODES#R, this conversation title will be ignored if a * valid shortcutId is added via {@link Notification.Builder#setShortcutId(String)}. In this * case, {@link ShortcutInfo#getShortLabel()} will be shown as the conversation title * instead. * * <p>This API's behavior was changed in SDK version {@link Build.VERSION_CODES#P}. If your * application's target version is less than {@link Build.VERSION_CODES#P}, setting a * conversation title to a non-null value will make {@link #isGroupConversation()} return Loading @@ -7183,6 +7208,46 @@ public class Notification implements Parcelable return mConversationTitle; } /** * Sets the icon to be displayed on the conversation, derived from the shortcutId. * * @hide */ public MessagingStyle setShortcutIcon(@Nullable Icon conversationIcon) { mShortcutIcon = conversationIcon; return this; } /** * Return the icon to be displayed on this conversation, derived from the shortcutId. May * return {@code null}. * * @hide */ @Nullable public Icon getShortcutIcon() { return mShortcutIcon; } /** * Sets the conversation type of this MessageStyle notification. * {@link #CONVERSATION_TYPE_LEGACY} will use the "older" layout from pre-R, * {@link #CONVERSATION_TYPE_NORMAL} will use the new "conversation" layout, and * {@link #CONVERSATION_TYPE_IMPORTANT} will add additional "important" treatments. * * @hide */ public MessagingStyle setConversationType(@ConversationType int conversationType) { mConversationType = conversationType; return this; } /** @hide */ @ConversationType public int getConversationType() { return mConversationType; } /** * Adds a message for display by this notification. Convenience call for a simple * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}. Loading Loading @@ -7334,6 +7399,9 @@ public class Notification implements Parcelable if (!mHistoricMessages.isEmpty()) { extras.putParcelableArray(EXTRA_HISTORIC_MESSAGES, Message.getBundleArrayForMessages(mHistoricMessages)); } if (mShortcutIcon != null) { extras.putParcelable(EXTRA_CONVERSATION_ICON, mShortcutIcon); } fixTitleAndTextExtras(extras); extras.putBoolean(EXTRA_IS_GROUP_CONVERSATION, mIsGroupConversation); Loading Loading @@ -7515,24 +7583,31 @@ public class Notification implements Parcelable } else { isOneToOne = !isGroupConversation(); } boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY; Icon largeIcon = isConversationLayout ? mShortcutIcon : mBuilder.mN.mLargeIcon; TemplateBindResult bindResult = new TemplateBindResult(); StandardTemplateParams p = mBuilder.mParams.reset().hasProgress(false).title( conversationTitle).text(null) StandardTemplateParams p = mBuilder.mParams.reset() .hasProgress(false) .title(conversationTitle) .text(null) .hideLargeIcon(hideRightIcons || isOneToOne) .hideReplyIcon(hideRightIcons) .headerTextSecondary(conversationTitle); RemoteViews contentView = mBuilder.applyStandardTemplateWithActions( mBuilder.getMessagingLayoutResource(), isConversationLayout ? mBuilder.getConversationLayoutResource() : mBuilder.getMessagingLayoutResource(), p, bindResult); addExtras(mBuilder.mN.extras); if (!CONVERSATION_LAYOUT_ENABLED) { if (!isConversationLayout) { // also update the end margin if there is an image contentView.setViewLayoutMarginEnd(R.id.notification_messaging, bindResult.getIconMarginEnd()); } contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor", mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p) mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p) : mBuilder.resolveContrastColor(p)); contentView.setInt(R.id.status_bar_latest_event_content, "setSenderTextColor", mBuilder.getPrimaryTextColor(p)); Loading @@ -7552,7 +7627,7 @@ public class Notification implements Parcelable contentView.setCharSequence(R.id.status_bar_latest_event_content, "setConversationTitle", conversationTitle); contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon", mBuilder.mN.mLargeIcon); largeIcon); contentView.setBundle(R.id.status_bar_latest_event_content, "setData", mBuilder.mN.extras); return contentView; Loading Loading @@ -7615,7 +7690,7 @@ public class Notification implements Parcelable public RemoteViews makeHeadsUpContentView(boolean increasedHeight) { RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */, true /* hideLargeIcon */); if (!CONVERSATION_LAYOUT_ENABLED) { if (mConversationType == CONVERSATION_TYPE_LEGACY) { remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1); } return remoteViews; Loading core/java/android/content/pm/LauncherApps.java +32 −0 Original line number Diff line number Diff line Loading @@ -1299,6 +1299,38 @@ public class LauncherApps { } } /** * @hide */ public Icon getShortcutIcon(@NonNull ShortcutInfo shortcut) { if (shortcut.hasIconFile()) { final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut); if (pfd == null) { return null; } try { final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor()); if (bmp != null) { if (shortcut.hasAdaptiveBitmap()) { return Icon.createWithAdaptiveBitmap(bmp); } else { return Icon.createWithBitmap(bmp); } } return null; } finally { try { pfd.close(); } catch (IOException ignore) { } } } else if (shortcut.hasIconResource()) { return Icon.createWithResource(shortcut.getPackage(), shortcut.getIconResourceId()); } else { return shortcut.getIcon(); } } private Drawable loadDrawableResourceFromPackage(String packageName, int resId, UserHandle user, int density) { try { Loading core/java/com/android/internal/widget/ConversationLayout.java +0 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,6 @@ import java.util.regex.Pattern; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { public static final boolean CONVERSATION_LAYOUT_ENABLED = true; private static final float COLOR_SHIFT_AMOUNT = 60; /** * Pattren for filter some ingonable characters. Loading packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +13 −7 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.hardware.SensorPrivacyManager; import android.media.AudioManager; Loading Loading @@ -139,6 +140,12 @@ public class SystemServicesModule { ServiceManager.checkService(DreamService.DREAM_SERVICE)); } @Provides @Singleton static IPackageManager provideIPackageManager() { return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); } @Singleton @Provides static IStatusBarService provideIStatusBarService() { Loading @@ -159,13 +166,6 @@ public class SystemServicesModule { return WindowManagerGlobal.getWindowManagerService(); } /** */ @Singleton @Provides public IPackageManager provideIPackageManager() { return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); } @Singleton @Provides static KeyguardManager provideKeyguardManager(Context context) { Loading Loading @@ -230,6 +230,12 @@ public class SystemServicesModule { return context.getSystemService(SensorPrivacyManager.class); } @Singleton @Provides static ShortcutManager provideShortcutManager(Context context) { return context.getSystemService(ShortcutManager.class); } @Provides @Singleton @Nullable Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessor.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.systemui.statusbar.notification import android.app.Notification import android.content.pm.LauncherApps import com.android.systemui.statusbar.notification.collection.NotificationEntry import javax.inject.Inject class ConversationNotificationProcessor @Inject constructor( private val launcherApps: LauncherApps ) { fun processNotification(entry: NotificationEntry, recoveredBuilder: Notification.Builder) { val messagingStyle = recoveredBuilder.style as? Notification.MessagingStyle ?: return messagingStyle.conversationType = if (entry.ranking.channel.isImportantConversation) Notification.MessagingStyle.CONVERSATION_TYPE_IMPORTANT else Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL entry.ranking.shortcutInfo?.let { shortcutInfo -> messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo) shortcutInfo.shortLabel?.let { shortLabel -> messagingStyle.conversationTitle = shortLabel } } } } No newline at end of file Loading
core/java/android/app/Notification.java +87 −12 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.graphics.drawable.Icon.TYPE_URI; import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP; import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast; import static com.android.internal.widget.ConversationLayout.CONVERSATION_LAYOUT_ENABLED; import android.annotation.ColorInt; import android.annotation.DimenRes; Loading Loading @@ -1229,6 +1228,9 @@ public class Notification implements Parcelable */ public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle"; /** @hide */ public static final String EXTRA_CONVERSATION_ICON = "android.conversationIcon"; /** * {@link #extras} key: an array of {@link android.app.Notification.MessagingStyle.Message} * bundles provided by a Loading Loading @@ -3576,7 +3578,6 @@ public class Notification implements Parcelable } } } } } Loading Loading @@ -6118,9 +6119,11 @@ public class Notification implements Parcelable } private int getMessagingLayoutResource() { return CONVERSATION_LAYOUT_ENABLED ? R.layout.notification_template_material_conversation : R.layout.notification_template_material_messaging; return R.layout.notification_template_material_messaging; } private int getConversationLayoutResource() { return R.layout.notification_template_material_conversation; } private int getActionLayoutResource() { Loading Loading @@ -7078,11 +7081,28 @@ public class Notification implements Parcelable */ public static final int MAXIMUM_RETAINED_MESSAGES = 25; /** @hide */ public static final int CONVERSATION_TYPE_LEGACY = 0; /** @hide */ public static final int CONVERSATION_TYPE_NORMAL = 1; /** @hide */ public static final int CONVERSATION_TYPE_IMPORTANT = 2; /** @hide */ @IntDef(prefix = {"CONVERSATION_TYPE_"}, value = { CONVERSATION_TYPE_LEGACY, CONVERSATION_TYPE_NORMAL, CONVERSATION_TYPE_IMPORTANT }) @Retention(RetentionPolicy.SOURCE) public @interface ConversationType {} @NonNull Person mUser; @Nullable CharSequence mConversationTitle; @Nullable Icon mShortcutIcon; List<Message> mMessages = new ArrayList<>(); List<Message> mHistoricMessages = new ArrayList<>(); boolean mIsGroupConversation; @ConversationType int mConversationType = CONVERSATION_TYPE_LEGACY; MessagingStyle() { } Loading Loading @@ -7160,6 +7180,11 @@ public class Notification implements Parcelable /** * Sets the title to be displayed on this conversation. May be set to {@code null}. * * <p>Starting in {@link Build.VERSION_CODES#R, this conversation title will be ignored if a * valid shortcutId is added via {@link Notification.Builder#setShortcutId(String)}. In this * case, {@link ShortcutInfo#getShortLabel()} will be shown as the conversation title * instead. * * <p>This API's behavior was changed in SDK version {@link Build.VERSION_CODES#P}. If your * application's target version is less than {@link Build.VERSION_CODES#P}, setting a * conversation title to a non-null value will make {@link #isGroupConversation()} return Loading @@ -7183,6 +7208,46 @@ public class Notification implements Parcelable return mConversationTitle; } /** * Sets the icon to be displayed on the conversation, derived from the shortcutId. * * @hide */ public MessagingStyle setShortcutIcon(@Nullable Icon conversationIcon) { mShortcutIcon = conversationIcon; return this; } /** * Return the icon to be displayed on this conversation, derived from the shortcutId. May * return {@code null}. * * @hide */ @Nullable public Icon getShortcutIcon() { return mShortcutIcon; } /** * Sets the conversation type of this MessageStyle notification. * {@link #CONVERSATION_TYPE_LEGACY} will use the "older" layout from pre-R, * {@link #CONVERSATION_TYPE_NORMAL} will use the new "conversation" layout, and * {@link #CONVERSATION_TYPE_IMPORTANT} will add additional "important" treatments. * * @hide */ public MessagingStyle setConversationType(@ConversationType int conversationType) { mConversationType = conversationType; return this; } /** @hide */ @ConversationType public int getConversationType() { return mConversationType; } /** * Adds a message for display by this notification. Convenience call for a simple * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}. Loading Loading @@ -7334,6 +7399,9 @@ public class Notification implements Parcelable if (!mHistoricMessages.isEmpty()) { extras.putParcelableArray(EXTRA_HISTORIC_MESSAGES, Message.getBundleArrayForMessages(mHistoricMessages)); } if (mShortcutIcon != null) { extras.putParcelable(EXTRA_CONVERSATION_ICON, mShortcutIcon); } fixTitleAndTextExtras(extras); extras.putBoolean(EXTRA_IS_GROUP_CONVERSATION, mIsGroupConversation); Loading Loading @@ -7515,24 +7583,31 @@ public class Notification implements Parcelable } else { isOneToOne = !isGroupConversation(); } boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY; Icon largeIcon = isConversationLayout ? mShortcutIcon : mBuilder.mN.mLargeIcon; TemplateBindResult bindResult = new TemplateBindResult(); StandardTemplateParams p = mBuilder.mParams.reset().hasProgress(false).title( conversationTitle).text(null) StandardTemplateParams p = mBuilder.mParams.reset() .hasProgress(false) .title(conversationTitle) .text(null) .hideLargeIcon(hideRightIcons || isOneToOne) .hideReplyIcon(hideRightIcons) .headerTextSecondary(conversationTitle); RemoteViews contentView = mBuilder.applyStandardTemplateWithActions( mBuilder.getMessagingLayoutResource(), isConversationLayout ? mBuilder.getConversationLayoutResource() : mBuilder.getMessagingLayoutResource(), p, bindResult); addExtras(mBuilder.mN.extras); if (!CONVERSATION_LAYOUT_ENABLED) { if (!isConversationLayout) { // also update the end margin if there is an image contentView.setViewLayoutMarginEnd(R.id.notification_messaging, bindResult.getIconMarginEnd()); } contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor", mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p) mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p) : mBuilder.resolveContrastColor(p)); contentView.setInt(R.id.status_bar_latest_event_content, "setSenderTextColor", mBuilder.getPrimaryTextColor(p)); Loading @@ -7552,7 +7627,7 @@ public class Notification implements Parcelable contentView.setCharSequence(R.id.status_bar_latest_event_content, "setConversationTitle", conversationTitle); contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon", mBuilder.mN.mLargeIcon); largeIcon); contentView.setBundle(R.id.status_bar_latest_event_content, "setData", mBuilder.mN.extras); return contentView; Loading Loading @@ -7615,7 +7690,7 @@ public class Notification implements Parcelable public RemoteViews makeHeadsUpContentView(boolean increasedHeight) { RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */, true /* hideLargeIcon */); if (!CONVERSATION_LAYOUT_ENABLED) { if (mConversationType == CONVERSATION_TYPE_LEGACY) { remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1); } return remoteViews; Loading
core/java/android/content/pm/LauncherApps.java +32 −0 Original line number Diff line number Diff line Loading @@ -1299,6 +1299,38 @@ public class LauncherApps { } } /** * @hide */ public Icon getShortcutIcon(@NonNull ShortcutInfo shortcut) { if (shortcut.hasIconFile()) { final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut); if (pfd == null) { return null; } try { final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor()); if (bmp != null) { if (shortcut.hasAdaptiveBitmap()) { return Icon.createWithAdaptiveBitmap(bmp); } else { return Icon.createWithBitmap(bmp); } } return null; } finally { try { pfd.close(); } catch (IOException ignore) { } } } else if (shortcut.hasIconResource()) { return Icon.createWithResource(shortcut.getPackage(), shortcut.getIconResourceId()); } else { return shortcut.getIcon(); } } private Drawable loadDrawableResourceFromPackage(String packageName, int resId, UserHandle user, int density) { try { Loading
core/java/com/android/internal/widget/ConversationLayout.java +0 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,6 @@ import java.util.regex.Pattern; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { public static final boolean CONVERSATION_LAYOUT_ENABLED = true; private static final float COLOR_SHIFT_AMOUNT = 60; /** * Pattren for filter some ingonable characters. Loading
packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +13 −7 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.hardware.SensorPrivacyManager; import android.media.AudioManager; Loading Loading @@ -139,6 +140,12 @@ public class SystemServicesModule { ServiceManager.checkService(DreamService.DREAM_SERVICE)); } @Provides @Singleton static IPackageManager provideIPackageManager() { return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); } @Singleton @Provides static IStatusBarService provideIStatusBarService() { Loading @@ -159,13 +166,6 @@ public class SystemServicesModule { return WindowManagerGlobal.getWindowManagerService(); } /** */ @Singleton @Provides public IPackageManager provideIPackageManager() { return IPackageManager.Stub.asInterface(ServiceManager.getService("package")); } @Singleton @Provides static KeyguardManager provideKeyguardManager(Context context) { Loading Loading @@ -230,6 +230,12 @@ public class SystemServicesModule { return context.getSystemService(SensorPrivacyManager.class); } @Singleton @Provides static ShortcutManager provideShortcutManager(Context context) { return context.getSystemService(ShortcutManager.class); } @Provides @Singleton @Nullable Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotificationProcessor.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.systemui.statusbar.notification import android.app.Notification import android.content.pm.LauncherApps import com.android.systemui.statusbar.notification.collection.NotificationEntry import javax.inject.Inject class ConversationNotificationProcessor @Inject constructor( private val launcherApps: LauncherApps ) { fun processNotification(entry: NotificationEntry, recoveredBuilder: Notification.Builder) { val messagingStyle = recoveredBuilder.style as? Notification.MessagingStyle ?: return messagingStyle.conversationType = if (entry.ranking.channel.isImportantConversation) Notification.MessagingStyle.CONVERSATION_TYPE_IMPORTANT else Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL entry.ranking.shortcutInfo?.let { shortcutInfo -> messagingStyle.shortcutIcon = launcherApps.getShortcutIcon(shortcutInfo) shortcutInfo.shortLabel?.let { shortLabel -> messagingStyle.conversationTitle = shortLabel } } } } No newline at end of file