blob: ebfabbfda3260db2f1dd6ba14f0f2e7d3665a000 [file] [log] [blame]
Julia Reynolds503ed942017-10-04 16:04:56 -04001/**
2 * Copyright (C) 2017 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 */
16package android.service.notification;
17
18import android.annotation.IntDef;
Julia Reynolds79f02772019-02-15 11:38:48 -050019import android.annotation.SystemApi;
Julia Reynolds503ed942017-10-04 16:04:56 -040020import android.app.RemoteInput;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24import java.lang.annotation.Retention;
25import java.lang.annotation.RetentionPolicy;
26
Julia Reynolds503ed942017-10-04 16:04:56 -040027public final class NotificationStats implements Parcelable {
28
29 private boolean mSeen;
30 private boolean mExpanded;
31 private boolean mDirectReplied;
32 private boolean mSnoozed;
33 private boolean mViewedSettings;
34 private boolean mInteracted;
35
36 /** @hide */
37 @IntDef(prefix = { "DISMISSAL_SURFACE_" }, value = {
38 DISMISSAL_NOT_DISMISSED, DISMISSAL_OTHER, DISMISSAL_PEEK, DISMISSAL_AOD, DISMISSAL_SHADE
39 })
40 @Retention(RetentionPolicy.SOURCE)
41 public @interface DismissalSurface {}
42
43
44 private @DismissalSurface int mDismissalSurface = DISMISSAL_NOT_DISMISSED;
45
46 /**
47 * Notification has not been dismissed yet.
48 */
Michael Wright3f4d5462018-08-22 23:34:45 +010049 public static final int DISMISSAL_NOT_DISMISSED = -1;
Julia Reynolds503ed942017-10-04 16:04:56 -040050 /**
51 * Notification has been dismissed from a {@link NotificationListenerService} or the app
52 * itself.
53 */
54 public static final int DISMISSAL_OTHER = 0;
55 /**
56 * Notification has been dismissed while peeking.
57 */
58 public static final int DISMISSAL_PEEK = 1;
59 /**
60 * Notification has been dismissed from always on display.
61 */
62 public static final int DISMISSAL_AOD = 2;
63 /**
64 * Notification has been dismissed from the notification shade.
65 */
66 public static final int DISMISSAL_SHADE = 3;
67
Julia Reynoldsfd4099d2018-08-21 11:06:06 -040068 /** @hide */
69 @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
70 DISMISS_SENTIMENT_UNKNOWN, DISMISS_SENTIMENT_NEGATIVE, DISMISS_SENTIMENT_NEUTRAL,
71 DISMISS_SENTIMENT_POSITIVE
72 })
73 @Retention(RetentionPolicy.SOURCE)
74 public @interface DismissalSentiment {}
75
76 /**
77 * No information is available about why this notification was dismissed, or the notification
78 * isn't dismissed yet.
79 */
80 public static final int DISMISS_SENTIMENT_UNKNOWN = -1000;
81 /**
82 * The user indicated while dismissing that they did not like the notification.
83 */
84 public static final int DISMISS_SENTIMENT_NEGATIVE = 0;
85 /**
86 * The user didn't indicate one way or another how they felt about the notification while
87 * dismissing it.
88 */
89 public static final int DISMISS_SENTIMENT_NEUTRAL = 1;
90 /**
91 * The user indicated while dismissing that they did like the notification.
92 */
93 public static final int DISMISS_SENTIMENT_POSITIVE = 2;
94
95
96 private @DismissalSentiment
97 int mDismissalSentiment = DISMISS_SENTIMENT_UNKNOWN;
98
Julia Reynolds503ed942017-10-04 16:04:56 -040099 public NotificationStats() {
100 }
101
Julia Reynolds79f02772019-02-15 11:38:48 -0500102 /**
103 * @hide
104 */
105 @SystemApi
106 protected NotificationStats(Parcel in) {
Julia Reynolds503ed942017-10-04 16:04:56 -0400107 mSeen = in.readByte() != 0;
108 mExpanded = in.readByte() != 0;
109 mDirectReplied = in.readByte() != 0;
110 mSnoozed = in.readByte() != 0;
111 mViewedSettings = in.readByte() != 0;
112 mInteracted = in.readByte() != 0;
113 mDismissalSurface = in.readInt();
Julia Reynoldsfd4099d2018-08-21 11:06:06 -0400114 mDismissalSentiment = in.readInt();
Julia Reynolds503ed942017-10-04 16:04:56 -0400115 }
116
117 @Override
118 public void writeToParcel(Parcel dest, int flags) {
119 dest.writeByte((byte) (mSeen ? 1 : 0));
120 dest.writeByte((byte) (mExpanded ? 1 : 0));
121 dest.writeByte((byte) (mDirectReplied ? 1 : 0));
122 dest.writeByte((byte) (mSnoozed ? 1 : 0));
123 dest.writeByte((byte) (mViewedSettings ? 1 : 0));
124 dest.writeByte((byte) (mInteracted ? 1 : 0));
125 dest.writeInt(mDismissalSurface);
Julia Reynoldsfd4099d2018-08-21 11:06:06 -0400126 dest.writeInt(mDismissalSentiment);
Julia Reynolds503ed942017-10-04 16:04:56 -0400127 }
128
129 @Override
130 public int describeContents() {
131 return 0;
132 }
133
134 public static final Creator<NotificationStats> CREATOR = new Creator<NotificationStats>() {
135 @Override
136 public NotificationStats createFromParcel(Parcel in) {
137 return new NotificationStats(in);
138 }
139
140 @Override
141 public NotificationStats[] newArray(int size) {
142 return new NotificationStats[size];
143 }
144 };
145
146 /**
147 * Returns whether the user has seen this notification at least once.
148 */
149 public boolean hasSeen() {
150 return mSeen;
151 }
152
153 /**
154 * Records that the user as seen this notification at least once.
155 */
156 public void setSeen() {
157 mSeen = true;
158 }
159
160 /**
161 * Returns whether the user has expanded this notification at least once.
162 */
163 public boolean hasExpanded() {
164 return mExpanded;
165 }
166
167 /**
168 * Records that the user has expanded this notification at least once.
169 */
170 public void setExpanded() {
171 mExpanded = true;
172 mInteracted = true;
173 }
174
175 /**
176 * Returns whether the user has replied to a notification that has a
177 * {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply} at
178 * least once.
179 */
180 public boolean hasDirectReplied() {
181 return mDirectReplied;
182 }
183
184 /**
185 * Records that the user has replied to a notification that has a
186 * {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply}
187 * at least once.
188 */
189 public void setDirectReplied() {
190 mDirectReplied = true;
191 mInteracted = true;
192 }
193
194 /**
195 * Returns whether the user has snoozed this notification at least once.
196 */
197 public boolean hasSnoozed() {
198 return mSnoozed;
199 }
200
201 /**
202 * Records that the user has snoozed this notification at least once.
203 */
204 public void setSnoozed() {
205 mSnoozed = true;
206 mInteracted = true;
207 }
208
209 /**
210 * Returns whether the user has viewed the in-shade settings for this notification at least
211 * once.
212 */
213 public boolean hasViewedSettings() {
214 return mViewedSettings;
215 }
216
217 /**
218 * Records that the user has viewed the in-shade settings for this notification at least once.
219 */
220 public void setViewedSettings() {
221 mViewedSettings = true;
222 mInteracted = true;
223 }
224
225 /**
226 * Returns whether the user has interacted with this notification beyond having viewed it.
227 */
228 public boolean hasInteracted() {
229 return mInteracted;
230 }
231
232 /**
233 * Returns from which surface the notification was dismissed.
234 */
235 public @DismissalSurface int getDismissalSurface() {
236 return mDismissalSurface;
237 }
238
239 /**
240 * Returns from which surface the notification was dismissed.
241 */
242 public void setDismissalSurface(@DismissalSurface int dismissalSurface) {
243 mDismissalSurface = dismissalSurface;
244 }
245
Julia Reynoldsfd4099d2018-08-21 11:06:06 -0400246 /**
247 * Records whether the user indicated how they felt about a notification before or
248 * during dismissal.
249 */
250 public void setDismissalSentiment(@DismissalSentiment int dismissalSentiment) {
251 mDismissalSentiment = dismissalSentiment;
252 }
253
254 /**
255 * Returns how the user indicated they felt about a notification before or during dismissal.
256 */
257 public @DismissalSentiment int getDismissalSentiment() {
258 return mDismissalSentiment;
259 }
260
Julia Reynolds503ed942017-10-04 16:04:56 -0400261 @Override
262 public boolean equals(Object o) {
263 if (this == o) return true;
264 if (o == null || getClass() != o.getClass()) return false;
265
266 NotificationStats that = (NotificationStats) o;
267
268 if (mSeen != that.mSeen) return false;
269 if (mExpanded != that.mExpanded) return false;
270 if (mDirectReplied != that.mDirectReplied) return false;
271 if (mSnoozed != that.mSnoozed) return false;
272 if (mViewedSettings != that.mViewedSettings) return false;
273 if (mInteracted != that.mInteracted) return false;
274 return mDismissalSurface == that.mDismissalSurface;
275 }
276
277 @Override
278 public int hashCode() {
279 int result = (mSeen ? 1 : 0);
280 result = 31 * result + (mExpanded ? 1 : 0);
281 result = 31 * result + (mDirectReplied ? 1 : 0);
282 result = 31 * result + (mSnoozed ? 1 : 0);
283 result = 31 * result + (mViewedSettings ? 1 : 0);
284 result = 31 * result + (mInteracted ? 1 : 0);
285 result = 31 * result + mDismissalSurface;
286 return result;
287 }
288
289 @Override
290 public String toString() {
291 final StringBuilder sb = new StringBuilder("NotificationStats{");
292 sb.append("mSeen=").append(mSeen);
293 sb.append(", mExpanded=").append(mExpanded);
294 sb.append(", mDirectReplied=").append(mDirectReplied);
295 sb.append(", mSnoozed=").append(mSnoozed);
296 sb.append(", mViewedSettings=").append(mViewedSettings);
297 sb.append(", mInteracted=").append(mInteracted);
298 sb.append(", mDismissalSurface=").append(mDismissalSurface);
299 sb.append('}');
300 return sb.toString();
301 }
302}