1 /**
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  */
16 package android.service.notification;
17 
18 import android.annotation.IntDef;
19 import android.annotation.SystemApi;
20 import android.annotation.TestApi;
21 import android.app.RemoteInput;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 
28 /**
29  * @hide
30  */
31 @TestApi
32 @SystemApi
33 public final class NotificationStats implements Parcelable {
34 
35     private boolean mSeen;
36     private boolean mExpanded;
37     private boolean mDirectReplied;
38     private boolean mSnoozed;
39     private boolean mViewedSettings;
40     private boolean mInteracted;
41 
42     /** @hide */
43     @IntDef(prefix = { "DISMISSAL_SURFACE_" }, value = {
44             DISMISSAL_NOT_DISMISSED, DISMISSAL_OTHER, DISMISSAL_PEEK, DISMISSAL_AOD, DISMISSAL_SHADE
45     })
46     @Retention(RetentionPolicy.SOURCE)
47     public @interface DismissalSurface {}
48 
49 
50     private @DismissalSurface int mDismissalSurface = DISMISSAL_NOT_DISMISSED;
51 
52     /**
53      * Notification has not been dismissed yet.
54      */
55     public static final int DISMISSAL_NOT_DISMISSED = -1;
56     /**
57      * Notification has been dismissed from a {@link NotificationListenerService} or the app
58      * itself.
59      */
60     public static final int DISMISSAL_OTHER = 0;
61     /**
62      * Notification has been dismissed while peeking.
63      */
64     public static final int DISMISSAL_PEEK = 1;
65     /**
66      * Notification has been dismissed from always on display.
67      */
68     public static final int DISMISSAL_AOD = 2;
69     /**
70      * Notification has been dismissed from the notification shade.
71      */
72     public static final int DISMISSAL_SHADE = 3;
73 
NotificationStats()74     public NotificationStats() {
75     }
76 
NotificationStats(Parcel in)77     protected NotificationStats(Parcel in) {
78         mSeen = in.readByte() != 0;
79         mExpanded = in.readByte() != 0;
80         mDirectReplied = in.readByte() != 0;
81         mSnoozed = in.readByte() != 0;
82         mViewedSettings = in.readByte() != 0;
83         mInteracted = in.readByte() != 0;
84         mDismissalSurface = in.readInt();
85     }
86 
87     @Override
writeToParcel(Parcel dest, int flags)88     public void writeToParcel(Parcel dest, int flags) {
89         dest.writeByte((byte) (mSeen ? 1 : 0));
90         dest.writeByte((byte) (mExpanded ? 1 : 0));
91         dest.writeByte((byte) (mDirectReplied ? 1 : 0));
92         dest.writeByte((byte) (mSnoozed ? 1 : 0));
93         dest.writeByte((byte) (mViewedSettings ? 1 : 0));
94         dest.writeByte((byte) (mInteracted ? 1 : 0));
95         dest.writeInt(mDismissalSurface);
96     }
97 
98     @Override
describeContents()99     public int describeContents() {
100         return 0;
101     }
102 
103     public static final Creator<NotificationStats> CREATOR = new Creator<NotificationStats>() {
104         @Override
105         public NotificationStats createFromParcel(Parcel in) {
106             return new NotificationStats(in);
107         }
108 
109         @Override
110         public NotificationStats[] newArray(int size) {
111             return new NotificationStats[size];
112         }
113     };
114 
115     /**
116      * Returns whether the user has seen this notification at least once.
117      */
hasSeen()118     public boolean hasSeen() {
119         return mSeen;
120     }
121 
122     /**
123      * Records that the user as seen this notification at least once.
124      */
setSeen()125     public void setSeen() {
126         mSeen = true;
127     }
128 
129     /**
130      * Returns whether the user has expanded this notification at least once.
131      */
hasExpanded()132     public boolean hasExpanded() {
133         return mExpanded;
134     }
135 
136     /**
137      * Records that the user has expanded this notification at least once.
138      */
setExpanded()139     public void setExpanded() {
140         mExpanded = true;
141         mInteracted = true;
142     }
143 
144     /**
145      * Returns whether the user has replied to a notification that has a
146      * {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply} at
147      * least once.
148      */
hasDirectReplied()149     public boolean hasDirectReplied() {
150         return mDirectReplied;
151     }
152 
153     /**
154      * Records that the user has replied to a notification that has a
155      * {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply}
156      * at least once.
157      */
setDirectReplied()158     public void setDirectReplied() {
159         mDirectReplied = true;
160         mInteracted = true;
161     }
162 
163     /**
164      * Returns whether the user has snoozed this notification at least once.
165      */
hasSnoozed()166     public boolean hasSnoozed() {
167         return mSnoozed;
168     }
169 
170     /**
171      * Records that the user has snoozed this notification at least once.
172      */
setSnoozed()173     public void setSnoozed() {
174         mSnoozed = true;
175         mInteracted = true;
176     }
177 
178     /**
179      * Returns whether the user has viewed the in-shade settings for this notification at least
180      * once.
181      */
hasViewedSettings()182     public boolean hasViewedSettings() {
183         return mViewedSettings;
184     }
185 
186     /**
187      * Records that the user has viewed the in-shade settings for this notification at least once.
188      */
setViewedSettings()189     public void setViewedSettings() {
190         mViewedSettings = true;
191         mInteracted = true;
192     }
193 
194     /**
195      * Returns whether the user has interacted with this notification beyond having viewed it.
196      */
hasInteracted()197     public boolean hasInteracted() {
198         return mInteracted;
199     }
200 
201     /**
202      * Returns from which surface the notification was dismissed.
203      */
getDismissalSurface()204     public @DismissalSurface int getDismissalSurface() {
205         return mDismissalSurface;
206     }
207 
208     /**
209      * Returns from which surface the notification was dismissed.
210      */
setDismissalSurface(@ismissalSurface int dismissalSurface)211     public void setDismissalSurface(@DismissalSurface int dismissalSurface) {
212         mDismissalSurface = dismissalSurface;
213     }
214 
215     @Override
equals(Object o)216     public boolean equals(Object o) {
217         if (this == o) return true;
218         if (o == null || getClass() != o.getClass()) return false;
219 
220         NotificationStats that = (NotificationStats) o;
221 
222         if (mSeen != that.mSeen) return false;
223         if (mExpanded != that.mExpanded) return false;
224         if (mDirectReplied != that.mDirectReplied) return false;
225         if (mSnoozed != that.mSnoozed) return false;
226         if (mViewedSettings != that.mViewedSettings) return false;
227         if (mInteracted != that.mInteracted) return false;
228         return mDismissalSurface == that.mDismissalSurface;
229     }
230 
231     @Override
hashCode()232     public int hashCode() {
233         int result = (mSeen ? 1 : 0);
234         result = 31 * result + (mExpanded ? 1 : 0);
235         result = 31 * result + (mDirectReplied ? 1 : 0);
236         result = 31 * result + (mSnoozed ? 1 : 0);
237         result = 31 * result + (mViewedSettings ? 1 : 0);
238         result = 31 * result + (mInteracted ? 1 : 0);
239         result = 31 * result + mDismissalSurface;
240         return result;
241     }
242 
243     @Override
toString()244     public String toString() {
245         final StringBuilder sb = new StringBuilder("NotificationStats{");
246         sb.append("mSeen=").append(mSeen);
247         sb.append(", mExpanded=").append(mExpanded);
248         sb.append(", mDirectReplied=").append(mDirectReplied);
249         sb.append(", mSnoozed=").append(mSnoozed);
250         sb.append(", mViewedSettings=").append(mViewedSettings);
251         sb.append(", mInteracted=").append(mInteracted);
252         sb.append(", mDismissalSurface=").append(mDismissalSurface);
253         sb.append('}');
254         return sb.toString();
255     }
256 }
257