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