InCallService.java revision b702ef8a91c9adec68b11e36c50b89fd5bcbb607
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 17package android.telecom; 18 19import android.annotation.SdkConstant; 20import android.annotation.SystemApi; 21import android.app.Service; 22import android.content.Intent; 23import android.hardware.camera2.CameraManager; 24import android.net.Uri; 25import android.os.Handler; 26import android.os.IBinder; 27import android.os.Looper; 28import android.os.Message; 29import android.view.Surface; 30 31import com.android.internal.os.SomeArgs; 32import com.android.internal.telecom.IInCallAdapter; 33import com.android.internal.telecom.IInCallService; 34 35import java.lang.String; 36import java.util.Collections; 37import java.util.List; 38 39/** 40 * This service is implemented by any app that wishes to provide the user-interface for managing 41 * phone calls. Telecom binds to this service while there exists a live (active or incoming) call, 42 * and uses it to notify the in-call app of any live and and recently disconnected calls. 43 */ 44public abstract class InCallService extends Service { 45 46 /** 47 * The {@link Intent} that must be declared as handled by the service. 48 */ 49 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 50 public static final String SERVICE_INTERFACE = "android.telecom.InCallService"; 51 52 private static final int MSG_SET_IN_CALL_ADAPTER = 1; 53 private static final int MSG_ADD_CALL = 2; 54 private static final int MSG_UPDATE_CALL = 3; 55 private static final int MSG_SET_POST_DIAL_WAIT = 4; 56 private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5; 57 private static final int MSG_BRING_TO_FOREGROUND = 6; 58 private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7; 59 60 /** Default Handler used to consolidate binder method calls onto a single thread. */ 61 private final Handler mHandler = new Handler(Looper.getMainLooper()) { 62 @Override 63 public void handleMessage(Message msg) { 64 if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) { 65 return; 66 } 67 68 switch (msg.what) { 69 case MSG_SET_IN_CALL_ADAPTER: 70 mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj)); 71 mPhone.addListener(mPhoneListener); 72 onPhoneCreated(mPhone); 73 break; 74 case MSG_ADD_CALL: 75 mPhone.internalAddCall((ParcelableCall) msg.obj); 76 break; 77 case MSG_UPDATE_CALL: 78 mPhone.internalUpdateCall((ParcelableCall) msg.obj); 79 break; 80 case MSG_SET_POST_DIAL_WAIT: { 81 SomeArgs args = (SomeArgs) msg.obj; 82 try { 83 String callId = (String) args.arg1; 84 String remaining = (String) args.arg2; 85 mPhone.internalSetPostDialWait(callId, remaining); 86 } finally { 87 args.recycle(); 88 } 89 break; 90 } 91 case MSG_ON_CALL_AUDIO_STATE_CHANGED: 92 mPhone.internalCallAudioStateChanged((CallAudioState) msg.obj); 93 break; 94 case MSG_BRING_TO_FOREGROUND: 95 mPhone.internalBringToForeground(msg.arg1 == 1); 96 break; 97 case MSG_ON_CAN_ADD_CALL_CHANGED: 98 mPhone.internalSetCanAddCall(msg.arg1 == 1); 99 break; 100 default: 101 break; 102 } 103 } 104 }; 105 106 /** Manages the binder calls so that the implementor does not need to deal with it. */ 107 private final class InCallServiceBinder extends IInCallService.Stub { 108 @Override 109 public void setInCallAdapter(IInCallAdapter inCallAdapter) { 110 mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget(); 111 } 112 113 @Override 114 public void addCall(ParcelableCall call) { 115 mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget(); 116 } 117 118 @Override 119 public void updateCall(ParcelableCall call) { 120 mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget(); 121 } 122 123 @Override 124 public void setPostDial(String callId, String remaining) { 125 // TODO: Unused 126 } 127 128 @Override 129 public void setPostDialWait(String callId, String remaining) { 130 SomeArgs args = SomeArgs.obtain(); 131 args.arg1 = callId; 132 args.arg2 = remaining; 133 mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget(); 134 } 135 136 @Override 137 public void onCallAudioStateChanged(CallAudioState callAudioState) { 138 mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget(); 139 } 140 141 @Override 142 public void bringToForeground(boolean showDialpad) { 143 mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget(); 144 } 145 146 @Override 147 public void onCanAddCallChanged(boolean canAddCall) { 148 mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0) 149 .sendToTarget(); 150 } 151 } 152 153 private Phone.Listener mPhoneListener = new Phone.Listener() { 154 /** ${inheritDoc} */ 155 @Override 156 public void onAudioStateChanged(Phone phone, AudioState audioState) { 157 InCallService.this.onAudioStateChanged(audioState); 158 } 159 160 public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) { 161 InCallService.this.onCallAudioStateChanged(callAudioState); 162 }; 163 164 /** ${inheritDoc} */ 165 @Override 166 public void onBringToForeground(Phone phone, boolean showDialpad) { 167 InCallService.this.onBringToForeground(showDialpad); 168 } 169 170 /** ${inheritDoc} */ 171 @Override 172 public void onCallAdded(Phone phone, Call call) { 173 InCallService.this.onCallAdded(call); 174 } 175 176 /** ${inheritDoc} */ 177 @Override 178 public void onCallRemoved(Phone phone, Call call) { 179 InCallService.this.onCallRemoved(call); 180 } 181 182 /** ${inheritDoc} */ 183 @Override 184 public void onCanAddCallChanged(Phone phone, boolean canAddCall) { 185 InCallService.this.onCanAddCallChanged(canAddCall); 186 } 187 188 }; 189 190 private Phone mPhone; 191 192 public InCallService() { 193 } 194 195 @Override 196 public IBinder onBind(Intent intent) { 197 return new InCallServiceBinder(); 198 } 199 200 @Override 201 public boolean onUnbind(Intent intent) { 202 if (mPhone != null) { 203 Phone oldPhone = mPhone; 204 mPhone = null; 205 206 oldPhone.destroy(); 207 // destroy sets all the calls to disconnected if any live ones still exist. Therefore, 208 // it is important to remove the Listener *after* the call to destroy so that 209 // InCallService.on* callbacks are appropriately called. 210 oldPhone.removeListener(mPhoneListener); 211 212 onPhoneDestroyed(oldPhone); 213 } 214 215 return false; 216 } 217 218 /** 219 * Obtain the {@code Phone} associated with this {@code InCallService}. 220 * 221 * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null} 222 * if the {@code InCallService} is not in a state where it has an associated 223 * {@code Phone}. 224 * @hide 225 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 226 */ 227 @SystemApi 228 @Deprecated 229 public Phone getPhone() { 230 return mPhone; 231 } 232 233 /** 234 * Obtains the current list of {@code Call}s to be displayed by this in-call experience. 235 * 236 * @return A list of the relevant {@code Call}s. 237 */ 238 public final List<Call> getCalls() { 239 return mPhone == null ? Collections.<Call>emptyList() : mPhone.getCalls(); 240 } 241 242 /** 243 * Returns if the device can support additional calls. 244 * 245 * @return Whether the phone supports adding more calls. 246 */ 247 public final boolean canAddCall() { 248 return mPhone == null ? false : mPhone.canAddCall(); 249 } 250 251 /** 252 * Obtains the current phone call audio state. 253 * 254 * @return An object encapsulating the audio state. Returns null if the service is not 255 * fully initialized. 256 * @deprecated Use {@link #getCallAudioState()} instead. 257 * @hide 258 */ 259 @Deprecated 260 public final AudioState getAudioState() { 261 return mPhone == null ? null : mPhone.getAudioState(); 262 } 263 264 /** 265 * Obtains the current phone call audio state. 266 * 267 * @return An object encapsulating the audio state. Returns null if the service is not 268 * fully initialized. 269 */ 270 public final CallAudioState getCallAudioState() { 271 return mPhone == null ? null : mPhone.getCallAudioState(); 272 } 273 274 /** 275 * Sets the microphone mute state. When this request is honored, there will be change to 276 * the {@link #getCallAudioState()}. 277 * 278 * @param state {@code true} if the microphone should be muted; {@code false} otherwise. 279 */ 280 public final void setMuted(boolean state) { 281 if (mPhone != null) { 282 mPhone.setMuted(state); 283 } 284 } 285 286 /** 287 * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will 288 * be change to the {@link #getCallAudioState()}. 289 * 290 * @param route The audio route to use. 291 */ 292 public final void setAudioRoute(int route) { 293 if (mPhone != null) { 294 mPhone.setAudioRoute(route); 295 } 296 } 297 298 /** 299 * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience 300 * to start displaying in-call information to the user. Each instance of {@code InCallService} 301 * will have only one {@code Phone}, and this method will be called exactly once in the lifetime 302 * of the {@code InCallService}. 303 * 304 * @param phone The {@code Phone} object associated with this {@code InCallService}. 305 * @hide 306 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 307 */ 308 @SystemApi 309 @Deprecated 310 public void onPhoneCreated(Phone phone) { 311 } 312 313 /** 314 * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience 315 * to stop displaying in-call information to the user. This method will be called exactly once 316 * in the lifetime of the {@code InCallService}, and it will always be called after a previous 317 * call to {@link #onPhoneCreated(Phone)}. 318 * 319 * @param phone The {@code Phone} object associated with this {@code InCallService}. 320 * @hide 321 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 322 */ 323 @SystemApi 324 @Deprecated 325 public void onPhoneDestroyed(Phone phone) { 326 } 327 328 /** 329 * Called when the audio state changes. 330 * 331 * @param audioState The new {@link AudioState}. 332 * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState) instead}. 333 * @hide 334 */ 335 @Deprecated 336 public void onAudioStateChanged(AudioState audioState) { 337 } 338 339 /** 340 * Called when the audio state changes. 341 * 342 * @param audioState The new {@link CallAudioState}. 343 */ 344 public void onCallAudioStateChanged(CallAudioState audioState) { 345 } 346 347 /** 348 * Called to bring the in-call screen to the foreground. The in-call experience should 349 * respond immediately by coming to the foreground to inform the user of the state of 350 * ongoing {@code Call}s. 351 * 352 * @param showDialpad If true, put up the dialpad when the screen is shown. 353 */ 354 public void onBringToForeground(boolean showDialpad) { 355 } 356 357 /** 358 * Called when a {@code Call} has been added to this in-call session. The in-call user 359 * experience should add necessary state listeners to the specified {@code Call} and 360 * immediately start to show the user information about the existence 361 * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will 362 * include this {@code Call}. 363 * 364 * @param call A newly added {@code Call}. 365 */ 366 public void onCallAdded(Call call) { 367 } 368 369 /** 370 * Called when a {@code Call} has been removed from this in-call session. The in-call user 371 * experience should remove any state listeners from the specified {@code Call} and 372 * immediately stop displaying any information about this {@code Call}. 373 * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}. 374 * 375 * @param call A newly removed {@code Call}. 376 */ 377 public void onCallRemoved(Call call) { 378 } 379 380 /** 381 * Called when the ability to add more calls changes. If the phone cannot 382 * support more calls then {@code canAddCall} is set to {@code false}. If it can, then it 383 * is set to {@code true}. This can be used to control the visibility of UI to add more calls. 384 * 385 * @param canAddCall Indicates whether an additional call can be added. 386 */ 387 public void onCanAddCallChanged(boolean canAddCall) { 388 } 389 390 /** 391 * Used to issue commands to the {@link Connection.VideoProvider} associated with a 392 * {@link Call}. 393 */ 394 public static abstract class VideoCall { 395 396 /** @hide */ 397 public abstract void destroy(); 398 399 /** 400 * Registers a callback to receive commands and state changes for video calls. 401 * 402 * @param callback The video call callback. 403 */ 404 public abstract void registerCallback(VideoCall.Callback callback); 405 406 /** 407 * Registers a callback to receive commands and state changes for video calls. 408 * 409 * @param callback The video call callback. 410 * @param handler A handler which commands and status changes will be delivered to. 411 */ 412 public abstract void registerCallback(VideoCall.Callback callback, Handler handler); 413 414 /** 415 * Clears the video call callback set via {@link #registerCallback}. 416 */ 417 public abstract void unregisterCallback(VideoCall.Callback callback); 418 419 /** 420 * Sets the camera to be used for the outgoing video. 421 * <p> 422 * Handled by {@link Connection.VideoProvider#onSetCamera(String)}. 423 * 424 * @param cameraId The id of the camera (use ids as reported by 425 * {@link CameraManager#getCameraIdList()}). 426 */ 427 public abstract void setCamera(String cameraId); 428 429 /** 430 * Sets the surface to be used for displaying a preview of what the user's camera is 431 * currently capturing. When video transmission is enabled, this is the video signal which 432 * is sent to the remote device. 433 * <p> 434 * Handled by {@link Connection.VideoProvider#onSetPreviewSurface(Surface)}. 435 * 436 * @param surface The {@link Surface}. 437 */ 438 public abstract void setPreviewSurface(Surface surface); 439 440 /** 441 * Sets the surface to be used for displaying the video received from the remote device. 442 * <p> 443 * Handled by {@link Connection.VideoProvider#onSetDisplaySurface(Surface)}. 444 * 445 * @param surface The {@link Surface}. 446 */ 447 public abstract void setDisplaySurface(Surface surface); 448 449 /** 450 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of 451 * the device is 0 degrees. 452 * <p> 453 * Handled by {@link Connection.VideoProvider#onSetDeviceOrientation(int)}. 454 * 455 * @param rotation The device orientation, in degrees. 456 */ 457 public abstract void setDeviceOrientation(int rotation); 458 459 /** 460 * Sets camera zoom ratio. 461 * <p> 462 * Handled by {@link Connection.VideoProvider#onSetZoom(float)}. 463 * 464 * @param value The camera zoom ratio. 465 */ 466 public abstract void setZoom(float value); 467 468 /** 469 * Issues a request to modify the properties of the current video session. 470 * <p> 471 * Example scenarios include: requesting an audio-only call to be upgraded to a 472 * bi-directional video call, turning on or off the user's camera, sending a pause signal 473 * when the {@link InCallService} is no longer the foreground application. 474 * <p> 475 * Handled by 476 * {@link Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}. 477 * 478 * @param requestProfile The requested call video properties. 479 */ 480 public abstract void sendSessionModifyRequest(VideoProfile requestProfile); 481 482 /** 483 * Provides a response to a request to change the current call video session 484 * properties. This should be called in response to a request the {@link InCallService} has 485 * received via {@link VideoCall.Callback#onSessionModifyRequestReceived}. 486 * <p> 487 * Handled by 488 * {@link Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)}. 489 * 490 * @param responseProfile The response call video properties. 491 */ 492 public abstract void sendSessionModifyResponse(VideoProfile responseProfile); 493 494 /** 495 * Issues a request to the {@link Connection.VideoProvider} to retrieve the capabilities 496 * of the current camera. The current camera is selected using 497 * {@link VideoCall#setCamera(String)}. 498 * <p> 499 * Camera capabilities are reported to the caller via 500 * {@link VideoCall.Callback#onCameraCapabilitiesChanged(VideoProfile.CameraCapabilities)}. 501 * <p> 502 * Handled by {@link Connection.VideoProvider#onRequestCameraCapabilities()}. 503 */ 504 public abstract void requestCameraCapabilities(); 505 506 /** 507 * Issues a request to the {@link Connection.VideoProvider} to retrieve the cumulative data 508 * usage for the video component of the current call (in bytes). Data usage is reported 509 * to the caller via {@link VideoCall.Callback#onCallDataUsageChanged}. 510 * <p> 511 * Handled by {@link Connection.VideoProvider#onRequestConnectionDataUsage()}. 512 */ 513 public abstract void requestCallDataUsage(); 514 515 /** 516 * Provides the {@link Connection.VideoProvider} with the {@link Uri} of an image to be 517 * displayed to the peer device when the video signal is paused. 518 * <p> 519 * Handled by {@link Connection.VideoProvider#onSetPauseImage(Uri)}. 520 * 521 * @param uri URI of image to display. 522 */ 523 public abstract void setPauseImage(Uri uri); 524 525 /** 526 * The {@link InCallService} extends this class to provide a means of receiving callbacks 527 * from the {@link Connection.VideoProvider}.<p> 528 * When the {@link InCallService} receives the 529 * {@link Call.Callback#onVideoCallChanged(Call, VideoCall)} callback, it should create an 530 * instance its {@link VideoCall.Callback} implementation and set it on the 531 * {@link VideoCall} using {@link VideoCall#registerCallback(Callback)}. 532 */ 533 public static abstract class Callback { 534 /** 535 * Called when the {@link Connection.VideoProvider} receives a session modification 536 * request is received from the peer device. 537 * <p> 538 * The {@link InCallService} may potentially prompt the user to confirm whether they 539 * wish to accept the request, or decide to automatically accept the request. In either 540 * case the {@link InCallService} should call 541 * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} to indicate the video 542 * profile agreed upon. 543 * <p> 544 * Callback originates from 545 * {@link Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)}. 546 * 547 * @param videoProfile The requested video profile. 548 */ 549 public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile); 550 551 /** 552 * Called when the {@link Connection.VideoProvider} receives a response to a session 553 * modification request previously sent to the peer device. 554 * <p> 555 * The new video state should not be considered active by the {@link InCallService} 556 * until the {@link Call} video state changes (the 557 * {@link Call.Callback#onDetailsChanged(Call, Call.Details)} callback is triggered 558 * when the video state changes). 559 * <p> 560 * Callback originates from 561 * {@link Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile, 562 * VideoProfile)}. 563 * 564 * @param status Status of the session modify request. Valid values are 565 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS}, 566 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL}, 567 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID}, 568 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT}, 569 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE}. 570 * @param requestedProfile The original request which was sent to the peer device. 571 * @param responseProfile The actual profile changes made by the peer device. 572 */ 573 public abstract void onSessionModifyResponseReceived(int status, 574 VideoProfile requestedProfile, VideoProfile responseProfile); 575 576 /** 577 * Handles events related to the current video session which the {@link InCallService} 578 * may wish to handle. These are separate from requested changes to the session due to 579 * the underlying protocol or connection. 580 * <p> 581 * Callback originates from 582 * {@link Connection.VideoProvider#handleCallSessionEvent(int)}. 583 * 584 * @param event The event. Valid values are: 585 * {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE}, 586 * {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME}, 587 * {@link Connection.VideoProvider#SESSION_EVENT_TX_START}, 588 * {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP}, 589 * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE}, 590 * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY}. 591 */ 592 public abstract void onCallSessionEvent(int event); 593 594 /** 595 * Handles a change to the video dimensions from the peer device. This could happen if, 596 * for example, the peer changes orientation of their device, or switches cameras. 597 * <p> 598 * Callback originates from 599 * {@link Connection.VideoProvider#changePeerDimensions(int, int)}. 600 * 601 * @param width The updated peer video width. 602 * @param height The updated peer video height. 603 */ 604 public abstract void onPeerDimensionsChanged(int width, int height); 605 606 /** 607 * Handles a change to the video quality. 608 * <p> 609 * Callback originates from {@link Connection.VideoProvider#changeVideoQuality(int)}. 610 * 611 * @param videoQuality The updated peer video quality. Valid values: 612 * {@link VideoProfile#QUALITY_HIGH}, 613 * {@link VideoProfile#QUALITY_MEDIUM}, 614 * {@link VideoProfile#QUALITY_LOW}, 615 * {@link VideoProfile#QUALITY_DEFAULT}. 616 */ 617 public abstract void onVideoQualityChanged(int videoQuality); 618 619 /** 620 * Handles an update to the total data used for the current video session. 621 * <p> 622 * Used by the {@link Connection.VideoProvider} in response to 623 * {@link VideoCall#requestCallDataUsage()}. May also be called periodically by the 624 * {@link Connection.VideoProvider}. 625 * <p> 626 * Callback originates from {@link Connection.VideoProvider#setCallDataUsage(long)}. 627 * 628 * @param dataUsage The updated data usage (in bytes). 629 */ 630 public abstract void onCallDataUsageChanged(long dataUsage); 631 632 /** 633 * Handles a change in the capabilities of the currently selected camera. 634 * <p> 635 * Used by the {@link Connection.VideoProvider} in response to 636 * {@link VideoCall#requestCameraCapabilities()}. The {@link Connection.VideoProvider} 637 * may also report the camera capabilities after a call to 638 * {@link VideoCall#setCamera(String)}. 639 * <p> 640 * Callback originates from 641 * {@link Connection.VideoProvider#changeCameraCapabilities( 642 * VideoProfile.CameraCapabilities)}. 643 * 644 * @param cameraCapabilities The changed camera capabilities. 645 */ 646 public abstract void onCameraCapabilitiesChanged( 647 VideoProfile.CameraCapabilities cameraCapabilities); 648 } 649 } 650} 651