1 /* 2 * Copyright (C) 2016 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 com.android.server.telecom.callfiltering; 18 19 import android.provider.CallLog; 20 import android.provider.CallLog.Calls; 21 import android.text.TextUtils; 22 23 import java.util.Objects; 24 25 public class CallFilteringResult { 26 public static class Builder { 27 private boolean mShouldAllowCall; 28 private boolean mShouldReject; 29 private boolean mShouldAddToCallLog; 30 private boolean mShouldShowNotification; 31 private boolean mShouldSilence = false; 32 private boolean mShouldScreenViaAudio = false; 33 private boolean mContactExists = false; 34 private int mCallBlockReason = Calls.BLOCK_REASON_NOT_BLOCKED; 35 private CharSequence mCallScreeningAppName = null; 36 private String mCallScreeningComponentName = null; 37 setShouldAllowCall(boolean shouldAllowCall)38 public Builder setShouldAllowCall(boolean shouldAllowCall) { 39 mShouldAllowCall = shouldAllowCall; 40 return this; 41 } 42 setShouldReject(boolean shouldReject)43 public Builder setShouldReject(boolean shouldReject) { 44 mShouldReject = shouldReject; 45 return this; 46 } 47 setShouldAddToCallLog(boolean shouldAddToCallLog)48 public Builder setShouldAddToCallLog(boolean shouldAddToCallLog) { 49 mShouldAddToCallLog = shouldAddToCallLog; 50 return this; 51 } 52 setShouldShowNotification(boolean shouldShowNotification)53 public Builder setShouldShowNotification(boolean shouldShowNotification) { 54 mShouldShowNotification = shouldShowNotification; 55 return this; 56 } 57 setShouldSilence(boolean shouldSilence)58 public Builder setShouldSilence(boolean shouldSilence) { 59 mShouldSilence = shouldSilence; 60 return this; 61 } 62 setCallBlockReason(int callBlockReason)63 public Builder setCallBlockReason(int callBlockReason) { 64 mCallBlockReason = callBlockReason; 65 return this; 66 } 67 setShouldScreenViaAudio(boolean shouldScreenViaAudio)68 public Builder setShouldScreenViaAudio(boolean shouldScreenViaAudio) { 69 mShouldScreenViaAudio = shouldScreenViaAudio; 70 return this; 71 } 72 setCallScreeningAppName(CharSequence callScreeningAppName)73 public Builder setCallScreeningAppName(CharSequence callScreeningAppName) { 74 mCallScreeningAppName = callScreeningAppName; 75 return this; 76 } 77 setCallScreeningComponentName(String callScreeningComponentName)78 public Builder setCallScreeningComponentName(String callScreeningComponentName) { 79 mCallScreeningComponentName = callScreeningComponentName; 80 return this; 81 } 82 setContactExists(boolean contactExists)83 public Builder setContactExists(boolean contactExists) { 84 mContactExists = contactExists; 85 return this; 86 } 87 from(CallFilteringResult result)88 public static Builder from(CallFilteringResult result) { 89 return new Builder() 90 .setShouldAllowCall(result.shouldAllowCall) 91 .setShouldReject(result.shouldReject) 92 .setShouldAddToCallLog(result.shouldAddToCallLog) 93 .setShouldShowNotification(result.shouldShowNotification) 94 .setShouldSilence(result.shouldSilence) 95 .setCallBlockReason(result.mCallBlockReason) 96 .setShouldScreenViaAudio(result.shouldScreenViaAudio) 97 .setCallScreeningAppName(result.mCallScreeningAppName) 98 .setCallScreeningComponentName(result.mCallScreeningComponentName) 99 .setContactExists(result.contactExists); 100 } 101 build()102 public CallFilteringResult build() { 103 return new CallFilteringResult(mShouldAllowCall, mShouldReject, mShouldSilence, 104 mShouldAddToCallLog, mShouldShowNotification, mCallBlockReason, 105 mCallScreeningAppName, mCallScreeningComponentName, mShouldScreenViaAudio, 106 mContactExists); 107 } 108 } 109 110 public boolean shouldAllowCall; 111 public boolean shouldReject; 112 public boolean shouldSilence; 113 public boolean shouldAddToCallLog; 114 public boolean shouldScreenViaAudio = false; 115 public boolean shouldShowNotification; 116 public int mCallBlockReason; 117 public CharSequence mCallScreeningAppName; 118 public String mCallScreeningComponentName; 119 public boolean contactExists; 120 CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName, boolean shouldScreenViaAudio, boolean contactExists)121 private CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean 122 shouldSilence, boolean shouldAddToCallLog, boolean shouldShowNotification, int 123 callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName, 124 boolean shouldScreenViaAudio, boolean contactExists) { 125 this.shouldAllowCall = shouldAllowCall; 126 this.shouldReject = shouldReject; 127 this.shouldSilence = shouldSilence; 128 this.shouldAddToCallLog = shouldAddToCallLog; 129 this.shouldShowNotification = shouldShowNotification; 130 this.shouldScreenViaAudio = shouldScreenViaAudio; 131 this.mCallBlockReason = callBlockReason; 132 this.mCallScreeningAppName = callScreeningAppName; 133 this.mCallScreeningComponentName = callScreeningComponentName; 134 this.contactExists = contactExists; 135 } 136 137 /** 138 * Combine this CallFilteringResult with another, returning a CallFilteringResult with the more 139 * restrictive properties of the two. Where there are multiple call filtering components which 140 * block a call, the first filter from {@link BlockCheckerFilter}, 141 * {@link DirectToVoicemailFilter}, {@link CallScreeningServiceFilter} which blocked a call 142 * shall be used to populate the call block reason, component name, etc. 143 */ combine(CallFilteringResult other)144 public CallFilteringResult combine(CallFilteringResult other) { 145 if (other == null) { 146 return this; 147 } 148 149 if (isBlockedByProvider(mCallBlockReason)) { 150 return getCombinedCallFilteringResult(other, mCallBlockReason, 151 null /*callScreeningAppName*/, null /*callScreeningComponentName*/); 152 } else if (isBlockedByProvider(other.mCallBlockReason)) { 153 return getCombinedCallFilteringResult(other, other.mCallBlockReason, 154 null /*callScreeningAppName*/, null /*callScreeningComponentName*/); 155 } 156 157 if (mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL 158 || other.mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL) { 159 return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, 160 null /*callScreeningAppName*/, null /*callScreeningComponentName*/); 161 } 162 163 if (shouldReject && mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) { 164 return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, 165 mCallScreeningAppName, mCallScreeningComponentName); 166 } else if (other.shouldReject && other.mCallBlockReason == CallLog.Calls 167 .BLOCK_REASON_CALL_SCREENING_SERVICE) { 168 return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, 169 other.mCallScreeningAppName, other.mCallScreeningComponentName); 170 } 171 172 if (shouldScreenViaAudio) { 173 return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_NOT_BLOCKED, 174 mCallScreeningAppName, mCallScreeningComponentName); 175 } else if (other.shouldScreenViaAudio) { 176 return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_NOT_BLOCKED, 177 other.mCallScreeningAppName, other.mCallScreeningComponentName); 178 } 179 180 return new Builder() 181 .setShouldAllowCall(shouldAllowCall && other.shouldAllowCall) 182 .setShouldReject(shouldReject || other.shouldReject) 183 .setShouldSilence(shouldSilence || other.shouldSilence) 184 .setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog) 185 .setShouldShowNotification(shouldShowNotification && other.shouldShowNotification) 186 .setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio) 187 .setContactExists(contactExists || other.contactExists) 188 .build(); 189 } 190 isBlockedByProvider(int blockReason)191 private boolean isBlockedByProvider(int blockReason) { 192 if (blockReason == Calls.BLOCK_REASON_BLOCKED_NUMBER 193 || blockReason == Calls.BLOCK_REASON_UNKNOWN_NUMBER 194 || blockReason == Calls.BLOCK_REASON_RESTRICTED_NUMBER 195 || blockReason == Calls.BLOCK_REASON_PAY_PHONE 196 || blockReason == Calls.BLOCK_REASON_NOT_IN_CONTACTS) { 197 return true; 198 } 199 200 return false; 201 } 202 getCombinedCallFilteringResult(CallFilteringResult other, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName)203 private CallFilteringResult getCombinedCallFilteringResult(CallFilteringResult other, 204 int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName) { 205 return new Builder() 206 .setShouldAllowCall(shouldAllowCall && other.shouldAllowCall) 207 .setShouldReject(shouldReject || other.shouldReject) 208 .setShouldSilence(shouldSilence || other.shouldSilence) 209 .setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog) 210 .setShouldShowNotification(shouldShowNotification && other.shouldShowNotification) 211 .setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio) 212 .setCallBlockReason(callBlockReason) 213 .setCallScreeningAppName(callScreeningAppName) 214 .setCallScreeningComponentName(callScreeningComponentName) 215 .setContactExists(contactExists || other.contactExists) 216 .build(); 217 } 218 219 220 @Override equals(Object o)221 public boolean equals(Object o) { 222 if (this == o) return true; 223 if (o == null || getClass() != o.getClass()) return false; 224 225 CallFilteringResult that = (CallFilteringResult) o; 226 227 if (shouldAllowCall != that.shouldAllowCall) return false; 228 if (shouldReject != that.shouldReject) return false; 229 if (shouldSilence != that.shouldSilence) return false; 230 if (shouldAddToCallLog != that.shouldAddToCallLog) return false; 231 if (shouldShowNotification != that.shouldShowNotification) return false; 232 if (mCallBlockReason != that.mCallBlockReason) return false; 233 if (contactExists != that.contactExists) return false; 234 235 if (!Objects.equals(mCallScreeningAppName, that.mCallScreeningAppName)) return false; 236 if (!Objects.equals(mCallScreeningComponentName, that.mCallScreeningComponentName)) { 237 return false; 238 } 239 return true; 240 } 241 242 @Override hashCode()243 public int hashCode() { 244 int result = (shouldAllowCall ? 1 : 0); 245 result = 31 * result + (shouldReject ? 1 : 0); 246 result = 31 * result + (shouldSilence ? 1 : 0); 247 result = 31 * result + (shouldAddToCallLog ? 1 : 0); 248 result = 31 * result + (shouldShowNotification ? 1 : 0); 249 return result; 250 } 251 252 @Override toString()253 public String toString() { 254 StringBuilder sb = new StringBuilder(); 255 sb.append("["); 256 if (shouldAllowCall) { 257 sb.append("Allow"); 258 } else if (shouldReject) { 259 sb.append("Reject"); 260 } else if (shouldSilence) { 261 sb.append("Silence"); 262 } else { 263 sb.append("Ignore"); 264 } 265 266 if (shouldScreenViaAudio) { 267 sb.append(", audio processing"); 268 } 269 270 if (shouldAddToCallLog) { 271 sb.append(", logged"); 272 } 273 274 if (shouldShowNotification) { 275 sb.append(", notified"); 276 } 277 278 if (contactExists) { 279 sb.append(", contact exists"); 280 } 281 282 if (mCallBlockReason != 0) { 283 sb.append(", mCallBlockReason = "); 284 sb.append(mCallBlockReason); 285 } 286 287 if (!TextUtils.isEmpty(mCallScreeningAppName)) { 288 sb.append(", mCallScreeningAppName = "); 289 sb.append(mCallScreeningAppName); 290 } 291 292 if (!TextUtils.isEmpty(mCallScreeningComponentName)) { 293 sb.append(", mCallScreeningComponentName = "); 294 sb.append(mCallScreeningComponentName); 295 } 296 sb.append("]"); 297 298 return sb.toString(); 299 } 300 } 301