Home | History | Annotate | Download | only in telecom
      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
    294         public void setInCallAdapter(IInCallAdapter inCallAdapter) {
    295             mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
    296         }
    297 
    298         @Override
    299         public void addCall(ParcelableCall call) {
    300             mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
    301         }
    302 
    303         @Override
    304         public void updateCall(ParcelableCall call) {
    305             mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
    306         }
    307 
    308         @Override
    309         public void setPostDial(String callId, String remaining) {
    310             // TODO: Unused
    311         }
    312 
    313         @Override
    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
    322         public void onCallAudioStateChanged(CallAudioState callAudioState) {
    323             mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget();
    324         }
    325 
    326         @Override
    327         public void bringToForeground(boolean showDialpad) {
    328             mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
    329         }
    330 
    331         @Override
    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
    338         public void silenceRinger() {
    339             mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
    340         }
    341 
    342         @Override
    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
    352         public void onRttUpgradeRequest(String callId, int id) {
    353             mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget();
    354         }
    355 
    356         @Override
    357         public void onRttInitiationFailure(String callId, int reason) {
    358             mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget();
    359         }
    360 
    361         @Override
    362         public void onHandoverFailed(String callId, int error) {
    363             mHandler.obtainMessage(MSG_ON_HANDOVER_FAILED, error, 0, callId).sendToTarget();
    364         }
    365 
    366         @Override
    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 
    417     public InCallService() {
    418     }
    419 
    420     @Override
    421     public IBinder onBind(Intent intent) {
    422         return new InCallServiceBinder();
    423     }
    424 
    425     @Override
    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
    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      */
    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      */
    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
    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      */
    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      */
    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      */
    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      */
    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
    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
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    627     public void onCanAddCallChanged(boolean canAddCall) {
    628     }
    629 
    630     /**
    631      * Called to silence the ringer if a ringing call exists.
    632      */
    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      */
    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 */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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              */
    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              */
    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              */
    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              */
    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              */
    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              */
    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              */
    909             public abstract void onCameraCapabilitiesChanged(
    910                     VideoProfile.CameraCapabilities cameraCapabilities);
    911         }
    912     }
    913 }
    914