Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.systemui.bubbles; |
| 18 | |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 19 | import static android.app.Notification.EXTRA_MESSAGES; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 20 | import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; |
| 21 | import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST; |
| 22 | import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED; |
| 23 | |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 24 | import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_EXPERIMENTS; |
| 25 | import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES; |
| 26 | import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 27 | |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 28 | import android.app.Notification; |
| 29 | import android.app.PendingIntent; |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 30 | import android.app.Person; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 31 | import android.content.Context; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 32 | import android.content.pm.LauncherApps; |
| 33 | import android.content.pm.ShortcutInfo; |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 34 | import android.graphics.Color; |
| 35 | import android.graphics.drawable.BitmapDrawable; |
| 36 | import android.graphics.drawable.Drawable; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 37 | import android.graphics.drawable.Icon; |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 38 | import android.os.Bundle; |
| 39 | import android.os.Parcelable; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 40 | import android.os.UserHandle; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 41 | import android.provider.Settings; |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 42 | import android.util.Log; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 43 | |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 44 | import com.android.internal.graphics.ColorUtils; |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 45 | import com.android.internal.util.ArrayUtils; |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 46 | import com.android.internal.util.ContrastColorUtil; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 47 | import com.android.systemui.statusbar.notification.collection.NotificationEntry; |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 48 | import com.android.systemui.statusbar.notification.people.PeopleHubNotificationListenerKt; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 49 | |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 50 | import java.util.ArrayList; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 51 | import java.util.Arrays; |
| 52 | import java.util.List; |
| 53 | |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 54 | /** |
| 55 | * Common class for experiments controlled via secure settings. |
| 56 | */ |
| 57 | public class BubbleExperimentConfig { |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 58 | private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 59 | |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 60 | private static final int BUBBLE_HEIGHT = 10000; |
| 61 | |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 62 | private static final String ALLOW_ANY_NOTIF_TO_BUBBLE = "allow_any_notif_to_bubble"; |
| 63 | private static final boolean ALLOW_ANY_NOTIF_TO_BUBBLE_DEFAULT = false; |
| 64 | |
| 65 | private static final String ALLOW_MESSAGE_NOTIFS_TO_BUBBLE = "allow_message_notifs_to_bubble"; |
Mady Mellor | dd6fe61 | 2020-04-15 11:47:55 -0700 | [diff] [blame] | 66 | private static final boolean ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT = false; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 67 | |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 68 | private static final String ALLOW_SHORTCUTS_TO_BUBBLE = "allow_shortcuts_to_bubble"; |
| 69 | private static final boolean ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT = false; |
| 70 | |
Mady Mellor | ea13b23 | 2019-12-05 15:55:46 -0800 | [diff] [blame] | 71 | private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; |
| 72 | |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 73 | /** |
| 74 | * When true, if a notification has the information necessary to bubble (i.e. valid |
| 75 | * contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata} |
| 76 | * object will be created by the system and added to the notification. |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 77 | * <p> |
| 78 | * This does not produce a bubble, only adds the metadata based on the notification info. |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 79 | */ |
| 80 | static boolean allowAnyNotifToBubble(Context context) { |
| 81 | return Settings.Secure.getInt(context.getContentResolver(), |
| 82 | ALLOW_ANY_NOTIF_TO_BUBBLE, |
| 83 | ALLOW_ANY_NOTIF_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Same as {@link #allowAnyNotifToBubble(Context)} except it filters for notifications that |
| 88 | * are using {@link Notification.MessagingStyle} and have remote input. |
| 89 | */ |
| 90 | static boolean allowMessageNotifsToBubble(Context context) { |
| 91 | return Settings.Secure.getInt(context.getContentResolver(), |
| 92 | ALLOW_MESSAGE_NOTIFS_TO_BUBBLE, |
| 93 | ALLOW_MESSAGE_NOTIFS_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; |
| 94 | } |
| 95 | |
| 96 | /** |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 97 | * When true, if the notification is able to bubble via {@link #allowAnyNotifToBubble(Context)} |
| 98 | * or {@link #allowMessageNotifsToBubble(Context)} or via normal BubbleMetadata, then a new |
| 99 | * BubbleMetadata object is constructed based on the shortcut info. |
| 100 | * <p> |
| 101 | * This does not produce a bubble, only adds the metadata based on shortcut info. |
| 102 | */ |
| 103 | static boolean useShortcutInfoToBubble(Context context) { |
| 104 | return Settings.Secure.getInt(context.getContentResolver(), |
| 105 | ALLOW_SHORTCUTS_TO_BUBBLE, |
| 106 | ALLOW_SHORTCUT_TO_BUBBLE_DEFAULT ? 1 : 0) != 0; |
| 107 | } |
| 108 | |
| 109 | /** |
Mady Mellor | ea13b23 | 2019-12-05 15:55:46 -0800 | [diff] [blame] | 110 | * Returns whether the provided package is whitelisted to bubble. |
| 111 | */ |
| 112 | static boolean isPackageWhitelistedToAutoBubble(Context context, String packageName) { |
| 113 | String unsplitList = Settings.Secure.getString(context.getContentResolver(), |
| 114 | WHITELISTED_AUTO_BUBBLE_APPS); |
| 115 | if (unsplitList != null) { |
| 116 | // We expect the list to be separated by commas and no white space (but we trim in case) |
| 117 | String[] packageList = unsplitList.split(","); |
| 118 | for (int i = 0; i < packageList.length; i++) { |
| 119 | if (packageList[i].trim().equals(packageName)) { |
| 120 | return true; |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | return false; |
| 125 | } |
| 126 | |
| 127 | /** |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 128 | * If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds |
| 129 | * {@link android.app.Notification.BubbleMetadata} to the notification entry as long as |
| 130 | * the notification has necessary info for BubbleMetadata. |
Mady Mellor | 3067294 | 2019-12-04 15:43:19 -0800 | [diff] [blame] | 131 | * |
| 132 | * @return whether an adjustment was made. |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 133 | */ |
Mady Mellor | 3067294 | 2019-12-04 15:43:19 -0800 | [diff] [blame] | 134 | static boolean adjustForExperiments(Context context, NotificationEntry entry, |
Mady Mellor | 3b86a4f | 2019-12-11 13:15:41 -0800 | [diff] [blame] | 135 | boolean previouslyUserCreated, boolean userBlocked) { |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 136 | Notification.BubbleMetadata metadata = null; |
| 137 | boolean addedMetadata = false; |
Mady Mellor | ea13b23 | 2019-12-05 15:55:46 -0800 | [diff] [blame] | 138 | boolean whiteListedToAutoBubble = |
| 139 | isPackageWhitelistedToAutoBubble(context, entry.getSbn().getPackageName()); |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 140 | |
| 141 | Notification notification = entry.getSbn().getNotification(); |
| 142 | boolean isMessage = Notification.MessagingStyle.class.equals( |
| 143 | notification.getNotificationStyle()); |
| 144 | boolean bubbleNotifForExperiment = (isMessage && allowMessageNotifsToBubble(context)) |
| 145 | || allowAnyNotifToBubble(context); |
| 146 | |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 147 | boolean useShortcutInfo = useShortcutInfoToBubble(context); |
| 148 | String shortcutId = entry.getSbn().getNotification().getShortcutId(); |
| 149 | |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 150 | boolean hasMetadata = entry.getBubbleMetadata() != null; |
| 151 | if ((!hasMetadata && (previouslyUserCreated || bubbleNotifForExperiment)) |
| 152 | || useShortcutInfo) { |
| 153 | if (DEBUG_EXPERIMENTS) { |
| 154 | Log.d(TAG, "Adjusting " + entry.getKey() + " for bubble experiment." |
| 155 | + " allowMessages=" + allowMessageNotifsToBubble(context) |
| 156 | + " isMessage=" + isMessage |
| 157 | + " allowNotifs=" + allowAnyNotifToBubble(context) |
| 158 | + " useShortcutInfo=" + useShortcutInfo |
| 159 | + " previouslyUserCreated=" + previouslyUserCreated); |
| 160 | } |
| 161 | } |
| 162 | |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 163 | if (useShortcutInfo && shortcutId != null) { |
| 164 | // We don't actually get anything useful from ShortcutInfo so just check existence |
| 165 | ShortcutInfo info = getShortcutInfo(context, entry.getSbn().getPackageName(), |
| 166 | entry.getSbn().getUser(), shortcutId); |
| 167 | if (info != null) { |
Mady Mellor | 2ac2d3a | 2020-01-08 17:18:54 -0800 | [diff] [blame] | 168 | metadata = createForShortcut(shortcutId); |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | // Replace existing metadata with shortcut, or we're bubbling for experiment |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 172 | boolean shouldBubble = entry.getBubbleMetadata() != null |
| 173 | || bubbleNotifForExperiment |
| 174 | || previouslyUserCreated; |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 175 | if (shouldBubble && metadata != null) { |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 176 | if (DEBUG_EXPERIMENTS) { |
| 177 | Log.d(TAG, "Adding experimental shortcut bubble for: " + entry.getKey()); |
| 178 | } |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 179 | entry.setBubbleMetadata(metadata); |
| 180 | addedMetadata = true; |
| 181 | } |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 182 | } |
| 183 | |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 184 | // Didn't get metadata from a shortcut & we're bubbling for experiment |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 185 | if (entry.getBubbleMetadata() == null |
| 186 | && (bubbleNotifForExperiment || previouslyUserCreated)) { |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 187 | metadata = createFromNotif(context, entry); |
| 188 | if (metadata != null) { |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 189 | if (DEBUG_EXPERIMENTS) { |
| 190 | Log.d(TAG, "Adding experimental notification bubble for: " + entry.getKey()); |
| 191 | } |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 192 | entry.setBubbleMetadata(metadata); |
| 193 | addedMetadata = true; |
| 194 | } |
| 195 | } |
| 196 | |
Mady Mellor | 3b86a4f | 2019-12-11 13:15:41 -0800 | [diff] [blame] | 197 | boolean bubbleForWhitelist = !userBlocked |
| 198 | && whiteListedToAutoBubble |
| 199 | && (addedMetadata || hasMetadata); |
Mady Mellor | ea13b23 | 2019-12-05 15:55:46 -0800 | [diff] [blame] | 200 | if ((previouslyUserCreated && addedMetadata) || bubbleForWhitelist) { |
| 201 | // Update to a previous bubble (or new autobubble), set its flag now. |
Mady Mellor | ff076eb | 2019-11-13 10:12:06 -0800 | [diff] [blame] | 202 | if (DEBUG_EXPERIMENTS) { |
| 203 | Log.d(TAG, "Setting FLAG_BUBBLE for: " + entry.getKey()); |
| 204 | } |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 205 | entry.setFlagBubble(true); |
Mady Mellor | 3067294 | 2019-12-04 15:43:19 -0800 | [diff] [blame] | 206 | return true; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 207 | } |
Mady Mellor | 3067294 | 2019-12-04 15:43:19 -0800 | [diff] [blame] | 208 | return addedMetadata; |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 209 | } |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 210 | |
| 211 | static Notification.BubbleMetadata createFromNotif(Context context, NotificationEntry entry) { |
| 212 | Notification notification = entry.getSbn().getNotification(); |
| 213 | final PendingIntent intent = notification.contentIntent; |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 214 | Icon icon = null; |
| 215 | // Use the icon of the person if available |
| 216 | List<Person> personList = getPeopleFromNotification(entry); |
| 217 | if (personList.size() > 0) { |
Joshua Tsuji | 22f90a0 | 2019-12-11 14:41:10 -0500 | [diff] [blame] | 218 | final Person person = personList.get(0); |
Joshua Tsuji | 22f90a0 | 2019-12-11 14:41:10 -0500 | [diff] [blame] | 219 | if (person != null) { |
| 220 | icon = person.getIcon(); |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 221 | if (icon == null) { |
| 222 | // Lets try and grab the icon constructed by the layout |
| 223 | Drawable d = PeopleHubNotificationListenerKt.extractAvatarFromRow(entry); |
| 224 | if (d instanceof BitmapDrawable) { |
| 225 | icon = Icon.createWithBitmap(((BitmapDrawable) d).getBitmap()); |
| 226 | } |
| 227 | } |
Joshua Tsuji | 22f90a0 | 2019-12-11 14:41:10 -0500 | [diff] [blame] | 228 | } |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 229 | } |
| 230 | if (icon == null) { |
Mady Mellor | 58dc519 | 2019-12-16 13:49:56 -0800 | [diff] [blame] | 231 | boolean shouldTint = notification.getLargeIcon() == null; |
| 232 | icon = shouldTint |
| 233 | ? notification.getSmallIcon() |
| 234 | : notification.getLargeIcon(); |
| 235 | if (shouldTint) { |
| 236 | int notifColor = entry.getSbn().getNotification().color; |
| 237 | notifColor = ColorUtils.setAlphaComponent(notifColor, 255); |
| 238 | notifColor = ContrastColorUtil.findContrastColor(notifColor, Color.WHITE, |
| 239 | true /* findFg */, 3f); |
| 240 | icon.setTint(notifColor); |
| 241 | } |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 242 | } |
Mady Mellor | 3067294 | 2019-12-04 15:43:19 -0800 | [diff] [blame] | 243 | if (intent != null) { |
Mady Mellor | aa9ce17 | 2020-03-17 10:34:20 -0700 | [diff] [blame] | 244 | return new Notification.BubbleMetadata.Builder(intent, icon) |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 245 | .setDesiredHeight(BUBBLE_HEIGHT) |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 246 | .build(); |
| 247 | } |
| 248 | return null; |
| 249 | } |
| 250 | |
Mady Mellor | 2ac2d3a | 2020-01-08 17:18:54 -0800 | [diff] [blame] | 251 | static Notification.BubbleMetadata createForShortcut(String shortcutId) { |
Mady Mellor | aa9ce17 | 2020-03-17 10:34:20 -0700 | [diff] [blame] | 252 | return new Notification.BubbleMetadata.Builder(shortcutId) |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 253 | .setDesiredHeight(BUBBLE_HEIGHT) |
Mady Mellor | b547e5e | 2019-12-02 10:15:56 -0800 | [diff] [blame] | 254 | .build(); |
| 255 | } |
| 256 | |
| 257 | static ShortcutInfo getShortcutInfo(Context context, String packageName, UserHandle user, |
| 258 | String shortcutId) { |
| 259 | LauncherApps launcherAppService = |
| 260 | (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE); |
| 261 | LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery(); |
| 262 | if (packageName != null) { |
| 263 | query.setPackage(packageName); |
| 264 | } |
| 265 | if (shortcutId != null) { |
| 266 | query.setShortcutIds(Arrays.asList(shortcutId)); |
| 267 | } |
| 268 | query.setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST); |
| 269 | List<ShortcutInfo> shortcuts = launcherAppService.getShortcuts(query, user); |
| 270 | return shortcuts != null && shortcuts.size() > 0 |
| 271 | ? shortcuts.get(0) |
| 272 | : null; |
| 273 | } |
| 274 | |
Mady Mellor | 89eb348 | 2019-11-13 17:32:01 -0800 | [diff] [blame] | 275 | static List<Person> getPeopleFromNotification(NotificationEntry entry) { |
| 276 | Bundle extras = entry.getSbn().getNotification().extras; |
| 277 | ArrayList<Person> personList = new ArrayList<>(); |
| 278 | if (extras == null) { |
| 279 | return personList; |
| 280 | } |
| 281 | |
| 282 | List<Person> p = extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST); |
| 283 | |
| 284 | if (p != null) { |
| 285 | personList.addAll(p); |
| 286 | } |
| 287 | |
| 288 | if (Notification.MessagingStyle.class.equals( |
| 289 | entry.getSbn().getNotification().getNotificationStyle())) { |
| 290 | final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); |
| 291 | if (!ArrayUtils.isEmpty(messages)) { |
| 292 | for (Notification.MessagingStyle.Message message : |
| 293 | Notification.MessagingStyle.Message |
| 294 | .getMessagesFromBundleArray(messages)) { |
| 295 | personList.add(message.getSenderPerson()); |
| 296 | } |
| 297 | } |
| 298 | } |
| 299 | return personList; |
| 300 | } |
Mady Mellor | 7f23490 | 2019-10-20 12:06:29 -0700 | [diff] [blame] | 301 | } |