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