• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package android.service.notification;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.annotation.StringDef;
21 import android.annotation.SystemApi;
22 import android.app.Notification;
23 import android.os.Bundle;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.os.UserHandle;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 
31 /**
32  * Ranking updates from the Assistant.
33  *
34  * The updates are provides as a {@link Bundle} of signals, using the keys provided in this
35  * class.
36  * Each {@code KEY} specifies what type of data it supports and what kind of Adjustment it
37  * realizes on the notification rankings.
38  *
39  * Notifications affected by the Adjustment will be re-ranked if necessary.
40  *
41  * @hide
42  */
43 @SystemApi
44 public final class Adjustment implements Parcelable {
45     private final String mPackage;
46     private final String mKey;
47     private final CharSequence mExplanation;
48     private final Bundle mSignals;
49     private final int mUser;
50     @Nullable private String mIssuer;
51 
52     /** @hide */
53     @StringDef (prefix = { "KEY_" }, value = {
54             KEY_CONTEXTUAL_ACTIONS, KEY_GROUP_KEY, KEY_IMPORTANCE, KEY_PEOPLE, KEY_SNOOZE_CRITERIA,
55             KEY_TEXT_REPLIES, KEY_USER_SENTIMENT
56     })
57     @Retention(RetentionPolicy.SOURCE)
58     public @interface Keys {}
59 
60     /**
61      * Data type: ArrayList of {@code String}, where each is a representation of a
62      * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
63      * See {@link android.app.Notification.Builder#addPerson(String)}.
64      * @hide
65      */
66     @SystemApi
67     public static final String KEY_PEOPLE = "key_people";
68     /**
69      * Parcelable {@code ArrayList} of {@link SnoozeCriterion}. These criteria may be visible to
70      * users. If a user chooses to snooze a notification until one of these criterion, the
71      * assistant will be notified via
72      * {@link NotificationAssistantService#onNotificationSnoozedUntilContext}.
73      */
74     public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
75     /**
76      * Data type: String. Used to change what {@link Notification#getGroup() group} a notification
77      * belongs to.
78      * @hide
79      */
80     public static final String KEY_GROUP_KEY = "key_group_key";
81 
82     /**
83      * Data type: int, one of {@link NotificationListenerService.Ranking#USER_SENTIMENT_POSITIVE},
84      * {@link NotificationListenerService.Ranking#USER_SENTIMENT_NEUTRAL},
85      * {@link NotificationListenerService.Ranking#USER_SENTIMENT_NEGATIVE}. Used to express how
86      * a user feels about notifications in the same {@link android.app.NotificationChannel} as
87      * the notification represented by {@link #getKey()}.
88      */
89     public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
90 
91     /**
92      * Data type: ArrayList of {@link android.app.Notification.Action}.
93      * Used to suggest contextual actions for a notification.
94      *
95      * @see Notification.Action.Builder#setContextual(boolean)
96      */
97     public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
98 
99     /**
100      * Data type: ArrayList of {@link CharSequence}.
101      * Used to suggest smart replies for a notification.
102      */
103     public static final String KEY_TEXT_REPLIES = "key_text_replies";
104 
105     /**
106      * Data type: int, one of importance values e.g.
107      * {@link android.app.NotificationManager#IMPORTANCE_MIN}.
108      *
109      * <p> If used from
110      * {@link NotificationAssistantService#onNotificationEnqueued(StatusBarNotification)}, and
111      * received before the notification is posted, it can block a notification from appearing or
112      * silence it. Importance adjustments received too late from
113      * {@link NotificationAssistantService#onNotificationEnqueued(StatusBarNotification)} will be
114      * ignored.
115      * </p>
116      * <p>If used from
117      * {@link NotificationAssistantService#adjustNotification(Adjustment)}, it can
118      * visually demote or cancel a notification, but use this with care if they notification was
119      * recently posted because the notification may already have made noise.
120      * </p>
121      */
122     public static final String KEY_IMPORTANCE = "key_importance";
123 
124     /**
125      * Data type: float, a ranking score from 0 (lowest) to 1 (highest).
126      * Used to rank notifications inside that fall under the same classification (i.e. alerting,
127      * silenced).
128      */
129     public static final String KEY_RANKING_SCORE = "key_ranking_score";
130 
131     /**
132      * Data type: boolean, when true it suggests this is NOT a conversation notification.
133      * @hide
134      */
135     @SystemApi
136     public static final String KEY_NOT_CONVERSATION = "key_not_conversation";
137 
138     /**
139      * Create a notification adjustment.
140      *
141      * @param pkg The package of the notification.
142      * @param key The notification key.
143      * @param signals A bundle of signals that should inform notification display, ordering, and
144      *                interruptiveness.
145      * @param explanation A human-readable justification for the adjustment.
146      * @hide
147      */
148     @SystemApi
Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user)149     public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
150         mPackage = pkg;
151         mKey = key;
152         mSignals = signals;
153         mExplanation = explanation;
154         mUser = user;
155     }
156 
157     /**
158      * Create a notification adjustment.
159      *
160      * @param pkg The package of the notification.
161      * @param key The notification key.
162      * @param signals A bundle of signals that should inform notification display, ordering, and
163      *                interruptiveness.
164      * @param explanation A human-readable justification for the adjustment.
165      * @param userHandle User handle for for whose the adjustments will be applied.
166      */
Adjustment(@onNull String pkg, @NonNull String key, @NonNull Bundle signals, @NonNull CharSequence explanation, @NonNull UserHandle userHandle)167     public Adjustment(@NonNull String pkg, @NonNull String key, @NonNull Bundle signals,
168             @NonNull CharSequence explanation,
169             @NonNull UserHandle userHandle) {
170         mPackage = pkg;
171         mKey = key;
172         mSignals = signals;
173         mExplanation = explanation;
174         mUser = userHandle.getIdentifier();
175     }
176 
177     /**
178      * @hide
179      */
180     @SystemApi
Adjustment(Parcel in)181     protected Adjustment(Parcel in) {
182         if (in.readInt() == 1) {
183             mPackage = in.readString();
184         } else {
185             mPackage = null;
186         }
187         if (in.readInt() == 1) {
188             mKey = in.readString();
189         } else {
190             mKey = null;
191         }
192         if (in.readInt() == 1) {
193             mExplanation = in.readCharSequence();
194         } else {
195             mExplanation = null;
196         }
197         mSignals = in.readBundle();
198         mUser = in.readInt();
199         mIssuer = in.readString();
200     }
201 
202     public static final @android.annotation.NonNull Creator<Adjustment> CREATOR = new Creator<Adjustment>() {
203         @Override
204         public Adjustment createFromParcel(Parcel in) {
205             return new Adjustment(in);
206         }
207 
208         @Override
209         public Adjustment[] newArray(int size) {
210             return new Adjustment[size];
211         }
212     };
213 
getPackage()214     public @NonNull String getPackage() {
215         return mPackage;
216     }
217 
getKey()218     public @NonNull String getKey() {
219         return mKey;
220     }
221 
getExplanation()222     public @NonNull CharSequence getExplanation() {
223         return mExplanation;
224     }
225 
getSignals()226     public @NonNull Bundle getSignals() {
227         return mSignals;
228     }
229 
230     /** @hide */
231     @SystemApi
getUser()232     public int getUser() {
233         return mUser;
234     }
235 
getUserHandle()236     public @NonNull UserHandle getUserHandle() {
237         return UserHandle.of(mUser);
238     }
239 
240     @Override
describeContents()241     public int describeContents() {
242         return 0;
243     }
244 
245     @Override
writeToParcel(Parcel dest, int flags)246     public void writeToParcel(Parcel dest, int flags) {
247         if (mPackage != null) {
248             dest.writeInt(1);
249             dest.writeString(mPackage);
250         } else {
251             dest.writeInt(0);
252         }
253         if (mKey != null) {
254             dest.writeInt(1);
255             dest.writeString(mKey);
256         } else {
257             dest.writeInt(0);
258         }
259         if (mExplanation != null) {
260             dest.writeInt(1);
261             dest.writeCharSequence(mExplanation);
262         } else {
263             dest.writeInt(0);
264         }
265         dest.writeBundle(mSignals);
266         dest.writeInt(mUser);
267         dest.writeString(mIssuer);
268     }
269 
270     @NonNull
271     @Override
toString()272     public String toString() {
273         return "Adjustment{"
274                 + "mSignals=" + mSignals
275                 + '}';
276     }
277 
278     /** @hide */
setIssuer(@ullable String issuer)279     public void setIssuer(@Nullable String issuer) {
280         mIssuer = issuer;
281     }
282 
283     /** @hide */
getIssuer()284     public @Nullable String getIssuer() {
285         return mIssuer;
286     }
287 }
288