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