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