1 /*
2  * Copyright (C) 2013 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.annotation.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.annotation.SdkConstant;
22 import android.annotation.SystemApi;
23 import android.app.Service;
24 import android.app.UiModeManager;
25 import android.bluetooth.BluetoothDevice;
26 import android.content.ComponentName;
27 import android.content.Intent;
28 import android.hardware.camera2.CameraManager;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.IBinder;
33 import android.os.Looper;
34 import android.os.Message;
35 import android.os.OutcomeReceiver;
36 import android.view.Surface;
37 
38 import com.android.internal.os.SomeArgs;
39 import com.android.internal.telecom.IInCallAdapter;
40 import com.android.internal.telecom.IInCallService;
41 
42 import java.util.Collections;
43 import java.util.List;
44 import java.util.Objects;
45 import java.util.concurrent.Executor;
46 
47 /**
48  * This service is implemented by an app that wishes to provide functionality for managing
49  * phone calls.
50  * <h2>Becoming the Default Phone App</h2>
51  * The default dialer/phone app is one which provides the in-call user interface while the device is
52  * in a call.  It also provides the user with a means to initiate calls and see a history of calls
53  * on their device.  A device is bundled with a system provided default dialer/phone app.  The user
54  * may choose a single app to take over this role from the system app.  An app which wishes to
55  * fulfill this role uses the {@link android.app.role.RoleManager} to request that they fill the
56  * {@link android.app.role.RoleManager#ROLE_DIALER} role.
57  * <p>
58  * The default phone app provides a user interface while the device is in a call, and the device is
59  * not in car mode (i.e. {@link UiModeManager#getCurrentModeType()} is not
60  * {@link android.content.res.Configuration#UI_MODE_TYPE_CAR}).
61  * <p>
62  * In order to fill the {@link android.app.role.RoleManager#ROLE_DIALER} role, an app must meet a
63  * number of requirements:
64  * <ul>
65  *     <li>It must handle the {@link Intent#ACTION_DIAL} intent.  This means the app must provide
66  *     a dial pad UI for the user to initiate outgoing calls.</li>
67  *     <li>It must fully implement the {@link InCallService} API and provide both an incoming call
68  *     UI, as well as an ongoing call UI.</li>
69  * </ul>
70  * <p>
71  * Note: If the app filling the {@link android.app.role.RoleManager#ROLE_DIALER} returns a
72  * {@code null} {@link InCallService} during binding, the Telecom framework will automatically fall
73  * back to using the dialer app preloaded on the device.  The system will display a notification to
74  * the user to let them know that their call was continued using the preloaded dialer app.  Your
75  * app should never return a {@code null} binding; doing so means it does not fulfil the
76  * requirements of {@link android.app.role.RoleManager#ROLE_DIALER}.
77  * <p>
78  * Note: If your app fills {@link android.app.role.RoleManager#ROLE_DIALER} and makes changes at
79  * runtime which cause it to no longer fulfil the requirements of this role,
80  * {@link android.app.role.RoleManager} will automatically remove your app from the role and close
81  * your app.  For example, if you use
82  * {@link android.content.pm.PackageManager#setComponentEnabledSetting(ComponentName, int, int)} to
83  * programmatically disable the {@link InCallService} your app declares in its manifest, your app
84  * will no longer fulfil the requirements expected of
85  * {@link android.app.role.RoleManager#ROLE_DIALER}.
86  * <p>
87  * The preloaded dialer will ALWAYS be used when the user places an emergency call, even if your
88  * app fills the {@link android.app.role.RoleManager#ROLE_DIALER} role.  To ensure an optimal
89  * experience when placing an emergency call, the default dialer should ALWAYS use
90  * {@link android.telecom.TelecomManager#placeCall(Uri, Bundle)} to place calls (including
91  * emergency calls).  This ensures that the platform is able to verify that the request came from
92  * the default dialer.  If a non-preloaded dialer app uses {@link Intent#ACTION_CALL} to place an
93  * emergency call, it will be raised to the preloaded dialer app using {@link Intent#ACTION_DIAL}
94  * for confirmation; this is a suboptimal user experience.
95  * <p>
96  * Below is an example manifest registration for an {@code InCallService}. The meta-data
97  * {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} indicates that this particular
98  * {@code InCallService} implementation intends to replace the built-in in-call UI.
99  * The meta-data {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} indicates that this
100  * {@link InCallService} will play the ringtone for incoming calls.  See
101  * <a href="#incomingCallNotification">below</a> for more information on showing the incoming call
102  * UI and playing the ringtone in your app.
103  * <pre>
104  * {@code
105  * <service android:name="your.package.YourInCallServiceImplementation"
106  *          android:permission="android.permission.BIND_INCALL_SERVICE"
107  *          android:exported="true">
108  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
109  *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING"
110  *          android:value="true" />
111  *      <intent-filter>
112  *          <action android:name="android.telecom.InCallService"/>
113  *      </intent-filter>
114  * </service>
115  * }
116  * </pre>
117  *
118  * <em>Note: You should NOT mark your {@link InCallService} with the attribute
119  * {@code android:exported="false"}; doing so can result in a failure to bind to your implementation
120  * during calls.</em>
121  * <p>
122  * In addition to implementing the {@link InCallService} API, you must also declare an activity in
123  * your manifest which handles the {@link Intent#ACTION_DIAL} intent.  The example below illustrates
124  * how this is done:
125  * <pre>
126  * {@code
127  * <activity android:name="your.package.YourDialerActivity"
128  *           android:label="@string/yourDialerActivityLabel">
129  *      <intent-filter>
130  *           <action android:name="android.intent.action.DIAL" />
131  *           <category android:name="android.intent.category.DEFAULT" />
132  *      </intent-filter>
133  *      <intent-filter>
134  *           <action android:name="android.intent.action.DIAL" />
135  *           <category android:name="android.intent.category.DEFAULT" />
136  *           <data android:scheme="tel" />
137  *      </intent-filter>
138  * </activity>
139  * }
140  * </pre>
141  * <p>
142  * When a user installs your application and runs it for the first time, you should use the
143  * {@link android.app.role.RoleManager} to prompt the user to see if they would like your app to
144  * be the new default phone app.
145  * <p id="requestRole">
146  * The code below shows how your app can request to become the default phone/dialer app:
147  * <pre>
148  * {@code
149  * private static final int REQUEST_ID = 1;
150  *
151  * public void requestRole() {
152  *     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
153  *     Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER);
154  *     startActivityForResult(intent, REQUEST_ID);
155  * }
156  *
157  * &#64;Override
158  * public void onActivityResult(int requestCode, int resultCode, Intent data) {
159  *     if (requestCode == REQUEST_ID) {
160  *         if (resultCode == android.app.Activity.RESULT_OK) {
161  *             // Your app is now the default dialer app
162  *         } else {
163  *             // Your app is not the default dialer app
164  *         }
165  *     }
166  * }
167  * }
168  *
169  * </pre>
170  * <p id="companionInCallService">
171  * <h3>Access to InCallService for Wearable Devices</h3>
172  * <ol>
173  * If your app is a third-party companion app and wants to access InCallService APIs, what your
174  * app could do are:
175  * <p>
176  *   <ol>
177  *     <li> Declare MANAGE_ONGOING_CALLS permission in your manifest
178  *     <li> Associate with a physical wearable device via the
179  *          {@link android.companion.CompanionDeviceManager} API as a companion app. See:
180  *          https://developer.android.com/guide/topics/connectivity/companion-device-pairing
181  *     <li> Implement this InCallService with BIND_INCALL_SERVICE permission
182  *   </ol>
183  * </ol>
184  * <p>
185  *
186  * </pre>
187  * <p id="incomingCallNotification">
188  * <h3>Showing the Incoming Call Notification</h3>
189  * When your app receives a new incoming call via {@link InCallService#onCallAdded(Call)}, it is
190  * responsible for displaying an incoming call UI for the incoming call.  It should do this using
191  * {@link android.app.NotificationManager} APIs to post a new incoming call notification.
192  * <p>
193  * Where your app declares the meta-data {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING}, it
194  * is responsible for playing the ringtone for incoming calls.  Your app should create a
195  * {@link android.app.NotificationChannel} which specifies the desired ringtone.  For example:
196  * <pre><code>
197  * NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls",
198  *          NotificationManager.IMPORTANCE_MAX);
199  * // other channel setup stuff goes here.
200  *
201  * // We'll use the default system ringtone for our incoming call notification channel.  You can
202  * // use your own audio resource here.
203  * Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
204  * channel.setSound(ringtoneUri, new AudioAttributes.Builder()
205  *          // Setting the AudioAttributes is important as it identifies the purpose of your
206  *          // notification sound.
207  *          .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
208  *          .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
209  *      .build());
210  *
211  * NotificationManager mgr = getSystemService(NotificationManager.class);
212  * mgr.createNotificationChannel(channel);
213  * </code></pre>
214  * <p>
215  * When your app receives a new incoming call, it creates a {@link android.app.Notification} for the
216  * incoming call and associates it with your incoming call notification channel. You can specify a
217  * {@link android.app.PendingIntent} on the notification which will launch your full screen
218  * incoming call UI.  The notification manager framework will display your notification as a
219  * heads-up notification if the user is actively using the phone.  When the user is not using the
220  * phone, your full-screen incoming call UI is used instead.
221  * For example:
222  * <pre><code>{@code
223  * // Create an intent which triggers your fullscreen incoming call user interface.
224  * Intent intent = new Intent(Intent.ACTION_MAIN, null);
225  * intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
226  * intent.setClass(context, YourIncomingCallActivity.class);
227  * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
228  *
229  * // Build the notification as an ongoing high priority item; this ensures it will show as
230  * // a heads up notification which slides down over top of the current content.
231  * final Notification.Builder builder = new Notification.Builder(context);
232  * builder.setOngoing(true);
233  * builder.setPriority(Notification.PRIORITY_HIGH);
234  *
235  * // Set notification content intent to take user to the fullscreen UI if user taps on the
236  * // notification body.
237  * builder.setContentIntent(pendingIntent);
238  * // Set full screen intent to trigger display of the fullscreen UI when the notification
239  * // manager deems it appropriate.
240  * builder.setFullScreenIntent(pendingIntent, true);
241  *
242  * // Setup notification content.
243  * builder.setSmallIcon( yourIconResourceId );
244  * builder.setContentTitle("Your notification title");
245  * builder.setContentText("Your notification content.");
246  *
247  * // Use builder.addAction(..) to add buttons to answer or reject the call.
248  *
249  * NotificationManager notificationManager = mContext.getSystemService(
250  *     NotificationManager.class);
251  * notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, builder.build());
252  * }</pre>
253  * <p>
254  */
255 public abstract class InCallService extends Service {
256 
257     /**
258      * The {@link Intent} that must be declared as handled by the service.
259      */
260     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
261     public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
262 
263     private static final int MSG_SET_IN_CALL_ADAPTER = 1;
264     private static final int MSG_ADD_CALL = 2;
265     private static final int MSG_UPDATE_CALL = 3;
266     private static final int MSG_SET_POST_DIAL_WAIT = 4;
267     private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
268     private static final int MSG_BRING_TO_FOREGROUND = 6;
269     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
270     private static final int MSG_SILENCE_RINGER = 8;
271     private static final int MSG_ON_CONNECTION_EVENT = 9;
272     private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10;
273     private static final int MSG_ON_RTT_INITIATION_FAILURE = 11;
274     private static final int MSG_ON_HANDOVER_FAILED = 12;
275     private static final int MSG_ON_HANDOVER_COMPLETE = 13;
276     private static final int MSG_ON_CALL_ENDPOINT_CHANGED = 14;
277     private static final int MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED = 15;
278     private static final int MSG_ON_MUTE_STATE_CHANGED = 16;
279 
280     private CallEndpoint mCallEndpoint;
281 
282     /** Default Handler used to consolidate binder method calls onto a single thread. */
283     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
284         @Override
285         public void handleMessage(Message msg) {
286             if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
287                 return;
288             }
289 
290             switch (msg.what) {
291                 case MSG_SET_IN_CALL_ADAPTER:
292                     if (mPhone != null) {
293                         Log.i(this, "mPhone is already instantiated, ignoring "
294                                 + "request to reset adapter.");
295                         break;
296                     }
297                     String callingPackage = getApplicationContext().getOpPackageName();
298                     mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
299                             getApplicationContext().getApplicationInfo().targetSdkVersion);
300                     mPhone.addListener(mPhoneListener);
301                     onPhoneCreated(mPhone);
302                     break;
303                 case MSG_ADD_CALL:
304                     mPhone.internalAddCall((ParcelableCall) msg.obj);
305                     break;
306                 case MSG_UPDATE_CALL:
307                     mPhone.internalUpdateCall((ParcelableCall) msg.obj);
308                     break;
309                 case MSG_SET_POST_DIAL_WAIT: {
310                     SomeArgs args = (SomeArgs) msg.obj;
311                     try {
312                         String callId = (String) args.arg1;
313                         String remaining = (String) args.arg2;
314                         mPhone.internalSetPostDialWait(callId, remaining);
315                     } finally {
316                         args.recycle();
317                     }
318                     break;
319                 }
320                 case MSG_ON_CALL_AUDIO_STATE_CHANGED:
321                     mPhone.internalCallAudioStateChanged((CallAudioState) msg.obj);
322                     break;
323                 case MSG_BRING_TO_FOREGROUND:
324                     mPhone.internalBringToForeground(msg.arg1 == 1);
325                     break;
326                 case MSG_ON_CAN_ADD_CALL_CHANGED:
327                     mPhone.internalSetCanAddCall(msg.arg1 == 1);
328                     break;
329                 case MSG_SILENCE_RINGER:
330                     mPhone.internalSilenceRinger();
331                     break;
332                 case MSG_ON_CONNECTION_EVENT: {
333                     SomeArgs args = (SomeArgs) msg.obj;
334                     try {
335                         String callId = (String) args.arg1;
336                         String event = (String) args.arg2;
337                         Bundle extras = (Bundle) args.arg3;
338                         mPhone.internalOnConnectionEvent(callId, event, extras);
339                     } finally {
340                         args.recycle();
341                     }
342                     break;
343                 }
344                 case MSG_ON_RTT_UPGRADE_REQUEST: {
345                     String callId = (String) msg.obj;
346                     int requestId = msg.arg1;
347                     mPhone.internalOnRttUpgradeRequest(callId, requestId);
348                     break;
349                 }
350                 case MSG_ON_RTT_INITIATION_FAILURE: {
351                     String callId = (String) msg.obj;
352                     int reason = msg.arg1;
353                     mPhone.internalOnRttInitiationFailure(callId, reason);
354                     break;
355                 }
356                 case MSG_ON_HANDOVER_FAILED: {
357                     String callId = (String) msg.obj;
358                     int error = msg.arg1;
359                     mPhone.internalOnHandoverFailed(callId, error);
360                     break;
361                 }
362                 case MSG_ON_HANDOVER_COMPLETE: {
363                     String callId = (String) msg.obj;
364                     mPhone.internalOnHandoverComplete(callId);
365                     break;
366                 }
367                 case MSG_ON_CALL_ENDPOINT_CHANGED: {
368                     CallEndpoint endpoint = (CallEndpoint) msg.obj;
369                     if (!Objects.equals(mCallEndpoint, endpoint)) {
370                         mCallEndpoint = endpoint;
371                         InCallService.this.onCallEndpointChanged(mCallEndpoint);
372                     }
373                     break;
374                 }
375                 case MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED: {
376                     InCallService.this.onAvailableCallEndpointsChanged(
377                             (List<CallEndpoint>) msg.obj);
378                     break;
379                 }
380                 case MSG_ON_MUTE_STATE_CHANGED: {
381                     InCallService.this.onMuteStateChanged((boolean) msg.obj);
382                     break;
383                 }
384                 default:
385                     break;
386             }
387         }
388     };
389 
390     /** Manages the binder calls so that the implementor does not need to deal with it. */
391     private final class InCallServiceBinder extends IInCallService.Stub {
392         @Override
setInCallAdapter(IInCallAdapter inCallAdapter)393         public void setInCallAdapter(IInCallAdapter inCallAdapter) {
394             mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
395         }
396 
397         @Override
addCall(ParcelableCall call)398         public void addCall(ParcelableCall call) {
399             mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
400         }
401 
402         @Override
updateCall(ParcelableCall call)403         public void updateCall(ParcelableCall call) {
404             mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
405         }
406 
407         @Override
setPostDial(String callId, String remaining)408         public void setPostDial(String callId, String remaining) {
409             // TODO: Unused
410         }
411 
412         @Override
setPostDialWait(String callId, String remaining)413         public void setPostDialWait(String callId, String remaining) {
414             SomeArgs args = SomeArgs.obtain();
415             args.arg1 = callId;
416             args.arg2 = remaining;
417             mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget();
418         }
419 
420         @Override
onCallAudioStateChanged(CallAudioState callAudioState)421         public void onCallAudioStateChanged(CallAudioState callAudioState) {
422             mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget();
423         }
424 
425         @Override
onCallEndpointChanged(CallEndpoint callEndpoint)426         public void onCallEndpointChanged(CallEndpoint callEndpoint) {
427             mHandler.obtainMessage(MSG_ON_CALL_ENDPOINT_CHANGED, callEndpoint).sendToTarget();
428         }
429 
430         @Override
onAvailableCallEndpointsChanged(List<CallEndpoint> availableEndpoints)431         public void onAvailableCallEndpointsChanged(List<CallEndpoint> availableEndpoints) {
432             mHandler.obtainMessage(MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED, availableEndpoints)
433                     .sendToTarget();
434         }
435 
436         @Override
onMuteStateChanged(boolean isMuted)437         public void onMuteStateChanged(boolean isMuted) {
438             mHandler.obtainMessage(MSG_ON_MUTE_STATE_CHANGED, isMuted).sendToTarget();
439         }
440 
441         @Override
bringToForeground(boolean showDialpad)442         public void bringToForeground(boolean showDialpad) {
443             mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
444         }
445 
446         @Override
onCanAddCallChanged(boolean canAddCall)447         public void onCanAddCallChanged(boolean canAddCall) {
448             mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
449                     .sendToTarget();
450         }
451 
452         @Override
silenceRinger()453         public void silenceRinger() {
454             mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
455         }
456 
457         @Override
onConnectionEvent(String callId, String event, Bundle extras)458         public void onConnectionEvent(String callId, String event, Bundle extras) {
459             SomeArgs args = SomeArgs.obtain();
460             args.arg1 = callId;
461             args.arg2 = event;
462             args.arg3 = extras;
463             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
464         }
465 
466         @Override
onRttUpgradeRequest(String callId, int id)467         public void onRttUpgradeRequest(String callId, int id) {
468             mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget();
469         }
470 
471         @Override
onRttInitiationFailure(String callId, int reason)472         public void onRttInitiationFailure(String callId, int reason) {
473             mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget();
474         }
475 
476         @Override
onHandoverFailed(String callId, int error)477         public void onHandoverFailed(String callId, int error) {
478             mHandler.obtainMessage(MSG_ON_HANDOVER_FAILED, error, 0, callId).sendToTarget();
479         }
480 
481         @Override
onHandoverComplete(String callId)482         public void onHandoverComplete(String callId) {
483             mHandler.obtainMessage(MSG_ON_HANDOVER_COMPLETE, callId).sendToTarget();
484         }
485     }
486 
487     private Phone.Listener mPhoneListener = new Phone.Listener() {
488         /** ${inheritDoc} */
489         @Override
490         public void onAudioStateChanged(Phone phone, AudioState audioState) {
491             InCallService.this.onAudioStateChanged(audioState);
492         }
493 
494         public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) {
495             InCallService.this.onCallAudioStateChanged(callAudioState);
496         };
497 
498         /** ${inheritDoc} */
499         @Override
500         public void onBringToForeground(Phone phone, boolean showDialpad) {
501             InCallService.this.onBringToForeground(showDialpad);
502         }
503 
504         /** ${inheritDoc} */
505         @Override
506         public void onCallAdded(Phone phone, Call call) {
507             InCallService.this.onCallAdded(call);
508         }
509 
510         /** ${inheritDoc} */
511         @Override
512         public void onCallRemoved(Phone phone, Call call) {
513             InCallService.this.onCallRemoved(call);
514         }
515 
516         /** ${inheritDoc} */
517         @Override
518         public void onCanAddCallChanged(Phone phone, boolean canAddCall) {
519             InCallService.this.onCanAddCallChanged(canAddCall);
520         }
521 
522         /** ${inheritDoc} */
523         @Override
524         public void onSilenceRinger(Phone phone) {
525             InCallService.this.onSilenceRinger();
526         }
527 
528     };
529 
530     private Phone mPhone;
531 
InCallService()532     public InCallService() {
533     }
534 
535     @Override
onBind(Intent intent)536     public IBinder onBind(Intent intent) {
537         return new InCallServiceBinder();
538     }
539 
540     @Override
onUnbind(Intent intent)541     public boolean onUnbind(Intent intent) {
542         if (mPhone != null) {
543             Phone oldPhone = mPhone;
544             mPhone = null;
545 
546             oldPhone.destroy();
547             // destroy sets all the calls to disconnected if any live ones still exist. Therefore,
548             // it is important to remove the Listener *after* the call to destroy so that
549             // InCallService.on* callbacks are appropriately called.
550             oldPhone.removeListener(mPhoneListener);
551 
552             onPhoneDestroyed(oldPhone);
553         }
554 
555         return false;
556     }
557 
558     /**
559      * Obtain the {@code Phone} associated with this {@code InCallService}.
560      *
561      * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
562      *         if the {@code InCallService} is not in a state where it has an associated
563      *         {@code Phone}.
564      * @hide
565      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
566      */
567     @SystemApi
568     @Deprecated
getPhone()569     public Phone getPhone() {
570         return mPhone;
571     }
572 
573     /**
574      * Obtains the current list of {@code Call}s to be displayed by this in-call service.
575      *
576      * @return A list of the relevant {@code Call}s.
577      */
getCalls()578     public final List<Call> getCalls() {
579         return mPhone == null ? Collections.<Call>emptyList() : mPhone.getCalls();
580     }
581 
582     /**
583      * Returns if the device can support additional calls.
584      *
585      * @return Whether the phone supports adding more calls.
586      */
canAddCall()587     public final boolean canAddCall() {
588         return mPhone == null ? false : mPhone.canAddCall();
589     }
590 
591     /**
592      * Obtains the current phone call audio state.
593      *
594      * @return An object encapsulating the audio state. Returns null if the service is not
595      *         fully initialized.
596      * @deprecated Use {@link #getCallAudioState()} instead.
597      * @hide
598      */
599     @Deprecated
getAudioState()600     public final AudioState getAudioState() {
601         return mPhone == null ? null : mPhone.getAudioState();
602     }
603 
604     /**
605      * Obtains the current phone call audio state.
606      *
607      * @return An object encapsulating the audio state. Returns null if the service is not
608      *         fully initialized.
609      * @deprecated Use {@link #getCurrentCallEndpoint()},
610      * {@link #onAvailableCallEndpointsChanged(List)} and
611      * {@link #onMuteStateChanged(boolean)} instead.
612      */
613     @Deprecated
getCallAudioState()614     public final CallAudioState getCallAudioState() {
615         return mPhone == null ? null : mPhone.getCallAudioState();
616     }
617 
618     /**
619      * Sets the microphone mute state. When this request is honored, there will be change to
620      * the {@link #getCallAudioState()}.
621      *
622      * @param state {@code true} if the microphone should be muted; {@code false} otherwise.
623      */
setMuted(boolean state)624     public final void setMuted(boolean state) {
625         if (mPhone != null) {
626             mPhone.setMuted(state);
627         }
628     }
629 
630     /**
631      * Sets the audio route (speaker, bluetooth, etc...).  When this request is honored, there will
632      * be change to the {@link #getCallAudioState()}.
633      *
634      * @param route The audio route to use.
635      * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
636      * instead.
637      */
638     @Deprecated
setAudioRoute(int route)639     public final void setAudioRoute(int route) {
640         if (mPhone != null) {
641             mPhone.setAudioRoute(route);
642         }
643     }
644 
645     /**
646      * Request audio routing to a specific bluetooth device. Calling this method may result in
647      * the device routing audio to a different bluetooth device than the one specified if the
648      * bluetooth stack is unable to route audio to the requested device.
649      * A list of available devices can be obtained via
650      * {@link CallAudioState#getSupportedBluetoothDevices()}
651      *
652      * @param bluetoothDevice The bluetooth device to connect to.
653      * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
654      * instead.
655      */
656     @Deprecated
requestBluetoothAudio(@onNull BluetoothDevice bluetoothDevice)657     public final void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) {
658         if (mPhone != null) {
659             mPhone.requestBluetoothAudio(bluetoothDevice.getAddress());
660         }
661     }
662 
663     /**
664      * Request audio routing to a specific CallEndpoint. Clients should not define their own
665      * CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid
666      * endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}.
667      * When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}.
668      *
669      * @param endpoint The call endpoint to use.
670      * @param executor The executor of where the callback will execute.
671      * @param callback The callback to notify the result of the endpoint change.
672      */
requestCallEndpointChange(@onNull CallEndpoint endpoint, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, CallEndpointException> callback)673     public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint,
674             @NonNull @CallbackExecutor Executor executor,
675             @NonNull OutcomeReceiver<Void, CallEndpointException> callback) {
676         if (mPhone != null) {
677             mPhone.requestCallEndpointChange(endpoint, executor, callback);
678         }
679     }
680 
681     /**
682      * Obtains the current CallEndpoint.
683      *
684      * @return An object encapsulating the CallEndpoint.
685      */
686     @NonNull
getCurrentCallEndpoint()687     public final CallEndpoint getCurrentCallEndpoint() {
688         return mCallEndpoint;
689     }
690 
691     /**
692      * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
693      * to start displaying in-call information to the user. Each instance of {@code InCallService}
694      * will have only one {@code Phone}, and this method will be called exactly once in the lifetime
695      * of the {@code InCallService}.
696      *
697      * @param phone The {@code Phone} object associated with this {@code InCallService}.
698      * @hide
699      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
700      */
701     @SystemApi
702     @Deprecated
onPhoneCreated(Phone phone)703     public void onPhoneCreated(Phone phone) {
704     }
705 
706     /**
707      * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
708      * to stop displaying in-call information to the user. This method will be called exactly once
709      * in the lifetime of the {@code InCallService}, and it will always be called after a previous
710      * call to {@link #onPhoneCreated(Phone)}.
711      *
712      * @param phone The {@code Phone} object associated with this {@code InCallService}.
713      * @hide
714      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
715      */
716     @SystemApi
717     @Deprecated
onPhoneDestroyed(Phone phone)718     public void onPhoneDestroyed(Phone phone) {
719     }
720 
721     /**
722      * Called when the audio state changes.
723      *
724      * @param audioState The new {@link AudioState}.
725      * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState) instead}.
726      * @hide
727      */
728     @Deprecated
onAudioStateChanged(AudioState audioState)729     public void onAudioStateChanged(AudioState audioState) {
730     }
731 
732     /**
733      * Called when the audio state changes.
734      *
735      * @param audioState The new {@link CallAudioState}.
736      * @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)},
737      * {@link #onAvailableCallEndpointsChanged(List)} and
738      * {@link #onMuteStateChanged(boolean)} instead.
739      */
740     @Deprecated
onCallAudioStateChanged(CallAudioState audioState)741     public void onCallAudioStateChanged(CallAudioState audioState) {
742     }
743 
744     /**
745      * Called when the current CallEndpoint changes.
746      *
747      * @param callEndpoint The current CallEndpoint {@link CallEndpoint}.
748      */
onCallEndpointChanged(@onNull CallEndpoint callEndpoint)749     public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {
750     }
751 
752     /**
753      * Called when the available CallEndpoint changes.
754      *
755      * @param availableEndpoints The set of available CallEndpoint {@link CallEndpoint}.
756      */
onAvailableCallEndpointsChanged(@onNull List<CallEndpoint> availableEndpoints)757     public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {
758     }
759 
760     /**
761      * Called when the mute state changes.
762      *
763      * @param isMuted The current mute state.
764      */
onMuteStateChanged(boolean isMuted)765     public void onMuteStateChanged(boolean isMuted) {
766     }
767 
768     /**
769      * Called to bring the in-call screen to the foreground. The in-call experience should
770      * respond immediately by coming to the foreground to inform the user of the state of
771      * ongoing {@code Call}s.
772      *
773      * @param showDialpad If true, put up the dialpad when the screen is shown.
774      */
onBringToForeground(boolean showDialpad)775     public void onBringToForeground(boolean showDialpad) {
776     }
777 
778     /**
779      * Called when a {@code Call} has been added to this in-call session. The in-call user
780      * experience should add necessary state listeners to the specified {@code Call} and
781      * immediately start to show the user information about the existence
782      * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will
783      * include this {@code Call}.
784      *
785      * @param call A newly added {@code Call}.
786      */
onCallAdded(Call call)787     public void onCallAdded(Call call) {
788     }
789 
790     /**
791      * Called when a {@code Call} has been removed from this in-call session. The in-call user
792      * experience should remove any state listeners from the specified {@code Call} and
793      * immediately stop displaying any information about this {@code Call}.
794      * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}.
795      *
796      * @param call A newly removed {@code Call}.
797      */
onCallRemoved(Call call)798     public void onCallRemoved(Call call) {
799     }
800 
801     /**
802      * Called when the ability to add more calls changes.  If the phone cannot
803      * support more calls then {@code canAddCall} is set to {@code false}.  If it can, then it
804      * is set to {@code true}. This can be used to control the visibility of UI to add more calls.
805      *
806      * @param canAddCall Indicates whether an additional call can be added.
807      */
onCanAddCallChanged(boolean canAddCall)808     public void onCanAddCallChanged(boolean canAddCall) {
809     }
810 
811     /**
812      * Called to silence the ringer if a ringing call exists.
813      */
onSilenceRinger()814     public void onSilenceRinger() {
815     }
816 
817     /**
818      * Unused; to handle connection events issued by a {@link ConnectionService}, implement the
819      * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)} callback.
820      * <p>
821      * See {@link Connection#sendConnectionEvent(String, Bundle)}.
822      *
823      * @param call The call the event is associated with.
824      * @param event The event.
825      * @param extras Any associated extras.
826      */
onConnectionEvent(Call call, String event, Bundle extras)827     public void onConnectionEvent(Call call, String event, Bundle extras) {
828     }
829 
830     /**
831      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
832      * {@link Call}.
833      */
834     public static abstract class VideoCall {
835 
836         /** @hide */
837         @SuppressWarnings("HiddenAbstractMethod")
destroy()838         public abstract void destroy();
839 
840         /**
841          * Registers a callback to receive commands and state changes for video calls.
842          *
843          * @param callback The video call callback.
844          */
registerCallback(VideoCall.Callback callback)845         public abstract void registerCallback(VideoCall.Callback callback);
846 
847         /**
848          * Registers a callback to receive commands and state changes for video calls.
849          *
850          * @param callback The video call callback.
851          * @param handler A handler which commands and status changes will be delivered to.
852          */
registerCallback(VideoCall.Callback callback, Handler handler)853         public abstract void registerCallback(VideoCall.Callback callback, Handler handler);
854 
855         /**
856          * Clears the video call callback set via {@link #registerCallback}.
857          *
858          * @param callback The video call callback to clear.
859          */
unregisterCallback(VideoCall.Callback callback)860         public abstract void unregisterCallback(VideoCall.Callback callback);
861 
862         /**
863          * Sets the camera to be used for the outgoing video.
864          * <p>
865          * Handled by {@link Connection.VideoProvider#onSetCamera(String)}.
866          *
867          * @param cameraId The id of the camera (use ids as reported by
868          * {@link CameraManager#getCameraIdList()}).
869          */
setCamera(String cameraId)870         public abstract void setCamera(String cameraId);
871 
872         /**
873          * Sets the surface to be used for displaying a preview of what the user's camera is
874          * currently capturing.  When video transmission is enabled, this is the video signal which
875          * is sent to the remote device.
876          * <p>
877          * Handled by {@link Connection.VideoProvider#onSetPreviewSurface(Surface)}.
878          *
879          * @param surface The {@link Surface}.
880          */
setPreviewSurface(Surface surface)881         public abstract void setPreviewSurface(Surface surface);
882 
883         /**
884          * Sets the surface to be used for displaying the video received from the remote device.
885          * <p>
886          * Handled by {@link Connection.VideoProvider#onSetDisplaySurface(Surface)}.
887          *
888          * @param surface The {@link Surface}.
889          */
setDisplaySurface(Surface surface)890         public abstract void setDisplaySurface(Surface surface);
891 
892         /**
893          * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
894          * the device is 0 degrees.
895          * <p>
896          * Handled by {@link Connection.VideoProvider#onSetDeviceOrientation(int)}.
897          *
898          * @param rotation The device orientation, in degrees.
899          */
setDeviceOrientation(int rotation)900         public abstract void setDeviceOrientation(int rotation);
901 
902         /**
903          * Sets the camera zoom ratio.
904          * <p>
905          * Handled by {@link Connection.VideoProvider#onSetZoom(float)}.
906          *
907          * @param value The camera zoom ratio; for the current camera, should be a value in the
908          * range defined by
909          * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
910          */
setZoom(float value)911         public abstract void setZoom(float value);
912 
913         /**
914          * Issues a request to modify the properties of the current video session.
915          * <p>
916          * Example scenarios include: requesting an audio-only call to be upgraded to a
917          * bi-directional video call, turning on or off the user's camera, sending a pause signal
918          * when the {@link InCallService} is no longer the foreground application.
919          * <p>
920          * Handled by
921          * {@link Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}.
922          *
923          * @param requestProfile The requested call video properties.
924          */
sendSessionModifyRequest(VideoProfile requestProfile)925         public abstract void sendSessionModifyRequest(VideoProfile requestProfile);
926 
927         /**
928          * Provides a response to a request to change the current call video session
929          * properties.  This should be called in response to a request the {@link InCallService} has
930          * received via {@link VideoCall.Callback#onSessionModifyRequestReceived}.
931          * <p>
932          * Handled by
933          * {@link Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)}.
934          *
935          * @param responseProfile The response call video properties.
936          */
sendSessionModifyResponse(VideoProfile responseProfile)937         public abstract void sendSessionModifyResponse(VideoProfile responseProfile);
938 
939         /**
940          * Issues a request to the {@link Connection.VideoProvider} to retrieve the capabilities
941          * of the current camera.  The current camera is selected using
942          * {@link VideoCall#setCamera(String)}.
943          * <p>
944          * Camera capabilities are reported to the caller via
945          * {@link VideoCall.Callback#onCameraCapabilitiesChanged(VideoProfile.CameraCapabilities)}.
946          * <p>
947          * Handled by {@link Connection.VideoProvider#onRequestCameraCapabilities()}.
948          */
requestCameraCapabilities()949         public abstract void requestCameraCapabilities();
950 
951         /**
952          * Issues a request to the {@link Connection.VideoProvider} to retrieve the cumulative data
953          * usage for the video component of the current call (in bytes).  Data usage is reported
954          * to the caller via {@link VideoCall.Callback#onCallDataUsageChanged}.
955          * <p>
956          * Handled by {@link Connection.VideoProvider#onRequestConnectionDataUsage()}.
957          */
requestCallDataUsage()958         public abstract void requestCallDataUsage();
959 
960         /**
961          * Provides the {@link Connection.VideoProvider} with the {@link Uri} of an image to be
962          * displayed to the peer device when the video signal is paused.
963          * <p>
964          * Handled by {@link Connection.VideoProvider#onSetPauseImage(Uri)}.
965          *
966          * @param uri URI of image to display.
967          */
setPauseImage(Uri uri)968         public abstract void setPauseImage(Uri uri);
969 
970         /**
971          * The {@link InCallService} extends this class to provide a means of receiving callbacks
972          * from the {@link Connection.VideoProvider}.
973          * <p>
974          * When the {@link InCallService} receives the
975          * {@link Call.Callback#onVideoCallChanged(Call, VideoCall)} callback, it should create an
976          * instance its {@link VideoCall.Callback} implementation and set it on the
977          * {@link VideoCall} using {@link VideoCall#registerCallback(Callback)}.
978          */
979         public static abstract class Callback {
980             /**
981              * Called when the {@link Connection.VideoProvider} receives a session modification
982              * request from the peer device.
983              * <p>
984              * The {@link InCallService} may potentially prompt the user to confirm whether they
985              * wish to accept the request, or decide to automatically accept the request.  In either
986              * case the {@link InCallService} should call
987              * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} to indicate the video
988              * profile agreed upon.
989              * <p>
990              * Callback originates from
991              * {@link Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)}.
992              *
993              * @param videoProfile The requested video profile.
994              */
onSessionModifyRequestReceived(VideoProfile videoProfile)995             public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile);
996 
997             /**
998              * Called when the {@link Connection.VideoProvider} receives a response to a session
999              * modification request previously sent to the peer device.
1000              * <p>
1001              * The new video state should not be considered active by the {@link InCallService}
1002              * until the {@link Call} video state changes (the
1003              * {@link Call.Callback#onDetailsChanged(Call, Call.Details)} callback is triggered
1004              * when the video state changes).
1005              * <p>
1006              * Callback originates from
1007              * {@link Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile,
1008              *      VideoProfile)}.
1009              *
1010              * @param status Status of the session modify request.  Valid values are
1011              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
1012              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
1013              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID},
1014              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT},
1015              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE}.
1016              * @param requestedProfile The original request which was sent to the peer device.
1017              * @param responseProfile The actual profile changes made by the peer device.
1018              */
onSessionModifyResponseReceived(int status, VideoProfile requestedProfile, VideoProfile responseProfile)1019             public abstract void onSessionModifyResponseReceived(int status,
1020                     VideoProfile requestedProfile, VideoProfile responseProfile);
1021 
1022             /**
1023              * Handles events related to the current video session which the {@link InCallService}
1024              * may wish to handle. These are separate from requested changes to the session due to
1025              * the underlying protocol or connection.
1026              * <p>
1027              * Callback originates from
1028              * {@link Connection.VideoProvider#handleCallSessionEvent(int)}.
1029              *
1030              * @param event The event.  Valid values are:
1031              *      {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE},
1032              *      {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME},
1033              *      {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
1034              *      {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
1035              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
1036              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY},
1037              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_PERMISSION_ERROR}.
1038              */
onCallSessionEvent(int event)1039             public abstract void onCallSessionEvent(int event);
1040 
1041             /**
1042              * Handles a change to the video dimensions from the peer device. This could happen if,
1043              * for example, the peer changes orientation of their device, or switches cameras.
1044              * <p>
1045              * Callback originates from
1046              * {@link Connection.VideoProvider#changePeerDimensions(int, int)}.
1047              *
1048              * @param width  The updated peer video width.
1049              * @param height The updated peer video height.
1050              */
onPeerDimensionsChanged(int width, int height)1051             public abstract void onPeerDimensionsChanged(int width, int height);
1052 
1053             /**
1054              * Handles a change to the video quality.
1055              * <p>
1056              * Callback originates from {@link Connection.VideoProvider#changeVideoQuality(int)}.
1057              *
1058              * @param videoQuality  The updated peer video quality.  Valid values:
1059              *      {@link VideoProfile#QUALITY_HIGH},
1060              *      {@link VideoProfile#QUALITY_MEDIUM},
1061              *      {@link VideoProfile#QUALITY_LOW},
1062              *      {@link VideoProfile#QUALITY_DEFAULT}.
1063              */
onVideoQualityChanged(int videoQuality)1064             public abstract void onVideoQualityChanged(int videoQuality);
1065 
1066             /**
1067              * Handles an update to the total data used for the current video session.
1068              * <p>
1069              * Used by the {@link Connection.VideoProvider} in response to
1070              * {@link VideoCall#requestCallDataUsage()}.  May also be called periodically by the
1071              * {@link Connection.VideoProvider}.
1072              * <p>
1073              * Callback originates from {@link Connection.VideoProvider#setCallDataUsage(long)}.
1074              *
1075              * @param dataUsage The updated data usage (in bytes).
1076              */
onCallDataUsageChanged(long dataUsage)1077             public abstract void onCallDataUsageChanged(long dataUsage);
1078 
1079             /**
1080              * Handles a change in the capabilities of the currently selected camera.
1081              * <p>
1082              * Used by the {@link Connection.VideoProvider} in response to
1083              * {@link VideoCall#requestCameraCapabilities()}.  The {@link Connection.VideoProvider}
1084              * may also report the camera capabilities after a call to
1085              * {@link VideoCall#setCamera(String)}.
1086              * <p>
1087              * Callback originates from
1088              * {@link Connection.VideoProvider#changeCameraCapabilities(
1089              *      VideoProfile.CameraCapabilities)}.
1090              *
1091              * @param cameraCapabilities The changed camera capabilities.
1092              */
onCameraCapabilitiesChanged( VideoProfile.CameraCapabilities cameraCapabilities)1093             public abstract void onCameraCapabilitiesChanged(
1094                     VideoProfile.CameraCapabilities cameraCapabilities);
1095         }
1096     }
1097 }
1098