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