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