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.statusbar.notification.collection; 18 19 import android.annotation.Nullable; 20 import android.app.Notification; 21 import android.app.NotificationChannel; 22 import android.app.NotificationManager; 23 import android.content.Context; 24 import android.content.pm.ShortcutInfo; 25 import android.os.UserHandle; 26 import android.service.notification.NotificationListenerService.Ranking; 27 import android.service.notification.SnoozeCriterion; 28 import android.service.notification.StatusBarNotification; 29 30 import com.android.internal.logging.InstanceId; 31 import com.android.systemui.statusbar.RankingBuilder; 32 import com.android.systemui.statusbar.SbnBuilder; 33 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection; 34 import com.android.systemui.util.time.FakeSystemClock; 35 36 import java.util.ArrayList; 37 38 import kotlin.Unit; 39 40 /** 41 * Combined builder for constructing a NotificationEntry and its associated StatusBarNotification 42 * and Ranking. Is largely a proxy for the SBN and Ranking builders, but does a little extra magic 43 * to make sure the keys match between the two, etc. 44 * 45 * Has the ability to set ListEntry properties as well. 46 * 47 * Only for use in tests. 48 */ 49 public class NotificationEntryBuilder { 50 private final SbnBuilder mSbnBuilder; 51 private final RankingBuilder mRankingBuilder; 52 private final FakeSystemClock mClock = new FakeSystemClock(); 53 private StatusBarNotification mSbn = null; 54 55 /* ListEntry properties */ 56 private GroupEntry mParent; 57 private NotifSection mNotifSection; 58 59 /* If set, use this creation time instead of mClock.uptimeMillis */ 60 private long mCreationTime = -1; 61 private int mStableIndex = -1; 62 NotificationEntryBuilder()63 public NotificationEntryBuilder() { 64 mSbnBuilder = new SbnBuilder(); 65 mRankingBuilder = new RankingBuilder(); 66 } 67 NotificationEntryBuilder(NotificationEntry source)68 public NotificationEntryBuilder(NotificationEntry source) { 69 mSbnBuilder = new SbnBuilder(source.getSbn()); 70 mRankingBuilder = new RankingBuilder(source.getRanking()); 71 72 mParent = source.getParent(); 73 mCreationTime = source.getCreationTime(); 74 } 75 76 /** Update an the parent on an existing entry */ setNewParent(NotificationEntry entry, GroupEntry parent)77 public static void setNewParent(NotificationEntry entry, GroupEntry parent) { 78 entry.setParent(parent); 79 } 80 81 /** Build a new instance of NotificationEntry */ build()82 public NotificationEntry build() { 83 return buildOrApply(null); 84 } 85 86 /** Modifies [target] to match the contents of this builder */ apply(NotificationEntry target)87 public void apply(NotificationEntry target) { 88 buildOrApply(target); 89 } 90 91 /** Convenience method for Kotlin callbacks that are passed a builder and need to return Unit */ done()92 public Unit done() { 93 return Unit.INSTANCE; 94 } 95 buildOrApply(NotificationEntry target)96 private NotificationEntry buildOrApply(NotificationEntry target) { 97 final StatusBarNotification sbn = mSbn != null ? mSbn : mSbnBuilder.build(); 98 final Ranking ranking = mRankingBuilder.setKey(sbn.getKey()).build(); 99 final long creationTime = mCreationTime != -1 ? mCreationTime : mClock.uptimeMillis(); 100 101 final NotificationEntry entry; 102 if (target == null) { 103 entry = new NotificationEntry(sbn, ranking, creationTime); 104 } else { 105 entry = target; 106 entry.setSbn(sbn); 107 entry.setRanking(ranking); 108 // Note: we can't modify the creation time as it's immutable 109 } 110 111 /* ListEntry properties */ 112 entry.setParent(mParent); 113 entry.getAttachState().setSection(mNotifSection); 114 entry.getAttachState().setStableIndex(mStableIndex); 115 return entry; 116 } 117 118 /** 119 * Sets the parent. 120 */ setParent(@ullable GroupEntry parent)121 public NotificationEntryBuilder setParent(@Nullable GroupEntry parent) { 122 mParent = parent; 123 return this; 124 } 125 126 /** 127 * Sets the parent. 128 */ setSection(@ullable NotifSection section)129 public NotificationEntryBuilder setSection(@Nullable NotifSection section) { 130 mNotifSection = section; 131 return this; 132 } 133 134 /** 135 * Sets the SBN directly. If set, causes all calls to delegated SbnBuilder methods to be 136 * ignored. 137 */ setSbn(@ullable StatusBarNotification sbn)138 public NotificationEntryBuilder setSbn(@Nullable StatusBarNotification sbn) { 139 mSbn = sbn; 140 return this; 141 } 142 setStableIndex(int index)143 public NotificationEntryBuilder setStableIndex(int index) { 144 mStableIndex = index; 145 return this; 146 } 147 148 /** 149 * Set the creation time 150 */ setCreationTime(long creationTime)151 public NotificationEntryBuilder setCreationTime(long creationTime) { 152 mCreationTime = creationTime; 153 return this; 154 } 155 156 /* Delegated to SbnBuilder */ 157 setPkg(String pkg)158 public NotificationEntryBuilder setPkg(String pkg) { 159 mSbnBuilder.setPkg(pkg); 160 return this; 161 } 162 setOpPkg(String opPkg)163 public NotificationEntryBuilder setOpPkg(String opPkg) { 164 mSbnBuilder.setOpPkg(opPkg); 165 return this; 166 } 167 setId(int id)168 public NotificationEntryBuilder setId(int id) { 169 mSbnBuilder.setId(id); 170 return this; 171 } 172 setTag(String tag)173 public NotificationEntryBuilder setTag(String tag) { 174 mSbnBuilder.setTag(tag); 175 return this; 176 } 177 setUid(int uid)178 public NotificationEntryBuilder setUid(int uid) { 179 mSbnBuilder.setUid(uid); 180 return this; 181 } 182 setInitialPid(int initialPid)183 public NotificationEntryBuilder setInitialPid(int initialPid) { 184 mSbnBuilder.setInitialPid(initialPid); 185 return this; 186 } 187 setNotification(Notification notification)188 public NotificationEntryBuilder setNotification(Notification notification) { 189 mSbnBuilder.setNotification(notification); 190 return this; 191 } 192 modifyNotification(Context context)193 public Notification.Builder modifyNotification(Context context) { 194 return mSbnBuilder.modifyNotification(context); 195 } 196 setUser(UserHandle user)197 public NotificationEntryBuilder setUser(UserHandle user) { 198 mSbnBuilder.setUser(user); 199 return this; 200 } 201 setOverrideGroupKey(String overrideGroupKey)202 public NotificationEntryBuilder setOverrideGroupKey(String overrideGroupKey) { 203 mSbnBuilder.setOverrideGroupKey(overrideGroupKey); 204 return this; 205 } 206 setPostTime(long postTime)207 public NotificationEntryBuilder setPostTime(long postTime) { 208 mSbnBuilder.setPostTime(postTime); 209 return this; 210 } 211 setInstanceId(InstanceId instanceId)212 public NotificationEntryBuilder setInstanceId(InstanceId instanceId) { 213 mSbnBuilder.setInstanceId(instanceId); 214 return this; 215 } 216 217 /* Delegated to Notification.Builder (via SbnBuilder) */ 218 setContentTitle(Context context, String contentTitle)219 public NotificationEntryBuilder setContentTitle(Context context, String contentTitle) { 220 mSbnBuilder.setContentTitle(context, contentTitle); 221 return this; 222 } 223 setContentText(Context context, String contentText)224 public NotificationEntryBuilder setContentText(Context context, String contentText) { 225 mSbnBuilder.setContentText(context, contentText); 226 return this; 227 } 228 setGroup(Context context, String groupKey)229 public NotificationEntryBuilder setGroup(Context context, String groupKey) { 230 mSbnBuilder.setGroup(context, groupKey); 231 return this; 232 } 233 setGroupSummary(Context context, boolean isGroupSummary)234 public NotificationEntryBuilder setGroupSummary(Context context, boolean isGroupSummary) { 235 mSbnBuilder.setGroupSummary(context, isGroupSummary); 236 return this; 237 } 238 setFlag(Context context, int mask, boolean value)239 public NotificationEntryBuilder setFlag(Context context, int mask, boolean value) { 240 mSbnBuilder.setFlag(context, mask, value); 241 return this; 242 } 243 244 /* Delegated to RankingBuilder */ 245 setRank(int rank)246 public NotificationEntryBuilder setRank(int rank) { 247 mRankingBuilder.setRank(rank); 248 return this; 249 } 250 setMatchesInterruptionFilter( boolean matchesInterruptionFilter)251 public NotificationEntryBuilder setMatchesInterruptionFilter( 252 boolean matchesInterruptionFilter) { 253 mRankingBuilder.setMatchesInterruptionFilter(matchesInterruptionFilter); 254 return this; 255 } 256 setVisibilityOverride(int visibilityOverride)257 public NotificationEntryBuilder setVisibilityOverride(int visibilityOverride) { 258 mRankingBuilder.setVisibilityOverride(visibilityOverride); 259 return this; 260 } 261 setSuppressedVisualEffects(int suppressedVisualEffects)262 public NotificationEntryBuilder setSuppressedVisualEffects(int suppressedVisualEffects) { 263 mRankingBuilder.setSuppressedVisualEffects(suppressedVisualEffects); 264 return this; 265 } 266 setExplanation(CharSequence explanation)267 public NotificationEntryBuilder setExplanation(CharSequence explanation) { 268 mRankingBuilder.setExplanation(explanation); 269 return this; 270 } 271 setAdditionalPeople(ArrayList<String> additionalPeople)272 public NotificationEntryBuilder setAdditionalPeople(ArrayList<String> additionalPeople) { 273 mRankingBuilder.setAdditionalPeople(additionalPeople); 274 return this; 275 } 276 setSnoozeCriteria( ArrayList<SnoozeCriterion> snoozeCriteria)277 public NotificationEntryBuilder setSnoozeCriteria( 278 ArrayList<SnoozeCriterion> snoozeCriteria) { 279 mRankingBuilder.setSnoozeCriteria(snoozeCriteria); 280 return this; 281 } 282 setCanShowBadge(boolean canShowBadge)283 public NotificationEntryBuilder setCanShowBadge(boolean canShowBadge) { 284 mRankingBuilder.setCanShowBadge(canShowBadge); 285 return this; 286 } 287 setSuspended(boolean suspended)288 public NotificationEntryBuilder setSuspended(boolean suspended) { 289 mRankingBuilder.setSuspended(suspended); 290 return this; 291 } 292 setLastAudiblyAlertedMs(long lastAudiblyAlertedMs)293 public NotificationEntryBuilder setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) { 294 mRankingBuilder.setLastAudiblyAlertedMs(lastAudiblyAlertedMs); 295 return this; 296 } 297 setNoisy(boolean noisy)298 public NotificationEntryBuilder setNoisy(boolean noisy) { 299 mRankingBuilder.setNoisy(noisy); 300 return this; 301 } 302 setCanBubble(boolean canBubble)303 public NotificationEntryBuilder setCanBubble(boolean canBubble) { 304 mRankingBuilder.setCanBubble(canBubble); 305 return this; 306 } 307 setImportance(@otificationManager.Importance int importance)308 public NotificationEntryBuilder setImportance(@NotificationManager.Importance int importance) { 309 mRankingBuilder.setImportance(importance); 310 return this; 311 } 312 setUserSentiment(int userSentiment)313 public NotificationEntryBuilder setUserSentiment(int userSentiment) { 314 mRankingBuilder.setUserSentiment(userSentiment); 315 return this; 316 } 317 setChannel(NotificationChannel channel)318 public NotificationEntryBuilder setChannel(NotificationChannel channel) { 319 mRankingBuilder.setChannel(channel); 320 return this; 321 } 322 setSmartActions( ArrayList<Notification.Action> smartActions)323 public NotificationEntryBuilder setSmartActions( 324 ArrayList<Notification.Action> smartActions) { 325 mRankingBuilder.setSmartActions(smartActions); 326 return this; 327 } 328 setSmartActions(Notification.Action... smartActions)329 public NotificationEntryBuilder setSmartActions(Notification.Action... smartActions) { 330 mRankingBuilder.setSmartActions(smartActions); 331 return this; 332 } 333 setSmartReplies(ArrayList<CharSequence> smartReplies)334 public NotificationEntryBuilder setSmartReplies(ArrayList<CharSequence> smartReplies) { 335 mRankingBuilder.setSmartReplies(smartReplies); 336 return this; 337 } 338 setSmartReplies(CharSequence... smartReplies)339 public NotificationEntryBuilder setSmartReplies(CharSequence... smartReplies) { 340 mRankingBuilder.setSmartReplies(smartReplies); 341 return this; 342 } 343 setShortcutInfo(ShortcutInfo shortcutInfo)344 public NotificationEntryBuilder setShortcutInfo(ShortcutInfo shortcutInfo) { 345 mRankingBuilder.setShortcutInfo(shortcutInfo); 346 return this; 347 } 348 setRankingAdjustment(int rankingAdjustment)349 public NotificationEntryBuilder setRankingAdjustment(int rankingAdjustment) { 350 mRankingBuilder.setRankingAdjustment(rankingAdjustment); 351 return this; 352 } 353 } 354