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 android.telecom; 18 19 import android.Manifest; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SystemApi; 25 import android.app.Service; 26 import android.content.ComponentName; 27 import android.content.Intent; 28 import android.content.pm.ServiceInfo; 29 import android.net.Uri; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.Looper; 33 import android.os.Message; 34 import android.os.Parcel; 35 import android.os.Parcelable; 36 import android.os.RemoteException; 37 38 import com.android.internal.os.SomeArgs; 39 import com.android.internal.telecom.ICallScreeningAdapter; 40 import com.android.internal.telecom.ICallScreeningService; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.Objects; 45 46 /** 47 * This service can be implemented by the default dialer (see 48 * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow 49 * incoming calls before they are shown to a user. A {@link CallScreeningService} can also see 50 * outgoing calls for the purpose of providing caller ID services for those calls. 51 * <p> 52 * Below is an example manifest registration for a {@code CallScreeningService}. 53 * <pre> 54 * {@code 55 * <service android:name="your.package.YourCallScreeningServiceImplementation" 56 * android:permission="android.permission.BIND_SCREENING_SERVICE"> 57 * <intent-filter> 58 * <action android:name="android.telecom.CallScreeningService"/> 59 * </intent-filter> 60 * </service> 61 * } 62 * </pre> 63 * <p> 64 * A CallScreeningService performs two functions: 65 * <ol> 66 * <li>Call blocking/screening - the service can choose which calls will ring on the user's 67 * device, and which will be silently sent to voicemail.</li> 68 * <li>Call identification - services which provide call identification functionality can 69 * display a user-interface of their choosing which contains identifying information for a call. 70 * </li> 71 * </ol> 72 * <p> 73 * <h2>Becoming the CallScreeningService</h2> 74 * Telecom will bind to a single app chosen by the user which implements the 75 * {@link CallScreeningService} API when there are new incoming and outgoing calls. 76 * <p> 77 * The code snippet below illustrates how your app can request that it fills the call screening 78 * role. 79 * <pre> 80 * {@code 81 * private static final int REQUEST_ID = 1; 82 * 83 * public void requestRole() { 84 * RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE); 85 * Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING); 86 * startActivityForResult(intent, REQUEST_ID); 87 * } 88 * 89 * @Override 90 * public void onActivityResult(int requestCode, int resultCode, Intent data) { 91 * if (requestCode == REQUEST_ID) { 92 * if (resultCode == android.app.Activity.RESULT_OK) { 93 * // Your app is now the call screening app 94 * } else { 95 * // Your app is not the call screening app 96 * } 97 * } 98 * } 99 * } 100 * </pre> 101 * 102 * <h2>CallScreeningService Lifecycle</h2> 103 * 104 * The framework binds to the {@link CallScreeningService} implemented by the user-chosen app 105 * filling the {@link android.app.role.RoleManager#ROLE_CALL_SCREENING} role when incoming calls are 106 * received (prior to ringing) and when outgoing calls are placed. The platform calls the 107 * {@link #onScreenCall(Call.Details)} method to provide your service with details about the call. 108 * <p> 109 * For incoming calls, the {@link CallScreeningService} must call 110 * {@link #respondToCall(Call.Details, CallResponse)} within 5 seconds of being bound to indicate to 111 * the platform whether the call should be blocked or not. Your app must do this even if it is 112 * primarily performing caller ID operations and not screening calls. It is important to perform 113 * screening operations in a timely matter as the user's device will not begin ringing until the 114 * response is received (or the timeout is hit). A {@link CallScreeningService} may choose to 115 * perform local database lookups to help determine if a call should be screened or not; care should 116 * be taken to ensure the timeout is not repeatedly hit, causing delays in the incoming call flow. 117 * <p> 118 * If your app provides a caller ID experience, it should launch an activity to show the caller ID 119 * information from {@link #onScreenCall(Call.Details)}. 120 */ 121 public abstract class CallScreeningService extends Service { 122 /** 123 * The {@link Intent} that must be declared as handled by the service. 124 */ 125 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 126 public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService"; 127 128 private static final int MSG_SCREEN_CALL = 1; 129 130 private final Handler mHandler = new Handler(Looper.getMainLooper()) { 131 @Override 132 public void handleMessage(Message msg) { 133 switch (msg.what) { 134 case MSG_SCREEN_CALL: 135 SomeArgs args = (SomeArgs) msg.obj; 136 try { 137 mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1; 138 Call.Details callDetails = Call.Details 139 .createFromParcelableCall((ParcelableCall) args.arg2); 140 onScreenCall(callDetails); 141 if (callDetails.getCallDirection() == Call.Details.DIRECTION_OUTGOING) { 142 mCallScreeningAdapter.onScreeningResponse( 143 callDetails.getTelecomCallId(), 144 new ComponentName(getPackageName(), getClass().getName()), 145 null); 146 } 147 } catch (RemoteException e) { 148 Log.w(this, "Exception when screening call: " + e); 149 } finally { 150 args.recycle(); 151 } 152 break; 153 } 154 } 155 }; 156 157 private final class CallScreeningBinder extends ICallScreeningService.Stub { 158 @Override screenCall(ICallScreeningAdapter adapter, ParcelableCall call)159 public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) { 160 Log.v(this, "screenCall"); 161 SomeArgs args = SomeArgs.obtain(); 162 args.arg1 = adapter; 163 args.arg2 = call; 164 mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget(); 165 } 166 } 167 168 private ICallScreeningAdapter mCallScreeningAdapter; 169 170 /** 171 * Parcelable version of {@link CallResponse} used to do IPC. 172 * @hide 173 */ 174 public static class ParcelableCallResponse implements Parcelable { 175 private final boolean mShouldDisallowCall; 176 private final boolean mShouldRejectCall; 177 private final boolean mShouldSilenceCall; 178 private final boolean mShouldSkipCallLog; 179 private final boolean mShouldSkipNotification; 180 private final boolean mShouldScreenCallViaAudioProcessing; 181 182 private final int mCallComposerAttachmentsToShow; 183 ParcelableCallResponse( boolean shouldDisallowCall, boolean shouldRejectCall, boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow)184 private ParcelableCallResponse( 185 boolean shouldDisallowCall, 186 boolean shouldRejectCall, 187 boolean shouldSilenceCall, 188 boolean shouldSkipCallLog, 189 boolean shouldSkipNotification, 190 boolean shouldScreenCallViaAudioProcessing, 191 int callComposerAttachmentsToShow) { 192 mShouldDisallowCall = shouldDisallowCall; 193 mShouldRejectCall = shouldRejectCall; 194 mShouldSilenceCall = shouldSilenceCall; 195 mShouldSkipCallLog = shouldSkipCallLog; 196 mShouldSkipNotification = shouldSkipNotification; 197 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; 198 mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; 199 } 200 ParcelableCallResponse(Parcel in)201 protected ParcelableCallResponse(Parcel in) { 202 mShouldDisallowCall = in.readBoolean(); 203 mShouldRejectCall = in.readBoolean(); 204 mShouldSilenceCall = in.readBoolean(); 205 mShouldSkipCallLog = in.readBoolean(); 206 mShouldSkipNotification = in.readBoolean(); 207 mShouldScreenCallViaAudioProcessing = in.readBoolean(); 208 mCallComposerAttachmentsToShow = in.readInt(); 209 } 210 toCallResponse()211 public CallResponse toCallResponse() { 212 return new CallResponse.Builder() 213 .setDisallowCall(mShouldDisallowCall) 214 .setRejectCall(mShouldRejectCall) 215 .setSilenceCall(mShouldSilenceCall) 216 .setSkipCallLog(mShouldSkipCallLog) 217 .setSkipNotification(mShouldSkipNotification) 218 .setShouldScreenCallViaAudioProcessing(mShouldScreenCallViaAudioProcessing) 219 .setCallComposerAttachmentsToShow(mCallComposerAttachmentsToShow) 220 .build(); 221 } 222 shouldDisallowCall()223 public boolean shouldDisallowCall() { 224 return mShouldDisallowCall; 225 } 226 shouldRejectCall()227 public boolean shouldRejectCall() { 228 return mShouldRejectCall; 229 } 230 shouldSilenceCall()231 public boolean shouldSilenceCall() { 232 return mShouldSilenceCall; 233 } 234 shouldSkipCallLog()235 public boolean shouldSkipCallLog() { 236 return mShouldSkipCallLog; 237 } 238 shouldSkipNotification()239 public boolean shouldSkipNotification() { 240 return mShouldSkipNotification; 241 } 242 shouldScreenCallViaAudioProcessing()243 public boolean shouldScreenCallViaAudioProcessing() { 244 return mShouldScreenCallViaAudioProcessing; 245 } 246 getCallComposerAttachmentsToShow()247 public int getCallComposerAttachmentsToShow() { 248 return mCallComposerAttachmentsToShow; 249 } 250 251 public static final Creator<ParcelableCallResponse> CREATOR = 252 new Creator<ParcelableCallResponse>() { 253 @Override 254 public ParcelableCallResponse createFromParcel(Parcel in) { 255 return new ParcelableCallResponse(in); 256 } 257 258 @Override 259 public ParcelableCallResponse[] newArray(int size) { 260 return new ParcelableCallResponse[size]; 261 } 262 }; 263 264 @Override describeContents()265 public int describeContents() { 266 return 0; 267 } 268 269 @Override writeToParcel(Parcel dest, int flags)270 public void writeToParcel(Parcel dest, int flags) { 271 dest.writeBoolean(mShouldDisallowCall); 272 dest.writeBoolean(mShouldRejectCall); 273 dest.writeBoolean(mShouldSilenceCall); 274 dest.writeBoolean(mShouldSkipCallLog); 275 dest.writeBoolean(mShouldSkipNotification); 276 dest.writeBoolean(mShouldScreenCallViaAudioProcessing); 277 dest.writeInt(mCallComposerAttachmentsToShow); 278 } 279 } 280 281 /** 282 * Information about how to respond to an incoming call. Call screening apps can construct an 283 * instance of this class using {@link CallResponse.Builder}. 284 */ 285 public static class CallResponse { 286 /** 287 * Bit flag indicating whether to show the picture attachment for call composer. 288 * 289 * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. 290 */ 291 public static final int CALL_COMPOSER_ATTACHMENT_PICTURE = 1; 292 293 /** 294 * Bit flag indicating whether to show the location attachment for call composer. 295 * 296 * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. 297 */ 298 public static final int CALL_COMPOSER_ATTACHMENT_LOCATION = 1 << 1; 299 300 /** 301 * Bit flag indicating whether to show the subject attachment for call composer. 302 * 303 * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. 304 */ 305 public static final int CALL_COMPOSER_ATTACHMENT_SUBJECT = 1 << 2; 306 307 /** 308 * Bit flag indicating whether to show the priority attachment for call composer. 309 * 310 * Used with {@link Builder#setCallComposerAttachmentsToShow(int)}. 311 */ 312 public static final int CALL_COMPOSER_ATTACHMENT_PRIORITY = 1 << 3; 313 314 /** @hide */ 315 @Retention(RetentionPolicy.SOURCE) 316 @IntDef(prefix = "CALL_COMPOSER_ATTACHMENT_", flag = true, 317 value = { 318 CALL_COMPOSER_ATTACHMENT_PICTURE, 319 CALL_COMPOSER_ATTACHMENT_LOCATION, 320 CALL_COMPOSER_ATTACHMENT_SUBJECT, 321 CALL_COMPOSER_ATTACHMENT_PRIORITY 322 } 323 ) 324 public @interface CallComposerAttachmentType {} 325 326 private static final int NUM_CALL_COMPOSER_ATTACHMENT_TYPES = 4; 327 328 private final boolean mShouldDisallowCall; 329 private final boolean mShouldRejectCall; 330 private final boolean mShouldSilenceCall; 331 private final boolean mShouldSkipCallLog; 332 private final boolean mShouldSkipNotification; 333 private final boolean mShouldScreenCallViaAudioProcessing; 334 private final int mCallComposerAttachmentsToShow; 335 CallResponse( boolean shouldDisallowCall, boolean shouldRejectCall, boolean shouldSilenceCall, boolean shouldSkipCallLog, boolean shouldSkipNotification, boolean shouldScreenCallViaAudioProcessing, int callComposerAttachmentsToShow)336 private CallResponse( 337 boolean shouldDisallowCall, 338 boolean shouldRejectCall, 339 boolean shouldSilenceCall, 340 boolean shouldSkipCallLog, 341 boolean shouldSkipNotification, 342 boolean shouldScreenCallViaAudioProcessing, 343 int callComposerAttachmentsToShow) { 344 if (!shouldDisallowCall 345 && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) { 346 throw new IllegalStateException("Invalid response state for allowed call."); 347 } 348 349 if (shouldDisallowCall && shouldScreenCallViaAudioProcessing) { 350 throw new IllegalStateException("Invalid response state for allowed call."); 351 } 352 353 mShouldDisallowCall = shouldDisallowCall; 354 mShouldRejectCall = shouldRejectCall; 355 mShouldSkipCallLog = shouldSkipCallLog; 356 mShouldSkipNotification = shouldSkipNotification; 357 mShouldSilenceCall = shouldSilenceCall; 358 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; 359 mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; 360 } 361 362 /* 363 * @return Whether the incoming call should be blocked. 364 */ getDisallowCall()365 public boolean getDisallowCall() { 366 return mShouldDisallowCall; 367 } 368 369 /* 370 * @return Whether the incoming call should be disconnected as if the user had manually 371 * rejected it. 372 */ getRejectCall()373 public boolean getRejectCall() { 374 return mShouldRejectCall; 375 } 376 377 /* 378 * @return Whether the ringtone should be silenced for the incoming call. 379 */ getSilenceCall()380 public boolean getSilenceCall() { 381 return mShouldSilenceCall; 382 } 383 384 /* 385 * @return Whether the incoming call should not be displayed in the call log. 386 */ getSkipCallLog()387 public boolean getSkipCallLog() { 388 return mShouldSkipCallLog; 389 } 390 391 /* 392 * @return Whether a missed call notification should not be shown for the incoming call. 393 */ getSkipNotification()394 public boolean getSkipNotification() { 395 return mShouldSkipNotification; 396 } 397 398 /** 399 * @return Whether we should enter the {@link Call#STATE_AUDIO_PROCESSING} state to allow 400 * for further screening of the call. 401 * @hide 402 */ getShouldScreenCallViaAudioProcessing()403 public boolean getShouldScreenCallViaAudioProcessing() { 404 return mShouldScreenCallViaAudioProcessing; 405 } 406 407 /** 408 * @return A bitmask of call composer attachments that should be shown to the user. 409 */ getCallComposerAttachmentsToShow()410 public @CallComposerAttachmentType int getCallComposerAttachmentsToShow() { 411 return mCallComposerAttachmentsToShow; 412 } 413 414 /** @hide */ toParcelable()415 public ParcelableCallResponse toParcelable() { 416 return new ParcelableCallResponse( 417 mShouldDisallowCall, 418 mShouldRejectCall, 419 mShouldSilenceCall, 420 mShouldSkipCallLog, 421 mShouldSkipNotification, 422 mShouldScreenCallViaAudioProcessing, 423 mCallComposerAttachmentsToShow 424 ); 425 } 426 427 @Override equals(Object o)428 public boolean equals(Object o) { 429 if (this == o) return true; 430 if (o == null || getClass() != o.getClass()) return false; 431 CallResponse that = (CallResponse) o; 432 return mShouldDisallowCall == that.mShouldDisallowCall && 433 mShouldRejectCall == that.mShouldRejectCall && 434 mShouldSilenceCall == that.mShouldSilenceCall && 435 mShouldSkipCallLog == that.mShouldSkipCallLog && 436 mShouldSkipNotification == that.mShouldSkipNotification && 437 mShouldScreenCallViaAudioProcessing 438 == that.mShouldScreenCallViaAudioProcessing && 439 mCallComposerAttachmentsToShow == that.mCallComposerAttachmentsToShow; 440 } 441 442 @Override hashCode()443 public int hashCode() { 444 return Objects.hash(mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall, 445 mShouldSkipCallLog, mShouldSkipNotification, 446 mShouldScreenCallViaAudioProcessing, 447 mCallComposerAttachmentsToShow); 448 } 449 450 public static class Builder { 451 private boolean mShouldDisallowCall; 452 private boolean mShouldRejectCall; 453 private boolean mShouldSilenceCall; 454 private boolean mShouldSkipCallLog; 455 private boolean mShouldSkipNotification; 456 private boolean mShouldScreenCallViaAudioProcessing; 457 private int mCallComposerAttachmentsToShow = -1; 458 459 /** 460 * Sets whether the incoming call should be blocked. 461 */ setDisallowCall(boolean shouldDisallowCall)462 public Builder setDisallowCall(boolean shouldDisallowCall) { 463 mShouldDisallowCall = shouldDisallowCall; 464 return this; 465 } 466 467 /** 468 * Sets whether the incoming call should be disconnected as if the user had manually 469 * rejected it. This property should only be set to true if the call is disallowed. 470 */ setRejectCall(boolean shouldRejectCall)471 public Builder setRejectCall(boolean shouldRejectCall) { 472 mShouldRejectCall = shouldRejectCall; 473 return this; 474 } 475 476 /** 477 * Sets whether ringing should be silenced for the incoming call. When set 478 * to {@code true}, the Telecom framework will not play a ringtone for the call. 479 * The call will, however, still be sent to the default dialer app if it is not blocked. 480 * A {@link CallScreeningService} can use this to ensure a potential nuisance call is 481 * still surfaced to the user, but in a less intrusive manner. 482 * 483 * Setting this to true only makes sense when the call has not been disallowed 484 * using {@link #setDisallowCall(boolean)}. 485 */ setSilenceCall(boolean shouldSilenceCall)486 public @NonNull Builder setSilenceCall(boolean shouldSilenceCall) { 487 mShouldSilenceCall = shouldSilenceCall; 488 return this; 489 } 490 491 /** 492 * Sets whether the incoming call should not be displayed in the call log. This property 493 * should only be set to true if the call is disallowed. 494 * <p> 495 * Note: Calls will still be logged with type 496 * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}, regardless of how this property 497 * is set. 498 */ setSkipCallLog(boolean shouldSkipCallLog)499 public Builder setSkipCallLog(boolean shouldSkipCallLog) { 500 mShouldSkipCallLog = shouldSkipCallLog; 501 return this; 502 } 503 504 /** 505 * Sets whether a missed call notification should not be shown for the incoming call. 506 * This property should only be set to true if the call is disallowed. 507 */ setSkipNotification(boolean shouldSkipNotification)508 public Builder setSkipNotification(boolean shouldSkipNotification) { 509 mShouldSkipNotification = shouldSkipNotification; 510 return this; 511 } 512 513 /** 514 * Sets whether to request background audio processing so that the in-call service can 515 * screen the call further. If set to {@code true}, {@link #setDisallowCall} should be 516 * called with {@code false}, and all other parameters in this builder will be ignored. 517 * <p> 518 * This request will only be honored if the {@link CallScreeningService} shares the same 519 * uid as the system dialer app. Otherwise, the call will go through as usual. 520 * <p> 521 * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which 522 * are using the microphone as part of audio processing should specify the 523 * foreground service type using the attribute 524 * {@link android.R.attr#foregroundServiceType} in the {@link CallScreeningService} 525 * service element of the app's manifest file. 526 * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be 527 * specified. 528 * @see 529 * <a href="https://developer.android.com/preview/privacy/foreground-service-types"> 530 * the Android Developer Site</a> for more information. 531 * 532 * @param shouldScreenCallViaAudioProcessing Whether to request further call screening. 533 * @hide 534 */ 535 @SystemApi 536 @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT) setShouldScreenCallViaAudioProcessing( boolean shouldScreenCallViaAudioProcessing)537 public @NonNull Builder setShouldScreenCallViaAudioProcessing( 538 boolean shouldScreenCallViaAudioProcessing) { 539 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing; 540 return this; 541 } 542 543 /** 544 * Sets the call composer attachments that should be shown to the user. 545 * 546 * Attachments that are not shown will not be passed to the in-call UI responsible for 547 * displaying the call to the user. 548 * 549 * If this method is not called on a {@link Builder}, all attachments will be shown, 550 * except pictures, which will only be shown to users if the call is from a contact. 551 * 552 * Setting attachments to show will have no effect if the call screening service does 553 * not belong to the same package as the system dialer (as returned by 554 * {@link TelecomManager#getSystemDialerPackage()}). 555 * 556 * @param callComposerAttachmentsToShow A bitmask of call composer attachments to show. 557 */ setCallComposerAttachmentsToShow( @allComposerAttachmentType int callComposerAttachmentsToShow)558 public @NonNull Builder setCallComposerAttachmentsToShow( 559 @CallComposerAttachmentType int callComposerAttachmentsToShow) { 560 // If the argument is less than zero (meaning unset), no-op since the conversion 561 // to/from the parcelable version may call with that value. 562 if (callComposerAttachmentsToShow < 0) { 563 return this; 564 } 565 566 if ((callComposerAttachmentsToShow 567 & (1 << NUM_CALL_COMPOSER_ATTACHMENT_TYPES)) != 0) { 568 throw new IllegalArgumentException("Attachment types must match the ones" 569 + " defined in CallResponse"); 570 } 571 mCallComposerAttachmentsToShow = callComposerAttachmentsToShow; 572 return this; 573 } 574 build()575 public CallResponse build() { 576 return new CallResponse( 577 mShouldDisallowCall, 578 mShouldRejectCall, 579 mShouldSilenceCall, 580 mShouldSkipCallLog, 581 mShouldSkipNotification, 582 mShouldScreenCallViaAudioProcessing, 583 mCallComposerAttachmentsToShow); 584 } 585 } 586 } 587 CallScreeningService()588 public CallScreeningService() { 589 } 590 591 @Override onBind(Intent intent)592 public IBinder onBind(Intent intent) { 593 Log.v(this, "onBind"); 594 return new CallScreeningBinder(); 595 } 596 597 @Override onUnbind(Intent intent)598 public boolean onUnbind(Intent intent) { 599 Log.v(this, "onUnbind"); 600 return false; 601 } 602 603 /** 604 * Called when a new incoming or outgoing call is added. 605 * <p> 606 * A {@link CallScreeningService} must indicate whether an incoming call is allowed or not by 607 * calling 608 * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}. 609 * Your app can tell if a call is an incoming call by checking to see if 610 * {@link Call.Details#getCallDirection()} is {@link Call.Details#DIRECTION_INCOMING}. 611 * <p> 612 * <em>Note:</em> A {@link CallScreeningService} must respond to a call within 5 seconds. After 613 * this time, the framework will unbind from the {@link CallScreeningService} and ignore its 614 * response. 615 * <p> 616 * <em>Note:</em> The {@link Call.Details} instance provided to a call screening service will 617 * only have the following properties set. The rest of the {@link Call.Details} properties will 618 * be set to their default value or {@code null}. 619 * <ul> 620 * <li>{@link Call.Details#getCallDirection()}</li> 621 * <li>{@link Call.Details#getCallerNumberVerificationStatus()}</li> 622 * <li>{@link Call.Details#getConnectTimeMillis()}</li> 623 * <li>{@link Call.Details#getCreationTimeMillis()}</li> 624 * <li>{@link Call.Details#getHandle()}</li> 625 * </ul> 626 * <p> 627 * Only calls where the {@link Call.Details#getHandle() handle} {@link Uri#getScheme() scheme} 628 * is {@link PhoneAccount#SCHEME_TEL} are passed for call 629 * screening. Further, only calls which are not in the user's contacts are passed for 630 * screening, unless the {@link CallScreeningService} has been granted 631 * {@link Manifest.permission#READ_CONTACTS} permission by the user. For outgoing calls, no 632 * post-dial digits are passed. 633 * <p> 634 * Calls with a {@link Call.Details#getHandlePresentation()} of 635 * {@link TelecomManager#PRESENTATION_RESTRICTED}, {@link TelecomManager#PRESENTATION_UNKNOWN} 636 * or {@link TelecomManager#PRESENTATION_PAYPHONE} presentation are not provided to the 637 * {@link CallScreeningService}. 638 * 639 * @param callDetails Information about a new call, see {@link Call.Details}. 640 */ onScreenCall(@onNull Call.Details callDetails)641 public abstract void onScreenCall(@NonNull Call.Details callDetails); 642 643 /** 644 * Responds to the given incoming call, either allowing it, silencing it or disallowing it. 645 * <p> 646 * The {@link CallScreeningService} calls this method to inform the system whether the call 647 * should be silently blocked or not. In the event that it should not be blocked, it may 648 * also be requested to ring silently. 649 * <p> 650 * Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is 651 * {@link Call.Details#DIRECTION_INCOMING}. 652 * <p> 653 * For incoming calls, a {@link CallScreeningService} MUST call this method within 5 seconds of 654 * {@link #onScreenCall(Call.Details)} being invoked by the platform. 655 * <p> 656 * Calls which are blocked/rejected will be logged to the system call log with a call type of 657 * {@link android.provider.CallLog.Calls#BLOCKED_TYPE} and 658 * {@link android.provider.CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE} block reason. 659 * 660 * @param callDetails The call to allow. 661 * <p> 662 * Must be the same {@link Call.Details call} which was provided to the 663 * {@link CallScreeningService} via {@link #onScreenCall(Call.Details)}. 664 * @param response The {@link CallScreeningService.CallResponse} which contains information 665 * about how to respond to a call. 666 */ respondToCall(@onNull Call.Details callDetails, @NonNull CallResponse response)667 public final void respondToCall(@NonNull Call.Details callDetails, 668 @NonNull CallResponse response) { 669 try { 670 mCallScreeningAdapter.onScreeningResponse( 671 callDetails.getTelecomCallId(), 672 new ComponentName(getPackageName(), getClass().getName()), 673 response.toParcelable()); 674 } catch (RemoteException e) { 675 Log.e(this, e, "Got remote exception when returning response"); 676 } 677 } 678 } 679