1 /* 2 * Copyright (C) 2014 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.bluetooth.BluetoothDevice; 21 import android.net.Uri; 22 import android.os.Binder; 23 import android.os.Bundle; 24 import android.os.OutcomeReceiver; 25 import android.os.RemoteException; 26 import android.os.ResultReceiver; 27 28 import com.android.internal.telecom.IInCallAdapter; 29 30 import java.util.List; 31 import java.util.concurrent.Executor; 32 33 /** 34 * Receives commands from {@link InCallService} implementations which should be executed by 35 * Telecom. When Telecom binds to a {@link InCallService}, an instance of this class is given to 36 * the in-call service through which it can manipulate live (active, dialing, ringing) calls. When 37 * the in-call service is notified of new calls, it can use the 38 * given call IDs to execute commands such as {@link #answerCall} for incoming calls or 39 * {@link #disconnectCall} for active calls the user would like to end. Some commands are only 40 * appropriate for calls in certain states; please consult each method for such limitations. 41 * <p> 42 * The adapter will stop functioning when there are no more calls. 43 * 44 * @hide 45 */ 46 public final class InCallAdapter { 47 private final IInCallAdapter mAdapter; 48 49 /** 50 * {@hide} 51 */ InCallAdapter(IInCallAdapter adapter)52 public InCallAdapter(IInCallAdapter adapter) { 53 mAdapter = adapter; 54 } 55 56 /** 57 * Instructs Telecom to answer the specified call. 58 * 59 * @param callId The identifier of the call to answer. 60 * @param videoState The video state in which to answer the call. 61 */ answerCall(String callId, int videoState)62 public void answerCall(String callId, int videoState) { 63 try { 64 mAdapter.answerCall(callId, videoState); 65 } catch (RemoteException e) { 66 } 67 } 68 69 /** 70 * Instructs Telecom to deflect the specified call. 71 * 72 * @param callId The identifier of the call to deflect. 73 * @param address The address to deflect. 74 */ deflectCall(String callId, Uri address)75 public void deflectCall(String callId, Uri address) { 76 try { 77 mAdapter.deflectCall(callId, address); 78 } catch (RemoteException e) { 79 } 80 } 81 82 /** 83 * Instructs Telecom to reject the specified call. 84 * 85 * @param callId The identifier of the call to reject. 86 * @param rejectWithMessage Whether to reject with a text message. 87 * @param textMessage An optional text message with which to respond. 88 */ rejectCall(String callId, boolean rejectWithMessage, String textMessage)89 public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) { 90 try { 91 mAdapter.rejectCall(callId, rejectWithMessage, textMessage); 92 } catch (RemoteException e) { 93 } 94 } 95 96 /** 97 * Instructs Telecom to reject the specified call. 98 * 99 * @param callId The identifier of the call to reject. 100 * @param rejectReason The reason the call was rejected. 101 */ rejectCall(String callId, @Call.RejectReason int rejectReason)102 public void rejectCall(String callId, @Call.RejectReason int rejectReason) { 103 try { 104 mAdapter.rejectCallWithReason(callId, rejectReason); 105 } catch (RemoteException e) { 106 } 107 } 108 109 /** 110 * Instructs Telecom to transfer the specified call. 111 * 112 * @param callId The identifier of the call to transfer. 113 * @param targetNumber The address to transfer to. 114 * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer, 115 * if {@code false}, it will initiate unconfirmed transfer. 116 */ transferCall(@onNull String callId, @NonNull Uri targetNumber, boolean isConfirmationRequired)117 public void transferCall(@NonNull String callId, @NonNull Uri targetNumber, 118 boolean isConfirmationRequired) { 119 try { 120 mAdapter.transferCall(callId, targetNumber, isConfirmationRequired); 121 } catch (RemoteException e) { 122 } 123 } 124 125 /** 126 * Instructs Telecom to transfer the specified call to another ongoing call. 127 * 128 * @param callId The identifier of the call to transfer. 129 * @param otherCallId The identifier of the other call to which this will be transferred. 130 */ transferCall(@onNull String callId, @NonNull String otherCallId)131 public void transferCall(@NonNull String callId, @NonNull String otherCallId) { 132 try { 133 mAdapter.consultativeTransfer(callId, otherCallId); 134 } catch (RemoteException e) { 135 } 136 } 137 138 /** 139 * Instructs Telecom to disconnect the specified call. 140 * 141 * @param callId The identifier of the call to disconnect. 142 */ disconnectCall(String callId)143 public void disconnectCall(String callId) { 144 try { 145 mAdapter.disconnectCall(callId); 146 } catch (RemoteException e) { 147 } 148 } 149 150 /** 151 * Instructs Telecom to put the specified call on hold. 152 * 153 * @param callId The identifier of the call to put on hold. 154 */ holdCall(String callId)155 public void holdCall(String callId) { 156 try { 157 mAdapter.holdCall(callId); 158 } catch (RemoteException e) { 159 } 160 } 161 162 /** 163 * Instructs Telecom to release the specified call from hold. 164 * 165 * @param callId The identifier of the call to release from hold. 166 */ unholdCall(String callId)167 public void unholdCall(String callId) { 168 try { 169 mAdapter.unholdCall(callId); 170 } catch (RemoteException e) { 171 } 172 } 173 174 /** 175 * Mute the microphone. 176 * 177 * @param shouldMute True if the microphone should be muted. 178 */ mute(boolean shouldMute)179 public void mute(boolean shouldMute) { 180 try { 181 mAdapter.mute(shouldMute); 182 } catch (RemoteException e) { 183 } 184 } 185 186 /** 187 * Sets the audio route (speaker, bluetooth, etc...). See {@link CallAudioState}. 188 * 189 * @param route The audio route to use. 190 */ setAudioRoute(int route)191 public void setAudioRoute(int route) { 192 try { 193 mAdapter.setAudioRoute(route, null); 194 } catch (RemoteException e) { 195 } 196 } 197 198 /** 199 * @see Call#enterBackgroundAudioProcessing() 200 */ enterBackgroundAudioProcessing(String callId)201 public void enterBackgroundAudioProcessing(String callId) { 202 try { 203 mAdapter.enterBackgroundAudioProcessing(callId); 204 } catch (RemoteException e) { 205 } 206 } 207 208 /** 209 * @see Call#exitBackgroundAudioProcessing(boolean) 210 */ exitBackgroundAudioProcessing(String callId, boolean shouldRing)211 public void exitBackgroundAudioProcessing(String callId, boolean shouldRing) { 212 try { 213 mAdapter.exitBackgroundAudioProcessing(callId, shouldRing); 214 } catch (RemoteException e) { 215 } 216 } 217 218 /** 219 * Request audio routing to a specific bluetooth device. Calling this method may result in 220 * the device routing audio to a different bluetooth device than the one specified. A list of 221 * available devices can be obtained via {@link CallAudioState#getSupportedBluetoothDevices()} 222 * 223 * @param bluetoothAddress The address of the bluetooth device to connect to, as returned by 224 * {@link BluetoothDevice#getAddress()}, or {@code null} if no device is preferred. 225 */ requestBluetoothAudio(String bluetoothAddress)226 public void requestBluetoothAudio(String bluetoothAddress) { 227 try { 228 mAdapter.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH, bluetoothAddress); 229 } catch (RemoteException e) { 230 } 231 } 232 233 /** 234 * Request audio routing to a specific CallEndpoint.. See {@link CallEndpoint}. 235 * 236 * @param endpoint The call endpoint to use. 237 * @param executor The executor of where the callback will execute. 238 * @param callback The callback to notify the result of the endpoint change. 239 */ requestCallEndpointChange(CallEndpoint endpoint, Executor executor, OutcomeReceiver<Void, CallEndpointException> callback)240 public void requestCallEndpointChange(CallEndpoint endpoint, Executor executor, 241 OutcomeReceiver<Void, CallEndpointException> callback) { 242 try { 243 mAdapter.requestCallEndpointChange(endpoint, new ResultReceiver(null) { 244 @Override 245 protected void onReceiveResult(int resultCode, Bundle result) { 246 super.onReceiveResult(resultCode, result); 247 final long identity = Binder.clearCallingIdentity(); 248 try { 249 if (resultCode == CallEndpoint.ENDPOINT_OPERATION_SUCCESS) { 250 executor.execute(() -> callback.onResult(null)); 251 } else { 252 executor.execute(() -> callback.onError( 253 result.getParcelable(CallEndpointException.CHANGE_ERROR, 254 CallEndpointException.class))); 255 } 256 } finally { 257 Binder.restoreCallingIdentity(identity); 258 } 259 } 260 }); 261 } catch (RemoteException e) { 262 Log.d(this, "Remote exception calling requestCallEndpointChange"); 263 } 264 } 265 266 /** 267 * Instructs Telecom to play a dual-tone multi-frequency signaling (DTMF) tone in a call. 268 * 269 * Any other currently playing DTMF tone in the specified call is immediately stopped. 270 * 271 * @param callId The unique ID of the call in which the tone will be played. 272 * @param digit A character representing the DTMF digit for which to play the tone. This 273 * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}. 274 */ playDtmfTone(String callId, char digit)275 public void playDtmfTone(String callId, char digit) { 276 try { 277 mAdapter.playDtmfTone(callId, digit); 278 } catch (RemoteException e) { 279 } 280 } 281 282 /** 283 * Instructs Telecom to stop any dual-tone multi-frequency signaling (DTMF) tone currently 284 * playing. 285 * 286 * DTMF tones are played by calling {@link #playDtmfTone(String,char)}. If no DTMF tone is 287 * currently playing, this method will do nothing. 288 * 289 * @param callId The unique ID of the call in which any currently playing tone will be stopped. 290 */ stopDtmfTone(String callId)291 public void stopDtmfTone(String callId) { 292 try { 293 mAdapter.stopDtmfTone(callId); 294 } catch (RemoteException e) { 295 } 296 } 297 298 /** 299 * Instructs Telecom to continue playing a post-dial DTMF string. 300 * 301 * A post-dial DTMF string is a string of digits entered after a phone number, when dialed, 302 * that are immediately sent as DTMF tones to the recipient as soon as the connection is made. 303 * While these tones are playing, Telecom will notify the {@link InCallService} that the call 304 * is in the post dial state. 305 * 306 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, Telecom 307 * will temporarily pause playing the tones for a pre-defined period of time. 308 * 309 * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, Telecom 310 * will pause playing the tones and notify the {@link InCallService} that the call is in the 311 * post dial wait state. When the user decides to continue the postdial sequence, the 312 * {@link InCallService} should invoke the {@link #postDialContinue(String,boolean)} method. 313 * 314 * @param callId The unique ID of the call for which postdial string playing should continue. 315 * @param proceed Whether or not to continue with the post-dial sequence. 316 */ postDialContinue(String callId, boolean proceed)317 public void postDialContinue(String callId, boolean proceed) { 318 try { 319 mAdapter.postDialContinue(callId, proceed); 320 } catch (RemoteException e) { 321 } 322 } 323 324 /** 325 * Instructs Telecom to add a PhoneAccountHandle to the specified call. 326 * 327 * @param callId The identifier of the call. 328 * @param accountHandle The PhoneAccountHandle through which to place the call. 329 * @param setDefault {@code True} if this account should be set as the default for calls. 330 */ phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, boolean setDefault)331 public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, 332 boolean setDefault) { 333 try { 334 mAdapter.phoneAccountSelected(callId, accountHandle, setDefault); 335 } catch (RemoteException e) { 336 } 337 } 338 339 /** 340 * Instructs Telecom to conference the specified call. 341 * 342 * @param callId The unique ID of the call. 343 * @hide 344 */ conference(String callId, String otherCallId)345 public void conference(String callId, String otherCallId) { 346 try { 347 mAdapter.conference(callId, otherCallId); 348 } catch (RemoteException ignored) { 349 } 350 } 351 352 /** 353 * Instructs Telecom to pull participants to existing call 354 * 355 * @param callId The unique ID of the call. 356 * @param participants participants to be pulled to existing call. 357 */ addConferenceParticipants(String callId, List<Uri> participants)358 public void addConferenceParticipants(String callId, List<Uri> participants) { 359 try { 360 mAdapter.addConferenceParticipants(callId, participants); 361 } catch (RemoteException ignored) { 362 } 363 } 364 365 366 /** 367 * Instructs Telecom to split the specified call from any conference call with which it may be 368 * connected. 369 * 370 * @param callId The unique ID of the call. 371 * @hide 372 */ splitFromConference(String callId)373 public void splitFromConference(String callId) { 374 try { 375 mAdapter.splitFromConference(callId); 376 } catch (RemoteException ignored) { 377 } 378 } 379 380 /** 381 * Instructs Telecom to merge child calls of the specified conference call. 382 */ mergeConference(String callId)383 public void mergeConference(String callId) { 384 try { 385 mAdapter.mergeConference(callId); 386 } catch (RemoteException ignored) { 387 } 388 } 389 390 /** 391 * Instructs Telecom to swap the child calls of the specified conference call. 392 */ swapConference(String callId)393 public void swapConference(String callId) { 394 try { 395 mAdapter.swapConference(callId); 396 } catch (RemoteException ignored) { 397 } 398 } 399 400 /** 401 * Instructs Telecom to pull an external call to the local device. 402 * 403 * @param callId The callId to pull. 404 */ pullExternalCall(String callId)405 public void pullExternalCall(String callId) { 406 try { 407 mAdapter.pullExternalCall(callId); 408 } catch (RemoteException ignored) { 409 } 410 } 411 412 /** 413 * Intructs Telecom to send a call event. 414 * 415 * @param callId The callId to send the event for. 416 * @param event The event. 417 * @param targetSdkVer Target sdk version of the app calling this api 418 * @param extras Extras associated with the event. 419 */ sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras)420 public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) { 421 try { 422 mAdapter.sendCallEvent(callId, event, targetSdkVer, extras); 423 } catch (RemoteException ignored) { 424 } 425 } 426 427 /** 428 * Intructs Telecom to add extras to a call. 429 * 430 * @param callId The callId to add the extras to. 431 * @param extras The extras. 432 */ putExtras(String callId, Bundle extras)433 public void putExtras(String callId, Bundle extras) { 434 try { 435 mAdapter.putExtras(callId, extras); 436 } catch (RemoteException ignored) { 437 } 438 } 439 440 /** 441 * Intructs Telecom to add an extra to a call. 442 * 443 * @param callId The callId to add the extras to. 444 * @param key The extra key. 445 * @param value The extra value. 446 */ putExtra(String callId, String key, boolean value)447 public void putExtra(String callId, String key, boolean value) { 448 try { 449 Bundle bundle = new Bundle(); 450 bundle.putBoolean(key, value); 451 mAdapter.putExtras(callId, bundle); 452 } catch (RemoteException ignored) { 453 } 454 } 455 456 /** 457 * Intructs Telecom to add an extra to a call. 458 * 459 * @param callId The callId to add the extras to. 460 * @param key The extra key. 461 * @param value The extra value. 462 */ putExtra(String callId, String key, int value)463 public void putExtra(String callId, String key, int value) { 464 try { 465 Bundle bundle = new Bundle(); 466 bundle.putInt(key, value); 467 mAdapter.putExtras(callId, bundle); 468 } catch (RemoteException ignored) { 469 } 470 } 471 472 /** 473 * Intructs Telecom to add an extra to a call. 474 * 475 * @param callId The callId to add the extras to. 476 * @param key The extra key. 477 * @param value The extra value. 478 */ putExtra(String callId, String key, String value)479 public void putExtra(String callId, String key, String value) { 480 try { 481 Bundle bundle = new Bundle(); 482 bundle.putString(key, value); 483 mAdapter.putExtras(callId, bundle); 484 } catch (RemoteException ignored) { 485 } 486 } 487 488 /** 489 * Intructs Telecom to remove extras from a call. 490 * @param callId The callId to remove the extras from. 491 * @param keys The extra keys to remove. 492 */ removeExtras(String callId, List<String> keys)493 public void removeExtras(String callId, List<String> keys) { 494 try { 495 mAdapter.removeExtras(callId, keys); 496 } catch (RemoteException ignored) { 497 } 498 } 499 500 /** 501 * Instructs Telecom to turn the proximity sensor on. 502 */ turnProximitySensorOn()503 public void turnProximitySensorOn() { 504 try { 505 mAdapter.turnOnProximitySensor(); 506 } catch (RemoteException ignored) { 507 } 508 } 509 510 /** 511 * Instructs Telecom to turn the proximity sensor off. 512 * 513 * @param screenOnImmediately If true, the screen will be turned on immediately if it was 514 * previously off. Otherwise, the screen will only be turned on after the proximity sensor 515 * is no longer triggered. 516 */ turnProximitySensorOff(boolean screenOnImmediately)517 public void turnProximitySensorOff(boolean screenOnImmediately) { 518 try { 519 mAdapter.turnOffProximitySensor(screenOnImmediately); 520 } catch (RemoteException ignored) { 521 } 522 } 523 524 /** 525 * Sends an RTT upgrade request to the remote end of the connection. 526 */ sendRttRequest(String callId)527 public void sendRttRequest(String callId) { 528 try { 529 mAdapter.sendRttRequest(callId); 530 } catch (RemoteException ignored) { 531 } 532 } 533 534 /** 535 * Responds to an RTT upgrade request initiated from the remote end. 536 * 537 * @param id the ID of the request as specified by Telecom 538 * @param accept Whether the request should be accepted. 539 */ respondToRttRequest(String callId, int id, boolean accept)540 public void respondToRttRequest(String callId, int id, boolean accept) { 541 try { 542 mAdapter.respondToRttRequest(callId, id, accept); 543 } catch (RemoteException ignored) { 544 } 545 } 546 547 /** 548 * Instructs Telecom to shut down the RTT communication channel. 549 */ stopRtt(String callId)550 public void stopRtt(String callId) { 551 try { 552 mAdapter.stopRtt(callId); 553 } catch (RemoteException ignored) { 554 } 555 } 556 557 /** 558 * Sets the RTT audio mode. 559 * @param mode the desired RTT audio mode 560 */ setRttMode(String callId, int mode)561 public void setRttMode(String callId, int mode) { 562 try { 563 mAdapter.setRttMode(callId, mode); 564 } catch (RemoteException ignored) { 565 } 566 } 567 568 569 /** 570 * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified 571 * by destAcct. 572 * @param callId The callId of the Call which calls this function. 573 * @param destAcct ConnectionService to which the call should be handed over. 574 * @param videoState The video state desired after the handover. 575 * @param extras Extra information to be passed to ConnectionService 576 */ handoverTo(String callId, PhoneAccountHandle destAcct, int videoState, Bundle extras)577 public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState, 578 Bundle extras) { 579 try { 580 mAdapter.handoverTo(callId, destAcct, videoState, extras); 581 } catch (RemoteException ignored) { 582 } 583 } 584 } 585