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