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