blob: b7f59e113372b3b28b95a3a25191530a80aec786 [file] [log] [blame]
Sailesh Nepal1bef3392016-01-24 18:21:53 -08001/*
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
17package android.telecom;
18
Hall Liuff4a1252020-01-01 16:27:14 -080019import android.Manifest;
Tyler Gunn7e45b722018-12-04 12:56:45 -080020import android.annotation.NonNull;
Hall Liuff4a1252020-01-01 16:27:14 -080021import android.annotation.RequiresPermission;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080022import android.annotation.SdkConstant;
Hall Liu6dfa2492019-10-01 17:20:39 -070023import android.annotation.SystemApi;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080024import android.app.Service;
tonyzhu9e1d4f82018-10-22 15:11:31 +080025import android.content.ComponentName;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080026import android.content.Intent;
Tyler Gunn460b7d42020-05-15 10:19:32 -070027import android.content.pm.ServiceInfo;
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080028import android.net.Uri;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080029import android.os.Handler;
30import android.os.IBinder;
31import android.os.Looper;
32import android.os.Message;
Hall Liu5efe9972021-02-04 13:09:45 -080033import android.os.Parcel;
34import android.os.Parcelable;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080035import android.os.RemoteException;
36
37import com.android.internal.os.SomeArgs;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080038import com.android.internal.telecom.ICallScreeningAdapter;
Tyler Gunne0caec72018-11-30 14:21:18 -080039import com.android.internal.telecom.ICallScreeningService;
Sailesh Nepal1bef3392016-01-24 18:21:53 -080040
Hall Liu5efe9972021-02-04 13:09:45 -080041import java.util.Objects;
42
Sailesh Nepal1bef3392016-01-24 18:21:53 -080043/**
44 * This service can be implemented by the default dialer (see
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080045 * {@link TelecomManager#getDefaultDialerPackage()}) or a third party app to allow or disallow
Tyler Gunna842e7622019-03-29 11:32:08 -070046 * incoming calls before they are shown to a user. A {@link CallScreeningService} can also see
47 * outgoing calls for the purpose of providing caller ID services for those calls.
Sailesh Nepal1bef3392016-01-24 18:21:53 -080048 * <p>
49 * Below is an example manifest registration for a {@code CallScreeningService}.
50 * <pre>
51 * {@code
52 * <service android:name="your.package.YourCallScreeningServiceImplementation"
53 * android:permission="android.permission.BIND_SCREENING_SERVICE">
54 * <intent-filter>
55 * <action android:name="android.telecom.CallScreeningService"/>
56 * </intent-filter>
57 * </service>
58 * }
59 * </pre>
Tyler Gunn7e45b722018-12-04 12:56:45 -080060 * <p>
61 * A CallScreeningService performs two functions:
62 * <ol>
63 * <li>Call blocking/screening - the service can choose which calls will ring on the user's
64 * device, and which will be silently sent to voicemail.</li>
Tyler Gunna842e7622019-03-29 11:32:08 -070065 * <li>Call identification - services which provide call identification functionality can
66 * display a user-interface of their choosing which contains identifying information for a call.
67 * </li>
Tyler Gunn7e45b722018-12-04 12:56:45 -080068 * </ol>
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080069 * <p>
Tyler Gunn467acc42020-10-07 15:42:06 -070070 * <h2>Becoming the CallScreeningService</h2>
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080071 * Telecom will bind to a single app chosen by the user which implements the
72 * {@link CallScreeningService} API when there are new incoming and outgoing calls.
73 * <p>
74 * The code snippet below illustrates how your app can request that it fills the call screening
75 * role.
76 * <pre>
77 * {@code
78 * private static final int REQUEST_ID = 1;
79 *
80 * public void requestRole() {
81 * RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
Grace Jia2d21e952019-09-20 14:57:00 -070082 * Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080083 * startActivityForResult(intent, REQUEST_ID);
84 * }
85 *
86 * &#64;Override
87 * public void onActivityResult(int requestCode, int resultCode, Intent data) {
88 * if (requestCode == REQUEST_ID) {
89 * if (resultCode == android.app.Activity.RESULT_OK) {
90 * // Your app is now the call screening app
91 * } else {
92 * // Your app is not the call screening app
93 * }
94 * }
95 * }
Tyler Gunn467acc42020-10-07 15:42:06 -070096 * }
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -080097 * </pre>
Tyler Gunn467acc42020-10-07 15:42:06 -070098 *
99 * <h2>CallScreeningService Lifecycle</h2>
100 *
101 * The framework binds to the {@link CallScreeningService} implemented by the user-chosen app
102 * filling the {@link android.app.role.RoleManager#ROLE_CALL_SCREENING} role when incoming calls are
103 * received (prior to ringing) and when outgoing calls are placed. The platform calls the
104 * {@link #onScreenCall(Call.Details)} method to provide your service with details about the call.
105 * <p>
106 * For incoming calls, the {@link CallScreeningService} must call
107 * {@link #respondToCall(Call.Details, CallResponse)} within 5 seconds of being bound to indicate to
108 * the platform whether the call should be blocked or not. Your app must do this even if it is
109 * primarily performing caller ID operations and not screening calls. It is important to perform
110 * screening operations in a timely matter as the user's device will not begin ringing until the
111 * response is received (or the timeout is hit). A {@link CallScreeningService} may choose to
112 * perform local database lookups to help determine if a call should be screened or not; care should
113 * be taken to ensure the timeout is not repeatedly hit, causing delays in the incoming call flow.
114 * <p>
115 * If your app provides a caller ID experience, it should launch an activity to show the caller ID
116 * information from {@link #onScreenCall(Call.Details)}.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800117 */
118public abstract class CallScreeningService extends Service {
119 /**
120 * The {@link Intent} that must be declared as handled by the service.
121 */
122 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
123 public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
124
125 private static final int MSG_SCREEN_CALL = 1;
126
127 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
128 @Override
129 public void handleMessage(Message msg) {
130 switch (msg.what) {
131 case MSG_SCREEN_CALL:
132 SomeArgs args = (SomeArgs) msg.obj;
133 try {
134 mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1;
Grace Jia90b38042019-11-06 14:12:33 -0800135 Call.Details callDetails = Call.Details
136 .createFromParcelableCall((ParcelableCall) args.arg2);
137 onScreenCall(callDetails);
138 if (callDetails.getCallDirection() == Call.Details.DIRECTION_OUTGOING) {
Hall Liu5efe9972021-02-04 13:09:45 -0800139 mCallScreeningAdapter.onScreeningResponse(
140 callDetails.getTelecomCallId(),
141 new ComponentName(getPackageName(), getClass().getName()),
142 null);
Grace Jia90b38042019-11-06 14:12:33 -0800143 }
144 } catch (RemoteException e) {
145 Log.w(this, "Exception when screening call: " + e);
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800146 } finally {
147 args.recycle();
148 }
149 break;
150 }
151 }
152 };
153
154 private final class CallScreeningBinder extends ICallScreeningService.Stub {
155 @Override
156 public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) {
157 Log.v(this, "screenCall");
158 SomeArgs args = SomeArgs.obtain();
159 args.arg1 = adapter;
160 args.arg2 = call;
161 mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget();
162 }
163 }
164
165 private ICallScreeningAdapter mCallScreeningAdapter;
166
Hall Liu5efe9972021-02-04 13:09:45 -0800167 /**
168 * Parcelable version of {@link CallResponse} used to do IPC.
169 * @hide
170 */
171 public static class ParcelableCallResponse implements Parcelable {
172 private final boolean mShouldDisallowCall;
173 private final boolean mShouldRejectCall;
174 private final boolean mShouldSilenceCall;
175 private final boolean mShouldSkipCallLog;
176 private final boolean mShouldSkipNotification;
177 private final boolean mShouldScreenCallViaAudioProcessing;
178
179 private ParcelableCallResponse(
180 boolean shouldDisallowCall,
181 boolean shouldRejectCall,
182 boolean shouldSilenceCall,
183 boolean shouldSkipCallLog,
184 boolean shouldSkipNotification,
185 boolean shouldScreenCallViaAudioProcessing) {
186 mShouldDisallowCall = shouldDisallowCall;
187 mShouldRejectCall = shouldRejectCall;
188 mShouldSilenceCall = shouldSilenceCall;
189 mShouldSkipCallLog = shouldSkipCallLog;
190 mShouldSkipNotification = shouldSkipNotification;
191 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
192 }
193
194 protected ParcelableCallResponse(Parcel in) {
195 mShouldDisallowCall = in.readBoolean();
196 mShouldRejectCall = in.readBoolean();
197 mShouldSilenceCall = in.readBoolean();
198 mShouldSkipCallLog = in.readBoolean();
199 mShouldSkipNotification = in.readBoolean();
200 mShouldScreenCallViaAudioProcessing = in.readBoolean();
201 }
202
203 public CallResponse toCallResponse() {
204 return new CallResponse.Builder()
205 .setDisallowCall(mShouldDisallowCall)
206 .setRejectCall(mShouldRejectCall)
207 .setSilenceCall(mShouldSilenceCall)
208 .setSkipCallLog(mShouldSkipCallLog)
209 .setSkipNotification(mShouldSkipNotification)
210 .setShouldScreenCallViaAudioProcessing(mShouldScreenCallViaAudioProcessing)
211 .build();
212 }
213
214 public boolean shouldDisallowCall() {
215 return mShouldDisallowCall;
216 }
217
218 public boolean shouldRejectCall() {
219 return mShouldRejectCall;
220 }
221
222 public boolean shouldSilenceCall() {
223 return mShouldSilenceCall;
224 }
225
226 public boolean shouldSkipCallLog() {
227 return mShouldSkipCallLog;
228 }
229
230 public boolean shouldSkipNotification() {
231 return mShouldSkipNotification;
232 }
233
234 public boolean shouldScreenCallViaAudioProcessing() {
235 return mShouldScreenCallViaAudioProcessing;
236 }
237
238 public static final Creator<ParcelableCallResponse> CREATOR =
239 new Creator<ParcelableCallResponse>() {
240 @Override
241 public ParcelableCallResponse createFromParcel(Parcel in) {
242 return new ParcelableCallResponse(in);
243 }
244
245 @Override
246 public ParcelableCallResponse[] newArray(int size) {
247 return new ParcelableCallResponse[size];
248 }
249 };
250
251 @Override
252 public int describeContents() {
253 return 0;
254 }
255
256 @Override
257 public void writeToParcel(Parcel dest, int flags) {
258 dest.writeBoolean(mShouldDisallowCall);
259 dest.writeBoolean(mShouldRejectCall);
260 dest.writeBoolean(mShouldSilenceCall);
261 dest.writeBoolean(mShouldSkipCallLog);
262 dest.writeBoolean(mShouldSkipNotification);
263 dest.writeBoolean(mShouldScreenCallViaAudioProcessing);
264 }
265 }
266
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800267 /*
268 * Information about how to respond to an incoming call.
269 */
Sailesh Nepalf4460712016-01-27 16:45:51 -0800270 public static class CallResponse {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800271 private final boolean mShouldDisallowCall;
272 private final boolean mShouldRejectCall;
Usman Abdullah47b392d2019-03-06 15:54:56 -0800273 private final boolean mShouldSilenceCall;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800274 private final boolean mShouldSkipCallLog;
275 private final boolean mShouldSkipNotification;
Hall Liu69554cf2019-11-11 17:44:09 -0800276 private final boolean mShouldScreenCallViaAudioProcessing;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800277
278 private CallResponse(
279 boolean shouldDisallowCall,
280 boolean shouldRejectCall,
Usman Abdullah47b392d2019-03-06 15:54:56 -0800281 boolean shouldSilenceCall,
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800282 boolean shouldSkipCallLog,
Hall Liu6dfa2492019-10-01 17:20:39 -0700283 boolean shouldSkipNotification,
Hall Liu69554cf2019-11-11 17:44:09 -0800284 boolean shouldScreenCallViaAudioProcessing) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800285 if (!shouldDisallowCall
286 && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
287 throw new IllegalStateException("Invalid response state for allowed call.");
288 }
289
Hall Liu69554cf2019-11-11 17:44:09 -0800290 if (shouldDisallowCall && shouldScreenCallViaAudioProcessing) {
Hall Liu6dfa2492019-10-01 17:20:39 -0700291 throw new IllegalStateException("Invalid response state for allowed call.");
292 }
293
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800294 mShouldDisallowCall = shouldDisallowCall;
295 mShouldRejectCall = shouldRejectCall;
296 mShouldSkipCallLog = shouldSkipCallLog;
297 mShouldSkipNotification = shouldSkipNotification;
Usman Abdullah47b392d2019-03-06 15:54:56 -0800298 mShouldSilenceCall = shouldSilenceCall;
Hall Liu69554cf2019-11-11 17:44:09 -0800299 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800300 }
301
302 /*
303 * @return Whether the incoming call should be blocked.
304 */
305 public boolean getDisallowCall() {
306 return mShouldDisallowCall;
307 }
308
309 /*
310 * @return Whether the incoming call should be disconnected as if the user had manually
311 * rejected it.
312 */
313 public boolean getRejectCall() {
314 return mShouldRejectCall;
315 }
316
317 /*
Usman Abdullah47b392d2019-03-06 15:54:56 -0800318 * @return Whether the ringtone should be silenced for the incoming call.
319 */
320 public boolean getSilenceCall() {
321 return mShouldSilenceCall;
322 }
323
324 /*
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800325 * @return Whether the incoming call should not be displayed in the call log.
326 */
327 public boolean getSkipCallLog() {
328 return mShouldSkipCallLog;
329 }
330
331 /*
332 * @return Whether a missed call notification should not be shown for the incoming call.
333 */
334 public boolean getSkipNotification() {
335 return mShouldSkipNotification;
336 }
337
Hall Liu6dfa2492019-10-01 17:20:39 -0700338 /**
339 * @return Whether we should enter the {@link Call#STATE_AUDIO_PROCESSING} state to allow
340 * for further screening of the call.
341 * @hide
342 */
Hall Liu69554cf2019-11-11 17:44:09 -0800343 public boolean getShouldScreenCallViaAudioProcessing() {
344 return mShouldScreenCallViaAudioProcessing;
Hall Liu6dfa2492019-10-01 17:20:39 -0700345 }
346
Hall Liu5efe9972021-02-04 13:09:45 -0800347 /** @hide */
348 public ParcelableCallResponse toParcelable() {
349 return new ParcelableCallResponse(
350 mShouldDisallowCall,
351 mShouldRejectCall,
352 mShouldSilenceCall,
353 mShouldSkipCallLog,
354 mShouldSkipNotification,
355 mShouldScreenCallViaAudioProcessing
356 );
357 }
358
359 @Override
360 public boolean equals(Object o) {
361 if (this == o) return true;
362 if (o == null || getClass() != o.getClass()) return false;
363 CallResponse that = (CallResponse) o;
364 return mShouldDisallowCall == that.mShouldDisallowCall &&
365 mShouldRejectCall == that.mShouldRejectCall &&
366 mShouldSilenceCall == that.mShouldSilenceCall &&
367 mShouldSkipCallLog == that.mShouldSkipCallLog &&
368 mShouldSkipNotification == that.mShouldSkipNotification &&
369 mShouldScreenCallViaAudioProcessing == that.mShouldScreenCallViaAudioProcessing;
370 }
371
372 @Override
373 public int hashCode() {
374 return Objects.hash(mShouldDisallowCall, mShouldRejectCall, mShouldSilenceCall,
375 mShouldSkipCallLog, mShouldSkipNotification,
376 mShouldScreenCallViaAudioProcessing);
377 }
378
Sailesh Nepalf4460712016-01-27 16:45:51 -0800379 public static class Builder {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800380 private boolean mShouldDisallowCall;
381 private boolean mShouldRejectCall;
Usman Abdullah47b392d2019-03-06 15:54:56 -0800382 private boolean mShouldSilenceCall;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800383 private boolean mShouldSkipCallLog;
384 private boolean mShouldSkipNotification;
Hall Liu69554cf2019-11-11 17:44:09 -0800385 private boolean mShouldScreenCallViaAudioProcessing;
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800386
Tyler Gunne0caec72018-11-30 14:21:18 -0800387 /**
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800388 * Sets whether the incoming call should be blocked.
389 */
390 public Builder setDisallowCall(boolean shouldDisallowCall) {
391 mShouldDisallowCall = shouldDisallowCall;
392 return this;
393 }
394
Tyler Gunne0caec72018-11-30 14:21:18 -0800395 /**
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800396 * Sets whether the incoming call should be disconnected as if the user had manually
397 * rejected it. This property should only be set to true if the call is disallowed.
398 */
399 public Builder setRejectCall(boolean shouldRejectCall) {
400 mShouldRejectCall = shouldRejectCall;
401 return this;
402 }
403
Tyler Gunne0caec72018-11-30 14:21:18 -0800404 /**
Usman Abdullah47b392d2019-03-06 15:54:56 -0800405 * Sets whether ringing should be silenced for the incoming call. When set
406 * to {@code true}, the Telecom framework will not play a ringtone for the call.
407 * The call will, however, still be sent to the default dialer app if it is not blocked.
408 * A {@link CallScreeningService} can use this to ensure a potential nuisance call is
409 * still surfaced to the user, but in a less intrusive manner.
410 *
411 * Setting this to true only makes sense when the call has not been disallowed
412 * using {@link #setDisallowCall(boolean)}.
413 */
414 public @NonNull Builder setSilenceCall(boolean shouldSilenceCall) {
415 mShouldSilenceCall = shouldSilenceCall;
416 return this;
417 }
418
419 /**
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800420 * Sets whether the incoming call should not be displayed in the call log. This property
421 * should only be set to true if the call is disallowed.
Tyler Gunne0caec72018-11-30 14:21:18 -0800422 * <p>
423 * Note: Calls will still be logged with type
424 * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}, regardless of how this property
425 * is set.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800426 */
427 public Builder setSkipCallLog(boolean shouldSkipCallLog) {
428 mShouldSkipCallLog = shouldSkipCallLog;
429 return this;
430 }
431
Tyler Gunne0caec72018-11-30 14:21:18 -0800432 /**
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800433 * Sets whether a missed call notification should not be shown for the incoming call.
434 * This property should only be set to true if the call is disallowed.
435 */
436 public Builder setSkipNotification(boolean shouldSkipNotification) {
437 mShouldSkipNotification = shouldSkipNotification;
438 return this;
439 }
440
Hall Liu6dfa2492019-10-01 17:20:39 -0700441 /**
442 * Sets whether to request background audio processing so that the in-call service can
443 * screen the call further. If set to {@code true}, {@link #setDisallowCall} should be
444 * called with {@code false}, and all other parameters in this builder will be ignored.
Tyler Gunn460b7d42020-05-15 10:19:32 -0700445 * <p>
Hall Liu6dfa2492019-10-01 17:20:39 -0700446 * This request will only be honored if the {@link CallScreeningService} shares the same
447 * uid as the default dialer app. Otherwise, the call will go through as usual.
Tyler Gunn460b7d42020-05-15 10:19:32 -0700448 * <p>
449 * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which
450 * are using the microphone as part of audio processing should specify the
451 * foreground service type using the attribute
452 * {@link android.R.attr#foregroundServiceType} in the {@link CallScreeningService}
453 * service element of the app's manifest file.
454 * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be
455 * specified.
456 * @see
457 * <a href="https://developer.android.com/preview/privacy/foreground-service-types">
458 * the Android Developer Site</a> for more information.
Hall Liu6dfa2492019-10-01 17:20:39 -0700459 *
Hall Liu69554cf2019-11-11 17:44:09 -0800460 * @param shouldScreenCallViaAudioProcessing Whether to request further call screening.
Hall Liu6dfa2492019-10-01 17:20:39 -0700461 * @hide
462 */
463 @SystemApi
Hall Liuff4a1252020-01-01 16:27:14 -0800464 @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
Hall Liu69554cf2019-11-11 17:44:09 -0800465 public @NonNull Builder setShouldScreenCallViaAudioProcessing(
466 boolean shouldScreenCallViaAudioProcessing) {
467 mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
Hall Liu6dfa2492019-10-01 17:20:39 -0700468 return this;
469 }
470
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800471 public CallResponse build() {
472 return new CallResponse(
473 mShouldDisallowCall,
474 mShouldRejectCall,
Usman Abdullah47b392d2019-03-06 15:54:56 -0800475 mShouldSilenceCall,
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800476 mShouldSkipCallLog,
Hall Liu6dfa2492019-10-01 17:20:39 -0700477 mShouldSkipNotification,
Hall Liu69554cf2019-11-11 17:44:09 -0800478 mShouldScreenCallViaAudioProcessing);
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800479 }
480 }
481 }
482
483 public CallScreeningService() {
484 }
485
486 @Override
487 public IBinder onBind(Intent intent) {
488 Log.v(this, "onBind");
489 return new CallScreeningBinder();
490 }
491
492 @Override
493 public boolean onUnbind(Intent intent) {
494 Log.v(this, "onUnbind");
495 return false;
496 }
497
498 /**
Tyler Gunn467acc42020-10-07 15:42:06 -0700499 * Called when a new incoming or outgoing call is added.
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800500 * <p>
501 * A {@link CallScreeningService} must indicate whether an incoming call is allowed or not by
502 * calling
503 * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}.
504 * Your app can tell if a call is an incoming call by checking to see if
505 * {@link Call.Details#getCallDirection()} is {@link Call.Details#DIRECTION_INCOMING}.
506 * <p>
Tyler Gunn467acc42020-10-07 15:42:06 -0700507 * <em>Note:</em> A {@link CallScreeningService} must respond to a call within 5 seconds. After
508 * this time, the framework will unbind from the {@link CallScreeningService} and ignore its
509 * response.
510 * <p>
511 * <em>Note:</em> The {@link Call.Details} instance provided to a call screening service will
512 * only have the following properties set. The rest of the {@link Call.Details} properties will
513 * be set to their default value or {@code null}.
Tyler Gunne0caec72018-11-30 14:21:18 -0800514 * <ul>
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800515 * <li>{@link Call.Details#getCallDirection()}</li>
Tyler Gunn467acc42020-10-07 15:42:06 -0700516 * <li>{@link Call.Details#getCallerNumberVerificationStatus()}</li>
Tyler Gunne0caec72018-11-30 14:21:18 -0800517 * <li>{@link Call.Details#getConnectTimeMillis()}</li>
518 * <li>{@link Call.Details#getCreationTimeMillis()}</li>
519 * <li>{@link Call.Details#getHandle()}</li>
Tyler Gunne0caec72018-11-30 14:21:18 -0800520 * </ul>
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800521 * <p>
522 * Only calls where the {@link Call.Details#getHandle() handle} {@link Uri#getScheme() scheme}
523 * is {@link PhoneAccount#SCHEME_TEL} are passed for call
524 * screening. Further, only calls which are not in the user's contacts are passed for
Tyler Gunn467acc42020-10-07 15:42:06 -0700525 * screening, unless the {@link CallScreeningService} has been granted
526 * {@link Manifest.permission#READ_CONTACTS} permission by the user. For outgoing calls, no
527 * post-dial digits are passed.
528 * <p>
529 * Calls with a {@link Call.Details#getHandlePresentation()} of
530 * {@link TelecomManager#PRESENTATION_RESTRICTED}, {@link TelecomManager#PRESENTATION_UNKNOWN}
531 * or {@link TelecomManager#PRESENTATION_PAYPHONE} presentation are not provided to the
532 * {@link CallScreeningService}.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800533 *
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800534 * @param callDetails Information about a new call, see {@link Call.Details}.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800535 */
Tyler Gunn7e45b722018-12-04 12:56:45 -0800536 public abstract void onScreenCall(@NonNull Call.Details callDetails);
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800537
538 /**
Usman Abdullah47b392d2019-03-06 15:54:56 -0800539 * Responds to the given incoming call, either allowing it, silencing it or disallowing it.
Tyler Gunn7e45b722018-12-04 12:56:45 -0800540 * <p>
541 * The {@link CallScreeningService} calls this method to inform the system whether the call
Usman Abdullah47b392d2019-03-06 15:54:56 -0800542 * should be silently blocked or not. In the event that it should not be blocked, it may
543 * also be requested to ring silently.
Tyler Gunn9e76fd19b2018-12-17 09:56:11 -0800544 * <p>
545 * Calls to this method are ignored unless the {@link Call.Details#getCallDirection()} is
546 * {@link Call.Details#DIRECTION_INCOMING}.
Tyler Gunn467acc42020-10-07 15:42:06 -0700547 * <p>
548 * For incoming calls, a {@link CallScreeningService} MUST call this method within 5 seconds of
549 * {@link #onScreenCall(Call.Details)} being invoked by the platform.
550 * <p>
551 * Calls which are blocked/rejected will be logged to the system call log with a call type of
552 * {@link android.provider.CallLog.Calls#BLOCKED_TYPE} and
553 * {@link android.provider.CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE} block reason.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800554 *
555 * @param callDetails The call to allow.
Tyler Gunn7e45b722018-12-04 12:56:45 -0800556 * <p>
557 * Must be the same {@link Call.Details call} which was provided to the
558 * {@link CallScreeningService} via {@link #onScreenCall(Call.Details)}.
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800559 * @param response The {@link CallScreeningService.CallResponse} which contains information
560 * about how to respond to a call.
561 */
Tyler Gunn7e45b722018-12-04 12:56:45 -0800562 public final void respondToCall(@NonNull Call.Details callDetails,
563 @NonNull CallResponse response) {
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800564 try {
Hall Liu5efe9972021-02-04 13:09:45 -0800565 mCallScreeningAdapter.onScreeningResponse(
566 callDetails.getTelecomCallId(),
567 new ComponentName(getPackageName(), getClass().getName()),
568 response.toParcelable());
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800569 } catch (RemoteException e) {
Hall Liu5efe9972021-02-04 13:09:45 -0800570 Log.e(this, e, "Got remote exception when returning response");
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800571 }
572 }
Sailesh Nepal1bef3392016-01-24 18:21:53 -0800573}