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                     String callingPackage = getApplicationContext().getOpPackageName();
293                     mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
294                             getApplicationContext().getApplicationInfo().targetSdkVersion);
295                     mPhone.addListener(mPhoneListener);
296                     onPhoneCreated(mPhone);
297                     break;
298                 case MSG_ADD_CALL:
299                     mPhone.internalAddCall((ParcelableCall) msg.obj);
300                     break;
301                 case MSG_UPDATE_CALL:
302                     mPhone.internalUpdateCall((ParcelableCall) msg.obj);
303                     break;
304                 case MSG_SET_POST_DIAL_WAIT: {
305                     SomeArgs args = (SomeArgs) msg.obj;
306                     try {
307                         String callId = (String) args.arg1;
308                         String remaining = (String) args.arg2;
309                         mPhone.internalSetPostDialWait(callId, remaining);
310                     } finally {
311                         args.recycle();
312                     }
313                     break;
314                 }
315                 case MSG_ON_CALL_AUDIO_STATE_CHANGED:
316                     mPhone.internalCallAudioStateChanged((CallAudioState) msg.obj);
317                     break;
318                 case MSG_BRING_TO_FOREGROUND:
319                     mPhone.internalBringToForeground(msg.arg1 == 1);
320                     break;
321                 case MSG_ON_CAN_ADD_CALL_CHANGED:
322                     mPhone.internalSetCanAddCall(msg.arg1 == 1);
323                     break;
324                 case MSG_SILENCE_RINGER:
325                     mPhone.internalSilenceRinger();
326                     break;
327                 case MSG_ON_CONNECTION_EVENT: {
328                     SomeArgs args = (SomeArgs) msg.obj;
329                     try {
330                         String callId = (String) args.arg1;
331                         String event = (String) args.arg2;
332                         Bundle extras = (Bundle) args.arg3;
333                         mPhone.internalOnConnectionEvent(callId, event, extras);
334                     } finally {
335                         args.recycle();
336                     }
337                     break;
338                 }
339                 case MSG_ON_RTT_UPGRADE_REQUEST: {
340                     String callId = (String) msg.obj;
341                     int requestId = msg.arg1;
342                     mPhone.internalOnRttUpgradeRequest(callId, requestId);
343                     break;
344                 }
345                 case MSG_ON_RTT_INITIATION_FAILURE: {
346                     String callId = (String) msg.obj;
347                     int reason = msg.arg1;
348                     mPhone.internalOnRttInitiationFailure(callId, reason);
349                     break;
350                 }
351                 case MSG_ON_HANDOVER_FAILED: {
352                     String callId = (String) msg.obj;
353                     int error = msg.arg1;
354                     mPhone.internalOnHandoverFailed(callId, error);
355                     break;
356                 }
357                 case MSG_ON_HANDOVER_COMPLETE: {
358                     String callId = (String) msg.obj;
359                     mPhone.internalOnHandoverComplete(callId);
360                     break;
361                 }
362                 case MSG_ON_CALL_ENDPOINT_CHANGED: {
363                     CallEndpoint endpoint = (CallEndpoint) msg.obj;
364                     if (!Objects.equals(mCallEndpoint, endpoint)) {
365                         mCallEndpoint = endpoint;
366                         InCallService.this.onCallEndpointChanged(mCallEndpoint);
367                     }
368                     break;
369                 }
370                 case MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED: {
371                     InCallService.this.onAvailableCallEndpointsChanged(
372                             (List<CallEndpoint>) msg.obj);
373                     break;
374                 }
375                 case MSG_ON_MUTE_STATE_CHANGED: {
376                     InCallService.this.onMuteStateChanged((boolean) msg.obj);
377                     break;
378                 }
379                 default:
380                     break;
381             }
382         }
383     };
384 
385     /** Manages the binder calls so that the implementor does not need to deal with it. */
386     private final class InCallServiceBinder extends IInCallService.Stub {
387         @Override
setInCallAdapter(IInCallAdapter inCallAdapter)388         public void setInCallAdapter(IInCallAdapter inCallAdapter) {
389             mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
390         }
391 
392         @Override
addCall(ParcelableCall call)393         public void addCall(ParcelableCall call) {
394             mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
395         }
396 
397         @Override
updateCall(ParcelableCall call)398         public void updateCall(ParcelableCall call) {
399             mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
400         }
401 
402         @Override
setPostDial(String callId, String remaining)403         public void setPostDial(String callId, String remaining) {
404             // TODO: Unused
405         }
406 
407         @Override
setPostDialWait(String callId, String remaining)408         public void setPostDialWait(String callId, String remaining) {
409             SomeArgs args = SomeArgs.obtain();
410             args.arg1 = callId;
411             args.arg2 = remaining;
412             mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget();
413         }
414 
415         @Override
onCallAudioStateChanged(CallAudioState callAudioState)416         public void onCallAudioStateChanged(CallAudioState callAudioState) {
417             mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget();
418         }
419 
420         @Override
onCallEndpointChanged(CallEndpoint callEndpoint)421         public void onCallEndpointChanged(CallEndpoint callEndpoint) {
422             mHandler.obtainMessage(MSG_ON_CALL_ENDPOINT_CHANGED, callEndpoint).sendToTarget();
423         }
424 
425         @Override
onAvailableCallEndpointsChanged(List<CallEndpoint> availableEndpoints)426         public void onAvailableCallEndpointsChanged(List<CallEndpoint> availableEndpoints) {
427             mHandler.obtainMessage(MSG_ON_AVAILABLE_CALL_ENDPOINTS_CHANGED, availableEndpoints)
428                     .sendToTarget();
429         }
430 
431         @Override
onMuteStateChanged(boolean isMuted)432         public void onMuteStateChanged(boolean isMuted) {
433             mHandler.obtainMessage(MSG_ON_MUTE_STATE_CHANGED, isMuted).sendToTarget();
434         }
435 
436         @Override
bringToForeground(boolean showDialpad)437         public void bringToForeground(boolean showDialpad) {
438             mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
439         }
440 
441         @Override
onCanAddCallChanged(boolean canAddCall)442         public void onCanAddCallChanged(boolean canAddCall) {
443             mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
444                     .sendToTarget();
445         }
446 
447         @Override
silenceRinger()448         public void silenceRinger() {
449             mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
450         }
451 
452         @Override
onConnectionEvent(String callId, String event, Bundle extras)453         public void onConnectionEvent(String callId, String event, Bundle extras) {
454             SomeArgs args = SomeArgs.obtain();
455             args.arg1 = callId;
456             args.arg2 = event;
457             args.arg3 = extras;
458             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
459         }
460 
461         @Override
onRttUpgradeRequest(String callId, int id)462         public void onRttUpgradeRequest(String callId, int id) {
463             mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget();
464         }
465 
466         @Override
onRttInitiationFailure(String callId, int reason)467         public void onRttInitiationFailure(String callId, int reason) {
468             mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget();
469         }
470 
471         @Override
onHandoverFailed(String callId, int error)472         public void onHandoverFailed(String callId, int error) {
473             mHandler.obtainMessage(MSG_ON_HANDOVER_FAILED, error, 0, callId).sendToTarget();
474         }
475 
476         @Override
onHandoverComplete(String callId)477         public void onHandoverComplete(String callId) {
478             mHandler.obtainMessage(MSG_ON_HANDOVER_COMPLETE, callId).sendToTarget();
479         }
480     }
481 
482     private Phone.Listener mPhoneListener = new Phone.Listener() {
483         /** ${inheritDoc} */
484         @Override
485         public void onAudioStateChanged(Phone phone, AudioState audioState) {
486             InCallService.this.onAudioStateChanged(audioState);
487         }
488 
489         public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) {
490             InCallService.this.onCallAudioStateChanged(callAudioState);
491         };
492 
493         /** ${inheritDoc} */
494         @Override
495         public void onBringToForeground(Phone phone, boolean showDialpad) {
496             InCallService.this.onBringToForeground(showDialpad);
497         }
498 
499         /** ${inheritDoc} */
500         @Override
501         public void onCallAdded(Phone phone, Call call) {
502             InCallService.this.onCallAdded(call);
503         }
504 
505         /** ${inheritDoc} */
506         @Override
507         public void onCallRemoved(Phone phone, Call call) {
508             InCallService.this.onCallRemoved(call);
509         }
510 
511         /** ${inheritDoc} */
512         @Override
513         public void onCanAddCallChanged(Phone phone, boolean canAddCall) {
514             InCallService.this.onCanAddCallChanged(canAddCall);
515         }
516 
517         /** ${inheritDoc} */
518         @Override
519         public void onSilenceRinger(Phone phone) {
520             InCallService.this.onSilenceRinger();
521         }
522 
523     };
524 
525     private Phone mPhone;
526 
InCallService()527     public InCallService() {
528     }
529 
530     @Override
onBind(Intent intent)531     public IBinder onBind(Intent intent) {
532         return new InCallServiceBinder();
533     }
534 
535     @Override
onUnbind(Intent intent)536     public boolean onUnbind(Intent intent) {
537         if (mPhone != null) {
538             Phone oldPhone = mPhone;
539             mPhone = null;
540 
541             oldPhone.destroy();
542             // destroy sets all the calls to disconnected if any live ones still exist. Therefore,
543             // it is important to remove the Listener *after* the call to destroy so that
544             // InCallService.on* callbacks are appropriately called.
545             oldPhone.removeListener(mPhoneListener);
546 
547             onPhoneDestroyed(oldPhone);
548         }
549 
550         return false;
551     }
552 
553     /**
554      * Obtain the {@code Phone} associated with this {@code InCallService}.
555      *
556      * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
557      *         if the {@code InCallService} is not in a state where it has an associated
558      *         {@code Phone}.
559      * @hide
560      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
561      */
562     @SystemApi
563     @Deprecated
getPhone()564     public Phone getPhone() {
565         return mPhone;
566     }
567 
568     /**
569      * Obtains the current list of {@code Call}s to be displayed by this in-call service.
570      *
571      * @return A list of the relevant {@code Call}s.
572      */
getCalls()573     public final List<Call> getCalls() {
574         return mPhone == null ? Collections.<Call>emptyList() : mPhone.getCalls();
575     }
576 
577     /**
578      * Returns if the device can support additional calls.
579      *
580      * @return Whether the phone supports adding more calls.
581      */
canAddCall()582     public final boolean canAddCall() {
583         return mPhone == null ? false : mPhone.canAddCall();
584     }
585 
586     /**
587      * Obtains the current phone call audio state.
588      *
589      * @return An object encapsulating the audio state. Returns null if the service is not
590      *         fully initialized.
591      * @deprecated Use {@link #getCallAudioState()} instead.
592      * @hide
593      */
594     @Deprecated
getAudioState()595     public final AudioState getAudioState() {
596         return mPhone == null ? null : mPhone.getAudioState();
597     }
598 
599     /**
600      * Obtains the current phone call audio state.
601      *
602      * @return An object encapsulating the audio state. Returns null if the service is not
603      *         fully initialized.
604      * @deprecated Use {@link #getCurrentCallEndpoint()},
605      * {@link #onAvailableCallEndpointsChanged(List)} and
606      * {@link #onMuteStateChanged(boolean)} instead.
607      */
608     @Deprecated
getCallAudioState()609     public final CallAudioState getCallAudioState() {
610         return mPhone == null ? null : mPhone.getCallAudioState();
611     }
612 
613     /**
614      * Sets the microphone mute state. When this request is honored, there will be change to
615      * the {@link #getCallAudioState()}.
616      *
617      * @param state {@code true} if the microphone should be muted; {@code false} otherwise.
618      */
setMuted(boolean state)619     public final void setMuted(boolean state) {
620         if (mPhone != null) {
621             mPhone.setMuted(state);
622         }
623     }
624 
625     /**
626      * Sets the audio route (speaker, bluetooth, etc...).  When this request is honored, there will
627      * be change to the {@link #getCallAudioState()}.
628      *
629      * @param route The audio route to use.
630      * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
631      * instead.
632      */
633     @Deprecated
setAudioRoute(int route)634     public final void setAudioRoute(int route) {
635         if (mPhone != null) {
636             mPhone.setAudioRoute(route);
637         }
638     }
639 
640     /**
641      * Request audio routing to a specific bluetooth device. Calling this method may result in
642      * the device routing audio to a different bluetooth device than the one specified if the
643      * bluetooth stack is unable to route audio to the requested device.
644      * A list of available devices can be obtained via
645      * {@link CallAudioState#getSupportedBluetoothDevices()}
646      *
647      * @param bluetoothDevice The bluetooth device to connect to.
648      * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}
649      * instead.
650      */
651     @Deprecated
requestBluetoothAudio(@onNull BluetoothDevice bluetoothDevice)652     public final void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) {
653         if (mPhone != null) {
654             mPhone.requestBluetoothAudio(bluetoothDevice.getAddress());
655         }
656     }
657 
658     /**
659      * Request audio routing to a specific CallEndpoint. Clients should not define their own
660      * CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid
661      * endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}.
662      * When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}.
663      *
664      * @param endpoint The call endpoint to use.
665      * @param executor The executor of where the callback will execute.
666      * @param callback The callback to notify the result of the endpoint change.
667      */
requestCallEndpointChange(@onNull CallEndpoint endpoint, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, CallEndpointException> callback)668     public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint,
669             @NonNull @CallbackExecutor Executor executor,
670             @NonNull OutcomeReceiver<Void, CallEndpointException> callback) {
671         if (mPhone != null) {
672             mPhone.requestCallEndpointChange(endpoint, executor, callback);
673         }
674     }
675 
676     /**
677      * Obtains the current CallEndpoint.
678      *
679      * @return An object encapsulating the CallEndpoint.
680      */
681     @NonNull
getCurrentCallEndpoint()682     public final CallEndpoint getCurrentCallEndpoint() {
683         return mCallEndpoint;
684     }
685 
686     /**
687      * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
688      * to start displaying in-call information to the user. Each instance of {@code InCallService}
689      * will have only one {@code Phone}, and this method will be called exactly once in the lifetime
690      * of the {@code InCallService}.
691      *
692      * @param phone The {@code Phone} object associated with this {@code InCallService}.
693      * @hide
694      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
695      */
696     @SystemApi
697     @Deprecated
onPhoneCreated(Phone phone)698     public void onPhoneCreated(Phone phone) {
699     }
700 
701     /**
702      * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
703      * to stop displaying in-call information to the user. This method will be called exactly once
704      * in the lifetime of the {@code InCallService}, and it will always be called after a previous
705      * call to {@link #onPhoneCreated(Phone)}.
706      *
707      * @param phone The {@code Phone} object associated with this {@code InCallService}.
708      * @hide
709      * @deprecated Use direct methods on InCallService instead of {@link Phone}.
710      */
711     @SystemApi
712     @Deprecated
onPhoneDestroyed(Phone phone)713     public void onPhoneDestroyed(Phone phone) {
714     }
715 
716     /**
717      * Called when the audio state changes.
718      *
719      * @param audioState The new {@link AudioState}.
720      * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState) instead}.
721      * @hide
722      */
723     @Deprecated
onAudioStateChanged(AudioState audioState)724     public void onAudioStateChanged(AudioState audioState) {
725     }
726 
727     /**
728      * Called when the audio state changes.
729      *
730      * @param audioState The new {@link CallAudioState}.
731      * @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)},
732      * {@link #onAvailableCallEndpointsChanged(List)} and
733      * {@link #onMuteStateChanged(boolean)} instead.
734      */
735     @Deprecated
onCallAudioStateChanged(CallAudioState audioState)736     public void onCallAudioStateChanged(CallAudioState audioState) {
737     }
738 
739     /**
740      * Called when the current CallEndpoint changes.
741      *
742      * @param callEndpoint The current CallEndpoint {@link CallEndpoint}.
743      */
onCallEndpointChanged(@onNull CallEndpoint callEndpoint)744     public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {
745     }
746 
747     /**
748      * Called when the available CallEndpoint changes.
749      *
750      * @param availableEndpoints The set of available CallEndpoint {@link CallEndpoint}.
751      */
onAvailableCallEndpointsChanged(@onNull List<CallEndpoint> availableEndpoints)752     public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {
753     }
754 
755     /**
756      * Called when the mute state changes.
757      *
758      * @param isMuted The current mute state.
759      */
onMuteStateChanged(boolean isMuted)760     public void onMuteStateChanged(boolean isMuted) {
761     }
762 
763     /**
764      * Called to bring the in-call screen to the foreground. The in-call experience should
765      * respond immediately by coming to the foreground to inform the user of the state of
766      * ongoing {@code Call}s.
767      *
768      * @param showDialpad If true, put up the dialpad when the screen is shown.
769      */
onBringToForeground(boolean showDialpad)770     public void onBringToForeground(boolean showDialpad) {
771     }
772 
773     /**
774      * Called when a {@code Call} has been added to this in-call session. The in-call user
775      * experience should add necessary state listeners to the specified {@code Call} and
776      * immediately start to show the user information about the existence
777      * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will
778      * include this {@code Call}.
779      *
780      * @param call A newly added {@code Call}.
781      */
onCallAdded(Call call)782     public void onCallAdded(Call call) {
783     }
784 
785     /**
786      * Called when a {@code Call} has been removed from this in-call session. The in-call user
787      * experience should remove any state listeners from the specified {@code Call} and
788      * immediately stop displaying any information about this {@code Call}.
789      * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}.
790      *
791      * @param call A newly removed {@code Call}.
792      */
onCallRemoved(Call call)793     public void onCallRemoved(Call call) {
794     }
795 
796     /**
797      * Called when the ability to add more calls changes.  If the phone cannot
798      * support more calls then {@code canAddCall} is set to {@code false}.  If it can, then it
799      * is set to {@code true}. This can be used to control the visibility of UI to add more calls.
800      *
801      * @param canAddCall Indicates whether an additional call can be added.
802      */
onCanAddCallChanged(boolean canAddCall)803     public void onCanAddCallChanged(boolean canAddCall) {
804     }
805 
806     /**
807      * Called to silence the ringer if a ringing call exists.
808      */
onSilenceRinger()809     public void onSilenceRinger() {
810     }
811 
812     /**
813      * Unused; to handle connection events issued by a {@link ConnectionService}, implement the
814      * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)} callback.
815      * <p>
816      * See {@link Connection#sendConnectionEvent(String, Bundle)}.
817      *
818      * @param call The call the event is associated with.
819      * @param event The event.
820      * @param extras Any associated extras.
821      */
onConnectionEvent(Call call, String event, Bundle extras)822     public void onConnectionEvent(Call call, String event, Bundle extras) {
823     }
824 
825     /**
826      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
827      * {@link Call}.
828      */
829     public static abstract class VideoCall {
830 
831         /** @hide */
832         @SuppressWarnings("HiddenAbstractMethod")
destroy()833         public abstract void destroy();
834 
835         /**
836          * Registers a callback to receive commands and state changes for video calls.
837          *
838          * @param callback The video call callback.
839          */
registerCallback(VideoCall.Callback callback)840         public abstract void registerCallback(VideoCall.Callback callback);
841 
842         /**
843          * Registers a callback to receive commands and state changes for video calls.
844          *
845          * @param callback The video call callback.
846          * @param handler A handler which commands and status changes will be delivered to.
847          */
registerCallback(VideoCall.Callback callback, Handler handler)848         public abstract void registerCallback(VideoCall.Callback callback, Handler handler);
849 
850         /**
851          * Clears the video call callback set via {@link #registerCallback}.
852          *
853          * @param callback The video call callback to clear.
854          */
unregisterCallback(VideoCall.Callback callback)855         public abstract void unregisterCallback(VideoCall.Callback callback);
856 
857         /**
858          * Sets the camera to be used for the outgoing video.
859          * <p>
860          * Handled by {@link Connection.VideoProvider#onSetCamera(String)}.
861          *
862          * @param cameraId The id of the camera (use ids as reported by
863          * {@link CameraManager#getCameraIdList()}).
864          */
setCamera(String cameraId)865         public abstract void setCamera(String cameraId);
866 
867         /**
868          * Sets the surface to be used for displaying a preview of what the user's camera is
869          * currently capturing.  When video transmission is enabled, this is the video signal which
870          * is sent to the remote device.
871          * <p>
872          * Handled by {@link Connection.VideoProvider#onSetPreviewSurface(Surface)}.
873          *
874          * @param surface The {@link Surface}.
875          */
setPreviewSurface(Surface surface)876         public abstract void setPreviewSurface(Surface surface);
877 
878         /**
879          * Sets the surface to be used for displaying the video received from the remote device.
880          * <p>
881          * Handled by {@link Connection.VideoProvider#onSetDisplaySurface(Surface)}.
882          *
883          * @param surface The {@link Surface}.
884          */
setDisplaySurface(Surface surface)885         public abstract void setDisplaySurface(Surface surface);
886 
887         /**
888          * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
889          * the device is 0 degrees.
890          * <p>
891          * Handled by {@link Connection.VideoProvider#onSetDeviceOrientation(int)}.
892          *
893          * @param rotation The device orientation, in degrees.
894          */
setDeviceOrientation(int rotation)895         public abstract void setDeviceOrientation(int rotation);
896 
897         /**
898          * Sets the camera zoom ratio.
899          * <p>
900          * Handled by {@link Connection.VideoProvider#onSetZoom(float)}.
901          *
902          * @param value The camera zoom ratio; for the current camera, should be a value in the
903          * range defined by
904          * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
905          */
setZoom(float value)906         public abstract void setZoom(float value);
907 
908         /**
909          * Issues a request to modify the properties of the current video session.
910          * <p>
911          * Example scenarios include: requesting an audio-only call to be upgraded to a
912          * bi-directional video call, turning on or off the user's camera, sending a pause signal
913          * when the {@link InCallService} is no longer the foreground application.
914          * <p>
915          * Handled by
916          * {@link Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}.
917          *
918          * @param requestProfile The requested call video properties.
919          */
sendSessionModifyRequest(VideoProfile requestProfile)920         public abstract void sendSessionModifyRequest(VideoProfile requestProfile);
921 
922         /**
923          * Provides a response to a request to change the current call video session
924          * properties.  This should be called in response to a request the {@link InCallService} has
925          * received via {@link VideoCall.Callback#onSessionModifyRequestReceived}.
926          * <p>
927          * Handled by
928          * {@link Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)}.
929          *
930          * @param responseProfile The response call video properties.
931          */
sendSessionModifyResponse(VideoProfile responseProfile)932         public abstract void sendSessionModifyResponse(VideoProfile responseProfile);
933 
934         /**
935          * Issues a request to the {@link Connection.VideoProvider} to retrieve the capabilities
936          * of the current camera.  The current camera is selected using
937          * {@link VideoCall#setCamera(String)}.
938          * <p>
939          * Camera capabilities are reported to the caller via
940          * {@link VideoCall.Callback#onCameraCapabilitiesChanged(VideoProfile.CameraCapabilities)}.
941          * <p>
942          * Handled by {@link Connection.VideoProvider#onRequestCameraCapabilities()}.
943          */
requestCameraCapabilities()944         public abstract void requestCameraCapabilities();
945 
946         /**
947          * Issues a request to the {@link Connection.VideoProvider} to retrieve the cumulative data
948          * usage for the video component of the current call (in bytes).  Data usage is reported
949          * to the caller via {@link VideoCall.Callback#onCallDataUsageChanged}.
950          * <p>
951          * Handled by {@link Connection.VideoProvider#onRequestConnectionDataUsage()}.
952          */
requestCallDataUsage()953         public abstract void requestCallDataUsage();
954 
955         /**
956          * Provides the {@link Connection.VideoProvider} with the {@link Uri} of an image to be
957          * displayed to the peer device when the video signal is paused.
958          * <p>
959          * Handled by {@link Connection.VideoProvider#onSetPauseImage(Uri)}.
960          *
961          * @param uri URI of image to display.
962          */
setPauseImage(Uri uri)963         public abstract void setPauseImage(Uri uri);
964 
965         /**
966          * The {@link InCallService} extends this class to provide a means of receiving callbacks
967          * from the {@link Connection.VideoProvider}.
968          * <p>
969          * When the {@link InCallService} receives the
970          * {@link Call.Callback#onVideoCallChanged(Call, VideoCall)} callback, it should create an
971          * instance its {@link VideoCall.Callback} implementation and set it on the
972          * {@link VideoCall} using {@link VideoCall#registerCallback(Callback)}.
973          */
974         public static abstract class Callback {
975             /**
976              * Called when the {@link Connection.VideoProvider} receives a session modification
977              * request from the peer device.
978              * <p>
979              * The {@link InCallService} may potentially prompt the user to confirm whether they
980              * wish to accept the request, or decide to automatically accept the request.  In either
981              * case the {@link InCallService} should call
982              * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} to indicate the video
983              * profile agreed upon.
984              * <p>
985              * Callback originates from
986              * {@link Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)}.
987              *
988              * @param videoProfile The requested video profile.
989              */
onSessionModifyRequestReceived(VideoProfile videoProfile)990             public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile);
991 
992             /**
993              * Called when the {@link Connection.VideoProvider} receives a response to a session
994              * modification request previously sent to the peer device.
995              * <p>
996              * The new video state should not be considered active by the {@link InCallService}
997              * until the {@link Call} video state changes (the
998              * {@link Call.Callback#onDetailsChanged(Call, Call.Details)} callback is triggered
999              * when the video state changes).
1000              * <p>
1001              * Callback originates from
1002              * {@link Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile,
1003              *      VideoProfile)}.
1004              *
1005              * @param status Status of the session modify request.  Valid values are
1006              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
1007              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
1008              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID},
1009              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT},
1010              *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE}.
1011              * @param requestedProfile The original request which was sent to the peer device.
1012              * @param responseProfile The actual profile changes made by the peer device.
1013              */
onSessionModifyResponseReceived(int status, VideoProfile requestedProfile, VideoProfile responseProfile)1014             public abstract void onSessionModifyResponseReceived(int status,
1015                     VideoProfile requestedProfile, VideoProfile responseProfile);
1016 
1017             /**
1018              * Handles events related to the current video session which the {@link InCallService}
1019              * may wish to handle. These are separate from requested changes to the session due to
1020              * the underlying protocol or connection.
1021              * <p>
1022              * Callback originates from
1023              * {@link Connection.VideoProvider#handleCallSessionEvent(int)}.
1024              *
1025              * @param event The event.  Valid values are:
1026              *      {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE},
1027              *      {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME},
1028              *      {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
1029              *      {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
1030              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
1031              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY},
1032              *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_PERMISSION_ERROR}.
1033              */
onCallSessionEvent(int event)1034             public abstract void onCallSessionEvent(int event);
1035 
1036             /**
1037              * Handles a change to the video dimensions from the peer device. This could happen if,
1038              * for example, the peer changes orientation of their device, or switches cameras.
1039              * <p>
1040              * Callback originates from
1041              * {@link Connection.VideoProvider#changePeerDimensions(int, int)}.
1042              *
1043              * @param width  The updated peer video width.
1044              * @param height The updated peer video height.
1045              */
onPeerDimensionsChanged(int width, int height)1046             public abstract void onPeerDimensionsChanged(int width, int height);
1047 
1048             /**
1049              * Handles a change to the video quality.
1050              * <p>
1051              * Callback originates from {@link Connection.VideoProvider#changeVideoQuality(int)}.
1052              *
1053              * @param videoQuality  The updated peer video quality.  Valid values:
1054              *      {@link VideoProfile#QUALITY_HIGH},
1055              *      {@link VideoProfile#QUALITY_MEDIUM},
1056              *      {@link VideoProfile#QUALITY_LOW},
1057              *      {@link VideoProfile#QUALITY_DEFAULT}.
1058              */
onVideoQualityChanged(int videoQuality)1059             public abstract void onVideoQualityChanged(int videoQuality);
1060 
1061             /**
1062              * Handles an update to the total data used for the current video session.
1063              * <p>
1064              * Used by the {@link Connection.VideoProvider} in response to
1065              * {@link VideoCall#requestCallDataUsage()}.  May also be called periodically by the
1066              * {@link Connection.VideoProvider}.
1067              * <p>
1068              * Callback originates from {@link Connection.VideoProvider#setCallDataUsage(long)}.
1069              *
1070              * @param dataUsage The updated data usage (in bytes).
1071              */
onCallDataUsageChanged(long dataUsage)1072             public abstract void onCallDataUsageChanged(long dataUsage);
1073 
1074             /**
1075              * Handles a change in the capabilities of the currently selected camera.
1076              * <p>
1077              * Used by the {@link Connection.VideoProvider} in response to
1078              * {@link VideoCall#requestCameraCapabilities()}.  The {@link Connection.VideoProvider}
1079              * may also report the camera capabilities after a call to
1080              * {@link VideoCall#setCamera(String)}.
1081              * <p>
1082              * Callback originates from
1083              * {@link Connection.VideoProvider#changeCameraCapabilities(
1084              *      VideoProfile.CameraCapabilities)}.
1085              *
1086              * @param cameraCapabilities The changed camera capabilities.
1087              */
onCameraCapabilitiesChanged( VideoProfile.CameraCapabilities cameraCapabilities)1088             public abstract void onCameraCapabilitiesChanged(
1089                     VideoProfile.CameraCapabilities cameraCapabilities);
1090         }
1091     }
1092 }
1093