• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * &#64;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