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