1 /*
2  * Copyright 2020 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 androidx.core.app;
18 
19 import android.app.Notification;
20 import android.app.NotificationChannel;
21 import android.app.NotificationChannelGroup;
22 import android.content.Intent;
23 import android.media.AudioAttributes;
24 import android.net.Uri;
25 import android.os.Build;
26 import android.provider.Settings;
27 
28 import androidx.annotation.RequiresApi;
29 import androidx.core.content.pm.ShortcutInfoCompat;
30 import androidx.core.util.Preconditions;
31 
32 import org.jspecify.annotations.NonNull;
33 import org.jspecify.annotations.Nullable;
34 
35 /**
36  * A representation of settings that apply to a collection of similarly themed notifications.
37  *
38  * Setters return {@code this} to allow chaining.
39  *
40  * This class doesn't do anything on older SDKs which don't support Notification Channels.
41  */
42 public class NotificationChannelCompat {
43     /**
44      * The id of the default channel for an app. This id is reserved by the system. All
45      * notifications posted from apps targeting {@link android.os.Build.VERSION_CODES#N_MR1} or
46      * earlier without a notification channel specified are posted to this channel.
47      */
48     public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
49 
50     private static final boolean DEFAULT_SHOW_BADGE = true;
51     private static final int DEFAULT_LIGHT_COLOR = 0;
52 
53     // These fields are settable through the builder
54     final @NonNull String mId;
55     CharSequence mName;
56     int mImportance;
57     String mDescription;
58     String mGroupId;
59     boolean mShowBadge = DEFAULT_SHOW_BADGE;
60     Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
61     AudioAttributes mAudioAttributes;
62     boolean mLights;
63     int mLightColor = DEFAULT_LIGHT_COLOR;
64     boolean mVibrationEnabled;
65     long[] mVibrationPattern;
66     String mParentId;
67     String mConversationId;
68 
69     // These fields are read-only
70     private boolean mBypassDnd;
71     private int mLockscreenVisibility;
72     private boolean mCanBubble;
73     private boolean mImportantConversation;
74 
75     /**
76      * Builder class for {@link NotificationChannelCompat} objects.
77      */
78     public static class Builder {
79         private final NotificationChannelCompat mChannel;
80 
81         /**
82          * Creates a notification channel builder.
83          *
84          * @param id         The id of the channel. Must be unique per package. The value may be
85          *                   truncated if it is too long.
86          * @param importance The importance of the channel. This controls how interruptive
87          *                   notifications posted to this channel are.
88          */
Builder(@onNull String id, int importance)89         public Builder(@NonNull String id, int importance) {
90             mChannel = new NotificationChannelCompat(id, importance);
91         }
92 
93         /**
94          * Sets the user visible name of this channel.
95          *
96          * You can rename this channel when the system locale changes by listening for the
97          * {@link Intent#ACTION_LOCALE_CHANGED} broadcast.
98          *
99          * <p>The recommended maximum length is 40 characters; the value may be truncated if it
100          * is too long.
101          */
setName(@ullable CharSequence name)102         public @NonNull Builder setName(@Nullable CharSequence name) {
103             mChannel.mName = name;
104             return this;
105         }
106 
107         /**
108          * Sets the level of interruption of this notification channel.
109          *
110          * Only modifiable before the channel is submitted to
111          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
112          *
113          * @param importance the amount the user should be interrupted by notifications from this
114          *                   channel.
115          */
setImportance(int importance)116         public @NonNull Builder setImportance(int importance) {
117             mChannel.mImportance = importance;
118             return this;
119         }
120 
121         /**
122          * Sets the user visible description of this channel.
123          *
124          * <p>The recommended maximum length is 300 characters; the value may be truncated if it is
125          * too long.
126          */
setDescription(@ullable String description)127         public @NonNull Builder setDescription(@Nullable String description) {
128             mChannel.mDescription = description;
129             return this;
130         }
131 
132         /**
133          * Sets what group this channel belongs to.
134          *
135          * Group information is only used for presentation, not for behavior.
136          *
137          * Only modifiable before the channel is submitted to
138          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)},
139          * unless the channel is not currently part of a group.
140          *
141          * @param groupId the id of a group created by
142          *                {@link NotificationManagerCompat#createNotificationChannelGroup}.
143          */
setGroup(@ullable String groupId)144         public @NonNull Builder setGroup(@Nullable String groupId) {
145             mChannel.mGroupId = groupId;
146             return this;
147         }
148 
149         /**
150          * Sets whether notifications posted to this channel can appear as application icon badges
151          * in a Launcher.
152          *
153          * Only modifiable before the channel is submitted to
154          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
155          *
156          * @param showBadge true if badges should be allowed to be shown.
157          */
setShowBadge(boolean showBadge)158         public @NonNull Builder setShowBadge(boolean showBadge) {
159             mChannel.mShowBadge = showBadge;
160             return this;
161         }
162 
163         /**
164          * Sets the sound that should be played for notifications posted to this channel and its
165          * audio attributes. Notification channels with an {@link #setImportance(int)}
166          * importance} of
167          * at least {@link NotificationManagerCompat#IMPORTANCE_DEFAULT} should have a sound.
168          *
169          * Only modifiable before the channel is submitted to
170          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
171          */
setSound(@ullable Uri sound, @Nullable AudioAttributes audioAttributes)172         public @NonNull Builder setSound(@Nullable Uri sound,
173                 @Nullable AudioAttributes audioAttributes) {
174             mChannel.mSound = sound;
175             mChannel.mAudioAttributes = audioAttributes;
176             return this;
177         }
178 
179         /**
180          * Sets whether notifications posted to this channel should display notification lights,
181          * on devices that support that feature.
182          *
183          * Only modifiable before the channel is submitted to
184          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
185          */
setLightsEnabled(boolean lights)186         public @NonNull Builder setLightsEnabled(boolean lights) {
187             mChannel.mLights = lights;
188             return this;
189         }
190 
191         /**
192          * Sets the notification light color for notifications posted to this channel, if lights are
193          * {@link #setLightsEnabled(boolean) enabled} on this channel and the device supports that
194          * feature.
195          *
196          * Only modifiable before the channel is submitted to
197          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
198          */
setLightColor(int argb)199         public @NonNull Builder setLightColor(int argb) {
200             mChannel.mLightColor = argb;
201             return this;
202         }
203 
204         /**
205          * Sets whether notification posted to this channel should vibrate. The vibration pattern
206          * can be set with {@link #setVibrationPattern(long[])}.
207          *
208          * Only modifiable before the channel is submitted to
209          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
210          */
setVibrationEnabled(boolean vibration)211         public @NonNull Builder setVibrationEnabled(boolean vibration) {
212             mChannel.mVibrationEnabled = vibration;
213             return this;
214         }
215 
216         /**
217          * Sets the vibration pattern for notifications posted to this channel. If the provided
218          * pattern is valid (non-null, non-empty), will {@link #setVibrationEnabled(boolean)} enable
219          * vibration} as well. Otherwise, vibration will be disabled.
220          *
221          * Only modifiable before the channel is submitted to
222          * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}.
223          */
setVibrationPattern(long @Nullable [] vibrationPattern)224         public @NonNull Builder setVibrationPattern(long @Nullable [] vibrationPattern) {
225             mChannel.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
226             mChannel.mVibrationPattern = vibrationPattern;
227             return this;
228         }
229 
230         /**
231          * Sets this channel as being conversation-centric. Different settings and functionality may
232          * be exposed for conversation-centric channels.
233          *
234          * Calling this on SDKs that do not support conversations will have no effect on the
235          * built channel.  As a result, this channel will not be linked to the channel with the
236          * parentChannelId.  That means that this channel must be published to directly to be used;
237          * it cannot be published to by publishing to the parentChannelId with the shortcutId.
238          *
239          * @param parentChannelId The {@link #getId()} id} of the generic channel that notifications
240          *                        of this type would be posted to in absence of a specific
241          *                        conversation id. For example, if this channel represents
242          *                        'Messages from Person A', the parent channel would be 'Messages.'
243          * @param conversationId  The {@link ShortcutInfoCompat#getId()} of the shortcut
244          *                        representing this channel's conversation.
245          */
setConversationId(@onNull String parentChannelId, @NonNull String conversationId)246         public @NonNull Builder setConversationId(@NonNull String parentChannelId,
247                 @NonNull String conversationId) {
248             if (Build.VERSION.SDK_INT >= 30) {
249                 mChannel.mParentId = parentChannelId;
250                 mChannel.mConversationId = conversationId;
251             }
252             return this;
253         }
254 
255         /**
256          * Creates a {@link NotificationChannelCompat} instance.
257          */
build()258         public @NonNull NotificationChannelCompat build() {
259             return mChannel;
260         }
261     }
262 
NotificationChannelCompat(@onNull String id, int importance)263     NotificationChannelCompat(@NonNull String id, int importance) {
264         mId = Preconditions.checkNotNull(id);
265         mImportance = importance;
266         if (Build.VERSION.SDK_INT >= 21) {
267             mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
268         }
269     }
270 
271     @RequiresApi(26)
NotificationChannelCompat(@onNull NotificationChannel channel)272     NotificationChannelCompat(@NonNull NotificationChannel channel) {
273         this(Api26Impl.getId(channel), Api26Impl.getImportance(channel));
274         // Populate all builder-editable fields
275         mName = Api26Impl.getName(channel);
276         mDescription = Api26Impl.getDescription(channel);
277         mGroupId = Api26Impl.getGroup(channel);
278         mShowBadge = Api26Impl.canShowBadge(channel);
279         mSound = Api26Impl.getSound(channel);
280         mAudioAttributes = Api26Impl.getAudioAttributes(channel);
281         mLights = Api26Impl.shouldShowLights(channel);
282         mLightColor = Api26Impl.getLightColor(channel);
283         mVibrationEnabled = Api26Impl.shouldVibrate(channel);
284         mVibrationPattern = Api26Impl.getVibrationPattern(channel);
285         if (Build.VERSION.SDK_INT >= 30) {
286             mParentId = Api30Impl.getParentChannelId(channel);
287             mConversationId = Api30Impl.getConversationId(channel);
288         }
289         // Populate all read-only fields
290         mBypassDnd = Api26Impl.canBypassDnd(channel);
291         mLockscreenVisibility = Api26Impl.getLockscreenVisibility(channel);
292         if (Build.VERSION.SDK_INT >= 29) {
293             mCanBubble = Api29Impl.canBubble(channel);
294         }
295         if (Build.VERSION.SDK_INT >= 30) {
296             mImportantConversation = Api30Impl.isImportantConversation(channel);
297         }
298     }
299 
300     /**
301      * Gets the platform notification channel object.
302      *
303      * Returns {@code null} on older SDKs which don't support Notification Channels.
304      */
getNotificationChannel()305     NotificationChannel getNotificationChannel() {
306         if (Build.VERSION.SDK_INT < 26) {
307             return null;
308         }
309         NotificationChannel channel = Api26Impl.createNotificationChannel(mId, mName, mImportance);
310         Api26Impl.setDescription(channel, mDescription);
311         Api26Impl.setGroup(channel, mGroupId);
312         Api26Impl.setShowBadge(channel, mShowBadge);
313         Api26Impl.setSound(channel, mSound, mAudioAttributes);
314         Api26Impl.enableLights(channel, mLights);
315         Api26Impl.setLightColor(channel, mLightColor);
316         Api26Impl.setVibrationPattern(channel, mVibrationPattern);
317         Api26Impl.enableVibration(channel, mVibrationEnabled);
318         if (Build.VERSION.SDK_INT >= 30 && mParentId != null && mConversationId != null) {
319             Api30Impl.setConversationId(channel, mParentId, mConversationId);
320         }
321         return channel;
322     }
323 
324     /**
325      * Creates a {@link Builder} instance with all the writeable property values of this instance.
326      */
toBuilder()327     public @NonNull Builder toBuilder() {
328         return new Builder(mId, mImportance)
329                 .setName(mName)
330                 .setDescription(mDescription)
331                 .setGroup(mGroupId)
332                 .setShowBadge(mShowBadge)
333                 .setSound(mSound, mAudioAttributes)
334                 .setLightsEnabled(mLights)
335                 .setLightColor(mLightColor)
336                 .setVibrationEnabled(mVibrationEnabled)
337                 .setVibrationPattern(mVibrationPattern)
338                 .setConversationId(mParentId, mConversationId);
339     }
340 
341     /**
342      * Returns the id of this channel.
343      */
getId()344     public @NonNull String getId() {
345         return mId;
346     }
347 
348     /**
349      * Returns the user visible name of this channel.
350      */
getName()351     public @Nullable CharSequence getName() {
352         return mName;
353     }
354 
355     /**
356      * Returns the user visible description of this channel.
357      */
getDescription()358     public @Nullable String getDescription() {
359         return mDescription;
360     }
361 
362     /**
363      * Returns the user specified importance e.g. {@link NotificationManagerCompat#IMPORTANCE_LOW}
364      * for notifications posted to this channel. Note: This value might be >
365      * {@link NotificationManagerCompat#IMPORTANCE_NONE}, but notifications posted to this channel
366      * will not be shown to the user if the parent {@link NotificationChannelGroup} or app is
367      * blocked.
368      * See {@link NotificationChannelGroup#isBlocked()} and
369      * {@link NotificationManagerCompat#areNotificationsEnabled()}.
370      */
getImportance()371     public int getImportance() {
372         return mImportance;
373     }
374 
375     /**
376      * Returns the notification sound for this channel.
377      */
getSound()378     public @Nullable Uri getSound() {
379         return mSound;
380     }
381 
382     /**
383      * Returns the audio attributes for sound played by notifications posted to this channel.
384      */
getAudioAttributes()385     public @Nullable AudioAttributes getAudioAttributes() {
386         return mAudioAttributes;
387     }
388 
389     /**
390      * Returns whether notifications posted to this channel trigger notification lights.
391      */
shouldShowLights()392     public boolean shouldShowLights() {
393         return mLights;
394     }
395 
396     /**
397      * Returns the notification light color for notifications posted to this channel. Irrelevant
398      * unless {@link #shouldShowLights()}.
399      */
getLightColor()400     public int getLightColor() {
401         return mLightColor;
402     }
403 
404     /**
405      * Returns whether notifications posted to this channel always vibrate.
406      */
shouldVibrate()407     public boolean shouldVibrate() {
408         return mVibrationEnabled;
409     }
410 
411     /**
412      * Returns the vibration pattern for notifications posted to this channel. Will be ignored if
413      * vibration is not enabled ({@link #shouldVibrate()}.
414      */
getVibrationPattern()415     public long @Nullable [] getVibrationPattern() {
416         return mVibrationPattern;
417     }
418 
419     /**
420      * Returns whether notifications posted to this channel can appear as badges in a Launcher
421      * application.
422      *
423      * Note that badging may be disabled for other reasons.
424      */
canShowBadge()425     public boolean canShowBadge() {
426         return mShowBadge;
427     }
428 
429     /**
430      * Returns what group this channel belongs to.
431      *
432      * This is used only for visually grouping channels in the UI.
433      */
getGroup()434     public @Nullable String getGroup() {
435         return mGroupId;
436     }
437 
438     /**
439      * Returns the {@link #getId() id} of the parent notification channel to this channel, if it's
440      * a conversation related channel.
441      * See {@link Builder#setConversationId(String, String)}.
442      */
getParentChannelId()443     public @Nullable String getParentChannelId() {
444         return mParentId;
445     }
446 
447     /**
448      * Returns the {@link ShortcutInfoCompat#getId() id} of the conversation backing this channel,
449      * if it's associated with a conversation.
450      * See {@link Builder#setConversationId(String, String)}.
451      */
getConversationId()452     public @Nullable String getConversationId() {
453         return mConversationId;
454     }
455 
456     /**
457      * Whether or not notifications posted to this channel can bypass the Do Not Disturb
458      * {@link android.app.NotificationManager#INTERRUPTION_FILTER_PRIORITY} mode.
459      *
460      * <p>This is a read-only property which is only valid on instances fetched from the
461      * {@link NotificationManagerCompat}.
462      */
canBypassDnd()463     public boolean canBypassDnd() {
464         return mBypassDnd;
465     }
466 
467     /**
468      * Returns whether or not notifications posted to this channel are shown on the lockscreen
469      * in full or redacted form.
470      *
471      * <p>This is a read-only property which is only valid on instances fetched from the
472      * {@link NotificationManagerCompat}.
473      */
474     @NotificationCompat.NotificationVisibility
getLockscreenVisibility()475     public int getLockscreenVisibility() {
476         return mLockscreenVisibility;
477     }
478 
479     /**
480      * Returns whether notifications posted to this channel are allowed to display outside of the
481      * notification shade, in a floating window on top of other apps.
482      *
483      * <p>This is a read-only property which is only valid on instances fetched from the
484      * {@link NotificationManagerCompat}.
485      */
canBubble()486     public boolean canBubble() {
487         return mCanBubble;
488     }
489 
490     /**
491      * Whether or not notifications in this conversation are considered important.
492      *
493      * <p>Important conversations may get special visual treatment, and might be able to bypass DND.
494      *
495      * <p>This is only valid for channels that represent conversations, that is, those with a valid
496      * {@link #getConversationId() conversation id}.
497      *
498      * <p>This is a read-only property which is only valid on instances fetched from the
499      * {@link NotificationManagerCompat}.
500      */
isImportantConversation()501     public boolean isImportantConversation() {
502         return mImportantConversation;
503     }
504 
505     /**
506      * A class for wrapping calls to {@link NotificationChannel} methods which
507      * were added in API 26; these calls must be wrapped to avoid performance issues.
508      * See the UnsafeNewApiCall lint rule for more details.
509      */
510     @RequiresApi(26)
511     static class Api26Impl {
Api26Impl()512         private Api26Impl() { }
513 
createNotificationChannel(String id, CharSequence name, int importance)514         static NotificationChannel createNotificationChannel(String id, CharSequence name,
515                 int importance) {
516             return new NotificationChannel(id, name, importance);
517         }
518 
getId(NotificationChannel notificationChannel)519         static String getId(NotificationChannel notificationChannel) {
520             return notificationChannel.getId();
521         }
522 
getImportance(NotificationChannel notificationChannel)523         static int getImportance(NotificationChannel notificationChannel) {
524             return notificationChannel.getImportance();
525         }
526 
getName(NotificationChannel notificationChannel)527         static CharSequence getName(NotificationChannel notificationChannel) {
528             return notificationChannel.getName();
529         }
530 
getDescription(NotificationChannel notificationChannel)531         static String getDescription(NotificationChannel notificationChannel) {
532             return notificationChannel.getDescription();
533         }
534 
setDescription(NotificationChannel notificationChannel, String description)535         static void setDescription(NotificationChannel notificationChannel, String description) {
536             notificationChannel.setDescription(description);
537         }
538 
getGroup(NotificationChannel notificationChannel)539         static String getGroup(NotificationChannel notificationChannel) {
540             return notificationChannel.getGroup();
541         }
542 
setGroup(NotificationChannel notificationChannel, String groupId)543         static void setGroup(NotificationChannel notificationChannel, String groupId) {
544             notificationChannel.setGroup(groupId);
545         }
546 
canShowBadge(NotificationChannel notificationChannel)547         static boolean canShowBadge(NotificationChannel notificationChannel) {
548             return notificationChannel.canShowBadge();
549         }
550 
setShowBadge(NotificationChannel notificationChannel, boolean showBadge)551         static void setShowBadge(NotificationChannel notificationChannel, boolean showBadge) {
552             notificationChannel.setShowBadge(showBadge);
553         }
554 
getSound(NotificationChannel notificationChannel)555         static Uri getSound(NotificationChannel notificationChannel) {
556             return notificationChannel.getSound();
557         }
558 
setSound(NotificationChannel notificationChannel, Uri sound, AudioAttributes audioAttributes)559         static void setSound(NotificationChannel notificationChannel, Uri sound,
560                 AudioAttributes audioAttributes) {
561             notificationChannel.setSound(sound, audioAttributes);
562         }
563 
getAudioAttributes(NotificationChannel notificationChannel)564         static AudioAttributes getAudioAttributes(NotificationChannel notificationChannel) {
565             return notificationChannel.getAudioAttributes();
566         }
567 
shouldShowLights(NotificationChannel notificationChannel)568         static boolean shouldShowLights(NotificationChannel notificationChannel) {
569             return notificationChannel.shouldShowLights();
570         }
571 
enableLights(NotificationChannel notificationChannel, boolean lights)572         static void enableLights(NotificationChannel notificationChannel, boolean lights) {
573             notificationChannel.enableLights(lights);
574         }
575 
getLightColor(NotificationChannel notificationChannel)576         static int getLightColor(NotificationChannel notificationChannel) {
577             return notificationChannel.getLightColor();
578         }
579 
setLightColor(NotificationChannel notificationChannel, int argb)580         static void setLightColor(NotificationChannel notificationChannel, int argb) {
581             notificationChannel.setLightColor(argb);
582         }
583 
shouldVibrate(NotificationChannel notificationChannel)584         static boolean shouldVibrate(NotificationChannel notificationChannel) {
585             return notificationChannel.shouldVibrate();
586         }
587 
enableVibration(NotificationChannel notificationChannel, boolean vibration)588         static void enableVibration(NotificationChannel notificationChannel, boolean vibration) {
589             notificationChannel.enableVibration(vibration);
590         }
591 
getVibrationPattern(NotificationChannel notificationChannel)592         static long[] getVibrationPattern(NotificationChannel notificationChannel) {
593             return notificationChannel.getVibrationPattern();
594         }
595 
setVibrationPattern(NotificationChannel notificationChannel, long[] vibrationPattern)596         static void setVibrationPattern(NotificationChannel notificationChannel,
597                 long[] vibrationPattern) {
598             notificationChannel.setVibrationPattern(vibrationPattern);
599         }
600 
canBypassDnd(NotificationChannel notificationChannel)601         static boolean canBypassDnd(NotificationChannel notificationChannel) {
602             return notificationChannel.canBypassDnd();
603         }
604 
getLockscreenVisibility(NotificationChannel notificationChannel)605         static int getLockscreenVisibility(NotificationChannel notificationChannel) {
606             return notificationChannel.getLockscreenVisibility();
607         }
608 
609     }
610 
611     /**
612      * A class for wrapping calls to {@link NotificationChannel} methods which
613      * were added in API 29; these calls must be wrapped to avoid performance issues.
614      * See the UnsafeNewApiCall lint rule for more details.
615      */
616     @RequiresApi(29)
617     static class Api29Impl {
Api29Impl()618         private Api29Impl() { }
619 
canBubble(NotificationChannel notificationChannel)620         static boolean canBubble(NotificationChannel notificationChannel) {
621             return notificationChannel.canBubble();
622         }
623     }
624 
625     /**
626      * A class for wrapping calls to {@link NotificationChannel} methods which
627      * were added in API 30; these calls must be wrapped to avoid performance issues.
628      * See the UnsafeNewApiCall lint rule for more details.
629      */
630     @RequiresApi(30)
631     static class Api30Impl {
Api30Impl()632         private Api30Impl() { }
633 
getParentChannelId(NotificationChannel notificationChannel)634         static String getParentChannelId(NotificationChannel notificationChannel) {
635             return notificationChannel.getParentChannelId();
636         }
637 
getConversationId(NotificationChannel notificationChannel)638         static String getConversationId(NotificationChannel notificationChannel) {
639             return notificationChannel.getConversationId();
640         }
641 
setConversationId(NotificationChannel notificationChannel, String parentChannelId, String conversationId)642         static void setConversationId(NotificationChannel notificationChannel,
643                 String parentChannelId, String conversationId) {
644             notificationChannel.setConversationId(parentChannelId, conversationId);
645         }
646 
isImportantConversation(NotificationChannel notificationChannel)647         static boolean isImportantConversation(NotificationChannel notificationChannel) {
648             return notificationChannel.isImportantConversation();
649         }
650     }
651 }
652