• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.ext.services.notification;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.text.TextUtils;
22 import android.util.Log;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 import org.xmlpull.v1.XmlSerializer;
28 
29 import java.io.IOException;
30 
31 public final class ChannelImpressions implements Parcelable {
32     private static final String TAG = "ExtAssistant.CI";
33     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
34 
35     static final float DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT = .8f;
36     static final int DEFAULT_STREAK_LIMIT = 2;
37     static final String ATT_DISMISSALS = "dismisses";
38     static final String ATT_VIEWS = "views";
39     static final String ATT_STREAK = "streak";
40 
41     private int mDismissals = 0;
42     private int mViews = 0;
43     private int mStreak = 0;
44 
45     private float mDismissToViewRatioLimit;
46     private int mStreakLimit;
47 
ChannelImpressions()48     public ChannelImpressions() {
49         mDismissToViewRatioLimit = DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT;
50         mStreakLimit = DEFAULT_STREAK_LIMIT;
51     }
52 
ChannelImpressions(Parcel in)53     protected ChannelImpressions(Parcel in) {
54         mDismissals = in.readInt();
55         mViews = in.readInt();
56         mStreak = in.readInt();
57         mDismissToViewRatioLimit = in.readFloat();
58         mStreakLimit = in.readInt();
59     }
60 
getStreak()61     public int getStreak() {
62         return mStreak;
63     }
64 
getDismissals()65     public int getDismissals() {
66         return mDismissals;
67     }
68 
getViews()69     public int getViews() {
70         return mViews;
71     }
72 
incrementDismissals()73     public void incrementDismissals() {
74         mDismissals++;
75         mStreak++;
76     }
77 
updateThresholds(float dismissToViewRatioLimit, int streakLimit)78     void updateThresholds(float dismissToViewRatioLimit, int streakLimit) {
79         mDismissToViewRatioLimit = dismissToViewRatioLimit;
80         mStreakLimit = streakLimit;
81     }
82 
83     @VisibleForTesting
getDismissToViewRatioLimit()84     float getDismissToViewRatioLimit() {
85         return mDismissToViewRatioLimit;
86     }
87 
88     @VisibleForTesting
getStreakLimit()89     int getStreakLimit() {
90         return mStreakLimit;
91     }
92 
append(ChannelImpressions additionalImpressions)93     public void append(ChannelImpressions additionalImpressions) {
94         if (additionalImpressions != null) {
95             mViews += additionalImpressions.getViews();
96             mStreak += additionalImpressions.getStreak();
97             mDismissals += additionalImpressions.getDismissals();
98         }
99     }
100 
incrementViews()101     public void incrementViews() {
102         mViews++;
103     }
104 
resetStreak()105     public void resetStreak() {
106         mStreak = 0;
107     }
108 
shouldTriggerBlock()109     public boolean shouldTriggerBlock() {
110         if (getViews() == 0) {
111             return false;
112         }
113         if (DEBUG) {
114             Log.d(TAG, "should trigger? " + getDismissals() + " " + getViews() + " " + getStreak());
115         }
116         return ((float) getDismissals() / getViews()) > mDismissToViewRatioLimit
117                 && getStreak() > mStreakLimit;
118     }
119 
120     @Override
writeToParcel(Parcel dest, int flags)121     public void writeToParcel(Parcel dest, int flags) {
122         dest.writeInt(mDismissals);
123         dest.writeInt(mViews);
124         dest.writeInt(mStreak);
125         dest.writeFloat(mDismissToViewRatioLimit);
126         dest.writeInt(mStreakLimit);
127     }
128 
129     @Override
describeContents()130     public int describeContents() {
131         return 0;
132     }
133 
134     public static final Creator<ChannelImpressions> CREATOR = new Creator<ChannelImpressions>() {
135         @Override
136         public ChannelImpressions createFromParcel(Parcel in) {
137             return new ChannelImpressions(in);
138         }
139 
140         @Override
141         public ChannelImpressions[] newArray(int size) {
142             return new ChannelImpressions[size];
143         }
144     };
145 
146     @Override
equals(Object o)147     public boolean equals(Object o) {
148         if (this == o) return true;
149         if (o == null || getClass() != o.getClass()) return false;
150 
151         ChannelImpressions that = (ChannelImpressions) o;
152 
153         if (mDismissals != that.mDismissals) return false;
154         if (mViews != that.mViews) return false;
155         return mStreak == that.mStreak;
156     }
157 
158     @Override
hashCode()159     public int hashCode() {
160         int result = mDismissals;
161         result = 31 * result + mViews;
162         result = 31 * result + mStreak;
163         return result;
164     }
165 
166     @Override
toString()167     public String toString() {
168         final StringBuilder sb = new StringBuilder("ChannelImpressions{");
169         sb.append("mDismissals=").append(mDismissals);
170         sb.append(", mViews=").append(mViews);
171         sb.append(", mStreak=").append(mStreak);
172         sb.append(", thresholds=(").append(mDismissToViewRatioLimit);
173         sb.append(",").append(mStreakLimit);
174         sb.append(")}");
175         return sb.toString();
176     }
177 
populateFromXml(XmlPullParser parser)178     protected void populateFromXml(XmlPullParser parser) {
179         mDismissals = safeInt(parser, ATT_DISMISSALS, 0);
180         mStreak = safeInt(parser, ATT_STREAK, 0);
181         mViews = safeInt(parser, ATT_VIEWS, 0);
182     }
183 
writeXml(XmlSerializer out)184     protected void writeXml(XmlSerializer out) throws IOException {
185         if (mDismissals != 0) {
186             out.attribute(null, ATT_DISMISSALS, String.valueOf(mDismissals));
187         }
188         if (mStreak != 0) {
189             out.attribute(null, ATT_STREAK, String.valueOf(mStreak));
190         }
191         if (mViews != 0) {
192             out.attribute(null, ATT_VIEWS, String.valueOf(mViews));
193         }
194     }
195 
safeInt(XmlPullParser parser, String att, int defValue)196     private static int safeInt(XmlPullParser parser, String att, int defValue) {
197         final String val = parser.getAttributeValue(null, att);
198         return tryParseInt(val, defValue);
199     }
200 
tryParseInt(String value, int defValue)201     private static int tryParseInt(String value, int defValue) {
202         if (TextUtils.isEmpty(value)) return defValue;
203         try {
204             return Integer.parseInt(value);
205         } catch (NumberFormatException e) {
206             return defValue;
207         }
208     }
209 }
210