359 lines
11 KiB
Java
359 lines
11 KiB
Java
![]() |
/**
|
||
|
* Copyright (C) 2017 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
package android.service.notification;
|
||
|
|
||
|
import android.annotation.FlaggedApi;
|
||
|
import android.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.SuppressLint;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.app.Flags;
|
||
|
import android.app.RemoteInput;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
|
||
|
/**
|
||
|
* Information about how the user has interacted with a given notification.
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public final class NotificationStats implements Parcelable {
|
||
|
|
||
|
private boolean mSeen;
|
||
|
private boolean mExpanded;
|
||
|
private boolean mDirectReplied;
|
||
|
private boolean mSmartReplied;
|
||
|
private boolean mSnoozed;
|
||
|
private boolean mViewedSettings;
|
||
|
private boolean mInteracted;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(prefix = { "DISMISSAL_SURFACE_" }, value = {
|
||
|
DISMISSAL_NOT_DISMISSED, DISMISSAL_OTHER, DISMISSAL_PEEK, DISMISSAL_AOD,
|
||
|
DISMISSAL_SHADE, DISMISSAL_BUBBLE, DISMISSAL_LOCKSCREEN
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface DismissalSurface {}
|
||
|
|
||
|
|
||
|
private @DismissalSurface int mDismissalSurface = DISMISSAL_NOT_DISMISSED;
|
||
|
|
||
|
/**
|
||
|
* Notification has not been dismissed yet.
|
||
|
*/
|
||
|
public static final int DISMISSAL_NOT_DISMISSED = -1;
|
||
|
/**
|
||
|
* Notification has been dismissed from a {@link NotificationListenerService} or the app
|
||
|
* itself.
|
||
|
*/
|
||
|
public static final int DISMISSAL_OTHER = 0;
|
||
|
/**
|
||
|
* Notification has been dismissed while peeking.
|
||
|
*/
|
||
|
public static final int DISMISSAL_PEEK = 1;
|
||
|
/**
|
||
|
* Notification has been dismissed from always on display.
|
||
|
*/
|
||
|
public static final int DISMISSAL_AOD = 2;
|
||
|
/**
|
||
|
* Notification has been dismissed from the notification shade.
|
||
|
*/
|
||
|
public static final int DISMISSAL_SHADE = 3;
|
||
|
/**
|
||
|
* Notification has been dismissed as a bubble.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int DISMISSAL_BUBBLE = 4;
|
||
|
/**
|
||
|
* Notification has been dismissed from the lock screen.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int DISMISSAL_LOCKSCREEN = 5;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
|
||
|
DISMISS_SENTIMENT_UNKNOWN, DISMISS_SENTIMENT_NEGATIVE, DISMISS_SENTIMENT_NEUTRAL,
|
||
|
DISMISS_SENTIMENT_POSITIVE
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface DismissalSentiment {}
|
||
|
|
||
|
/**
|
||
|
* No information is available about why this notification was dismissed, or the notification
|
||
|
* isn't dismissed yet.
|
||
|
*/
|
||
|
public static final int DISMISS_SENTIMENT_UNKNOWN = -1000;
|
||
|
/**
|
||
|
* The user indicated while dismissing that they did not like the notification.
|
||
|
*/
|
||
|
public static final int DISMISS_SENTIMENT_NEGATIVE = 0;
|
||
|
/**
|
||
|
* The user didn't indicate one way or another how they felt about the notification while
|
||
|
* dismissing it.
|
||
|
*/
|
||
|
public static final int DISMISS_SENTIMENT_NEUTRAL = 1;
|
||
|
/**
|
||
|
* The user indicated while dismissing that they did like the notification.
|
||
|
*/
|
||
|
public static final int DISMISS_SENTIMENT_POSITIVE = 2;
|
||
|
|
||
|
|
||
|
private @DismissalSentiment
|
||
|
int mDismissalSentiment = DISMISS_SENTIMENT_UNKNOWN;
|
||
|
|
||
|
public NotificationStats() {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
protected NotificationStats(Parcel in) {
|
||
|
mSeen = in.readByte() != 0;
|
||
|
mExpanded = in.readByte() != 0;
|
||
|
mDirectReplied = in.readByte() != 0;
|
||
|
if (Flags.lifetimeExtensionRefactor()) {
|
||
|
mSmartReplied = in.readByte() != 0;
|
||
|
}
|
||
|
mSnoozed = in.readByte() != 0;
|
||
|
mViewedSettings = in.readByte() != 0;
|
||
|
mInteracted = in.readByte() != 0;
|
||
|
mDismissalSurface = in.readInt();
|
||
|
mDismissalSentiment = in.readInt();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel dest, int flags) {
|
||
|
dest.writeByte((byte) (mSeen ? 1 : 0));
|
||
|
dest.writeByte((byte) (mExpanded ? 1 : 0));
|
||
|
dest.writeByte((byte) (mDirectReplied ? 1 : 0));
|
||
|
if (Flags.lifetimeExtensionRefactor()) {
|
||
|
dest.writeByte((byte) (mSmartReplied ? 1 : 0));
|
||
|
}
|
||
|
dest.writeByte((byte) (mSnoozed ? 1 : 0));
|
||
|
dest.writeByte((byte) (mViewedSettings ? 1 : 0));
|
||
|
dest.writeByte((byte) (mInteracted ? 1 : 0));
|
||
|
dest.writeInt(mDismissalSurface);
|
||
|
dest.writeInt(mDismissalSentiment);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public static final @android.annotation.NonNull Creator<NotificationStats> CREATOR = new Creator<NotificationStats>() {
|
||
|
@Override
|
||
|
public NotificationStats createFromParcel(Parcel in) {
|
||
|
return new NotificationStats(in);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public NotificationStats[] newArray(int size) {
|
||
|
return new NotificationStats[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has seen this notification at least once.
|
||
|
*/
|
||
|
public boolean hasSeen() {
|
||
|
return mSeen;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user as seen this notification at least once.
|
||
|
*/
|
||
|
public void setSeen() {
|
||
|
mSeen = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has expanded this notification at least once.
|
||
|
*/
|
||
|
public boolean hasExpanded() {
|
||
|
return mExpanded;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user has expanded this notification at least once.
|
||
|
*/
|
||
|
public void setExpanded() {
|
||
|
mExpanded = true;
|
||
|
mInteracted = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has replied to a notification that has a
|
||
|
* {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply} at
|
||
|
* least once.
|
||
|
*/
|
||
|
public boolean hasDirectReplied() {
|
||
|
return mDirectReplied;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user has replied to a notification that has a
|
||
|
* {@link android.app.Notification.Action.Builder#addRemoteInput(RemoteInput) direct reply}
|
||
|
* at least once.
|
||
|
*/
|
||
|
public void setDirectReplied() {
|
||
|
mDirectReplied = true;
|
||
|
mInteracted = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has replied to a notification that has a smart reply at least once.
|
||
|
*/
|
||
|
@FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
|
||
|
public boolean hasSmartReplied() {
|
||
|
return mSmartReplied;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user has replied to a notification that has a smart reply at least once.
|
||
|
*/
|
||
|
@SuppressLint("GetterSetterNames")
|
||
|
@FlaggedApi(Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
|
||
|
public void setSmartReplied() {
|
||
|
mSmartReplied = true;
|
||
|
mInteracted = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has snoozed this notification at least once.
|
||
|
*/
|
||
|
public boolean hasSnoozed() {
|
||
|
return mSnoozed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user has snoozed this notification at least once.
|
||
|
*/
|
||
|
public void setSnoozed() {
|
||
|
mSnoozed = true;
|
||
|
mInteracted = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has viewed the in-shade settings for this notification at least
|
||
|
* once.
|
||
|
*/
|
||
|
public boolean hasViewedSettings() {
|
||
|
return mViewedSettings;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records that the user has viewed the in-shade settings for this notification at least once.
|
||
|
*/
|
||
|
public void setViewedSettings() {
|
||
|
mViewedSettings = true;
|
||
|
mInteracted = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether the user has interacted with this notification beyond having viewed it.
|
||
|
*/
|
||
|
public boolean hasInteracted() {
|
||
|
return mInteracted;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns from which surface the notification was dismissed.
|
||
|
*/
|
||
|
public @DismissalSurface int getDismissalSurface() {
|
||
|
return mDismissalSurface;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns from which surface the notification was dismissed.
|
||
|
*/
|
||
|
public void setDismissalSurface(@DismissalSurface int dismissalSurface) {
|
||
|
mDismissalSurface = dismissalSurface;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Records whether the user indicated how they felt about a notification before or
|
||
|
* during dismissal.
|
||
|
*/
|
||
|
public void setDismissalSentiment(@DismissalSentiment int dismissalSentiment) {
|
||
|
mDismissalSentiment = dismissalSentiment;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns how the user indicated they felt about a notification before or during dismissal.
|
||
|
*/
|
||
|
public @DismissalSentiment int getDismissalSentiment() {
|
||
|
return mDismissalSentiment;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
if (this == o) return true;
|
||
|
if (o == null || getClass() != o.getClass()) return false;
|
||
|
|
||
|
NotificationStats that = (NotificationStats) o;
|
||
|
|
||
|
if (mSeen != that.mSeen) return false;
|
||
|
if (mExpanded != that.mExpanded) return false;
|
||
|
if (mDirectReplied != that.mDirectReplied) return false;
|
||
|
if (Flags.lifetimeExtensionRefactor()) {
|
||
|
if (mSmartReplied != that.mSmartReplied) return false;
|
||
|
}
|
||
|
if (mSnoozed != that.mSnoozed) return false;
|
||
|
if (mViewedSettings != that.mViewedSettings) return false;
|
||
|
if (mInteracted != that.mInteracted) return false;
|
||
|
return mDismissalSurface == that.mDismissalSurface;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
int result = (mSeen ? 1 : 0);
|
||
|
result = 31 * result + (mExpanded ? 1 : 0);
|
||
|
result = 31 * result + (mDirectReplied ? 1 : 0);
|
||
|
if (Flags.lifetimeExtensionRefactor()) {
|
||
|
result = 31 * result + (mSmartReplied ? 1 : 0);
|
||
|
}
|
||
|
result = 31 * result + (mSnoozed ? 1 : 0);
|
||
|
result = 31 * result + (mViewedSettings ? 1 : 0);
|
||
|
result = 31 * result + (mInteracted ? 1 : 0);
|
||
|
result = 31 * result + mDismissalSurface;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
@NonNull
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
final StringBuilder sb = new StringBuilder("NotificationStats{");
|
||
|
sb.append("mSeen=").append(mSeen);
|
||
|
sb.append(", mExpanded=").append(mExpanded);
|
||
|
sb.append(", mDirectReplied=").append(mDirectReplied);
|
||
|
if (Flags.lifetimeExtensionRefactor()) {
|
||
|
sb.append(", mSmartReplied=").append(mSmartReplied);
|
||
|
}
|
||
|
sb.append(", mSnoozed=").append(mSnoozed);
|
||
|
sb.append(", mViewedSettings=").append(mViewedSettings);
|
||
|
sb.append(", mInteracted=").append(mInteracted);
|
||
|
sb.append(", mDismissalSurface=").append(mDismissalSurface);
|
||
|
sb.append('}');
|
||
|
return sb.toString();
|
||
|
}
|
||
|
}
|