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 com.android.server.telecom; 18 19 import android.net.Uri; 20 import android.os.Binder; 21 import android.os.Bundle; 22 import android.telecom.Log; 23 import android.telecom.PhoneAccountHandle; 24 25 import com.android.internal.telecom.IInCallAdapter; 26 27 import java.util.List; 28 29 /** 30 * Receives call commands and updates from in-call app and passes them through to CallsManager. 31 * {@link InCallController} creates an instance of this class and passes it to the in-call app after 32 * binding to it. This adapter can receive commands and updates until the in-call app is unbound. 33 */ 34 class InCallAdapter extends IInCallAdapter.Stub { 35 private final CallsManager mCallsManager; 36 private final CallIdMapper mCallIdMapper; 37 private final TelecomSystem.SyncRoot mLock; 38 private final String mOwnerComponentName; 39 40 /** Persists the specified parameters. */ 41 public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper, 42 TelecomSystem.SyncRoot lock, String ownerComponentName) { 43 mCallsManager = callsManager; 44 mCallIdMapper = callIdMapper; 45 mLock = lock; 46 mOwnerComponentName = ownerComponentName; 47 } 48 49 @Override 50 public void answerCall(String callId, int videoState) { 51 try { 52 Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerComponentName); 53 long token = Binder.clearCallingIdentity(); 54 try { 55 synchronized (mLock) { 56 Log.d(this, "answerCall(%s,%d)", callId, videoState); 57 Call call = mCallIdMapper.getCall(callId); 58 if (call != null) { 59 mCallsManager.answerCall(call, videoState); 60 } else { 61 Log.w(this, "answerCall, unknown call id: %s", callId); 62 } 63 } 64 } finally { 65 Binder.restoreCallingIdentity(token); 66 } 67 } finally { 68 Log.endSession(); 69 } 70 } 71 72 @Override 73 public void deflectCall(String callId, Uri address) { 74 try { 75 Log.startSession(LogUtils.Sessions.ICA_DEFLECT_CALL, mOwnerComponentName); 76 long token = Binder.clearCallingIdentity(); 77 try { 78 synchronized (mLock) { 79 Log.i(this, "deflectCall - %s, %s ", callId, Log.pii(address)); 80 Call call = mCallIdMapper.getCall(callId); 81 if (call != null) { 82 mCallsManager.deflectCall(call, address); 83 } else { 84 Log.w(this, "deflectCall, unknown call id: %s", callId); 85 } 86 } 87 } finally { 88 Binder.restoreCallingIdentity(token); 89 } 90 } finally { 91 Log.endSession(); 92 } 93 } 94 95 @Override 96 public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) { 97 try { 98 Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName); 99 // Check to make sure the in-call app's user isn't restricted from sending SMS. If so, 100 // silently drop the outgoing message. Also drop message if the screen is locked. 101 if (!mCallsManager.isReplyWithSmsAllowed(Binder.getCallingUid())) { 102 rejectWithMessage = false; 103 textMessage = null; 104 } 105 long token = Binder.clearCallingIdentity(); 106 try { 107 synchronized (mLock) { 108 Log.d(this, "rejectCall(%s,%b,%s)", callId, rejectWithMessage, textMessage); 109 Call call = mCallIdMapper.getCall(callId); 110 if (call != null) { 111 mCallsManager.rejectCall(call, rejectWithMessage, textMessage); 112 } else { 113 Log.w(this, "setRingback, unknown call id: %s", callId); 114 } 115 } 116 } finally { 117 Binder.restoreCallingIdentity(token); 118 } 119 } finally { 120 Log.endSession(); 121 } 122 } 123 124 @Override 125 public void playDtmfTone(String callId, char digit) { 126 try { 127 Log.startSession("ICA.pDT", mOwnerComponentName); 128 long token = Binder.clearCallingIdentity(); 129 try { 130 synchronized (mLock) { 131 Log.d(this, "playDtmfTone(%s,%c)", callId, digit); 132 Call call = mCallIdMapper.getCall(callId); 133 if (call != null) { 134 mCallsManager.playDtmfTone(call, digit); 135 } else { 136 Log.w(this, "playDtmfTone, unknown call id: %s", callId); 137 } 138 } 139 } finally { 140 Binder.restoreCallingIdentity(token); 141 } 142 } finally { 143 Log.endSession(); 144 } 145 } 146 147 @Override 148 public void stopDtmfTone(String callId) { 149 try { 150 Log.startSession("ICA.sDT", mOwnerComponentName); 151 long token = Binder.clearCallingIdentity(); 152 try { 153 synchronized (mLock) { 154 Log.d(this, "stopDtmfTone(%s)", callId); 155 Call call = mCallIdMapper.getCall(callId); 156 if (call != null) { 157 mCallsManager.stopDtmfTone(call); 158 } else { 159 Log.w(this, "stopDtmfTone, unknown call id: %s", callId); 160 } 161 } 162 } finally { 163 Binder.restoreCallingIdentity(token); 164 } 165 } finally { 166 Log.endSession(); 167 } 168 } 169 170 @Override 171 public void postDialContinue(String callId, boolean proceed) { 172 try { 173 Log.startSession("ICA.pDC", mOwnerComponentName); 174 long token = Binder.clearCallingIdentity(); 175 try { 176 synchronized (mLock) { 177 Log.d(this, "postDialContinue(%s)", callId); 178 Call call = mCallIdMapper.getCall(callId); 179 if (call != null) { 180 mCallsManager.postDialContinue(call, proceed); 181 } else { 182 Log.w(this, "postDialContinue, unknown call id: %s", callId); 183 } 184 } 185 } finally { 186 Binder.restoreCallingIdentity(token); 187 } 188 } finally { 189 Log.endSession(); 190 } 191 } 192 193 @Override 194 public void disconnectCall(String callId) { 195 try { 196 Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName); 197 long token = Binder.clearCallingIdentity(); 198 try { 199 synchronized (mLock) { 200 Log.v(this, "disconnectCall: %s", callId); 201 Call call = mCallIdMapper.getCall(callId); 202 if (call != null) { 203 mCallsManager.disconnectCall(call); 204 } else { 205 Log.w(this, "disconnectCall, unknown call id: %s", callId); 206 } 207 } 208 } finally { 209 Binder.restoreCallingIdentity(token); 210 } 211 } finally { 212 Log.endSession(); 213 } 214 } 215 216 @Override 217 public void holdCall(String callId) { 218 try { 219 Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerComponentName); 220 long token = Binder.clearCallingIdentity(); 221 try { 222 synchronized (mLock) { 223 Call call = mCallIdMapper.getCall(callId); 224 if (call != null) { 225 mCallsManager.holdCall(call); 226 } else { 227 Log.w(this, "holdCall, unknown call id: %s", callId); 228 } 229 } 230 } finally { 231 Binder.restoreCallingIdentity(token); 232 } 233 } finally { 234 Log.endSession(); 235 } 236 } 237 238 @Override 239 public void unholdCall(String callId) { 240 try { 241 Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName); 242 long token = Binder.clearCallingIdentity(); 243 try { 244 synchronized (mLock) { 245 Call call = mCallIdMapper.getCall(callId); 246 if (call != null) { 247 mCallsManager.unholdCall(call); 248 } else { 249 Log.w(this, "unholdCall, unknown call id: %s", callId); 250 } 251 } 252 } finally { 253 Binder.restoreCallingIdentity(token); 254 } 255 } finally { 256 Log.endSession(); 257 } 258 } 259 260 @Override 261 public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, 262 boolean setDefault) { 263 try { 264 Log.startSession("ICA.pAS", mOwnerComponentName); 265 long token = Binder.clearCallingIdentity(); 266 try { 267 synchronized (mLock) { 268 Call call = mCallIdMapper.getCall(callId); 269 if (call != null) { 270 mCallsManager.phoneAccountSelected(call, accountHandle, setDefault); 271 } else { 272 Log.w(this, "phoneAccountSelected, unknown call id: %s", callId); 273 } 274 } 275 } finally { 276 Binder.restoreCallingIdentity(token); 277 } 278 } finally { 279 Log.endSession(); 280 } 281 } 282 283 @Override 284 public void mute(boolean shouldMute) { 285 try { 286 Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerComponentName); 287 long token = Binder.clearCallingIdentity(); 288 try { 289 synchronized (mLock) { 290 mCallsManager.mute(shouldMute); 291 } 292 } finally { 293 Binder.restoreCallingIdentity(token); 294 } 295 } finally { 296 Log.endSession(); 297 } 298 } 299 300 @Override 301 public void setAudioRoute(int route, String bluetoothAddress) { 302 try { 303 Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName); 304 long token = Binder.clearCallingIdentity(); 305 try { 306 synchronized (mLock) { 307 mCallsManager.setAudioRoute(route, bluetoothAddress); 308 } 309 } finally { 310 Binder.restoreCallingIdentity(token); 311 } 312 } finally { 313 Log.endSession(); 314 } 315 } 316 317 @Override 318 public void conference(String callId, String otherCallId) { 319 try { 320 Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerComponentName); 321 long token = Binder.clearCallingIdentity(); 322 try { 323 synchronized (mLock) { 324 Call call = mCallIdMapper.getCall(callId); 325 Call otherCall = mCallIdMapper.getCall(otherCallId); 326 if (call != null && otherCall != null) { 327 mCallsManager.conference(call, otherCall); 328 } else { 329 Log.w(this, "conference, unknown call id: %s or %s", callId, otherCallId); 330 } 331 } 332 } finally { 333 Binder.restoreCallingIdentity(token); 334 } 335 } finally { 336 Log.endSession(); 337 } 338 } 339 340 @Override 341 public void splitFromConference(String callId) { 342 try { 343 Log.startSession("ICA.sFC", mOwnerComponentName); 344 long token = Binder.clearCallingIdentity(); 345 try { 346 synchronized (mLock) { 347 Call call = mCallIdMapper.getCall(callId); 348 if (call != null) { 349 call.splitFromConference(); 350 } else { 351 Log.w(this, "splitFromConference, unknown call id: %s", callId); 352 } 353 } 354 } finally { 355 Binder.restoreCallingIdentity(token); 356 } 357 } finally { 358 Log.endSession(); 359 } 360 } 361 362 @Override 363 public void mergeConference(String callId) { 364 try { 365 Log.startSession("ICA.mC", mOwnerComponentName); 366 long token = Binder.clearCallingIdentity(); 367 try { 368 synchronized (mLock) { 369 Call call = mCallIdMapper.getCall(callId); 370 if (call != null) { 371 call.mergeConference(); 372 } else { 373 Log.w(this, "mergeConference, unknown call id: %s", callId); 374 } 375 } 376 } finally { 377 Binder.restoreCallingIdentity(token); 378 } 379 } finally { 380 Log.endSession(); 381 } 382 } 383 384 @Override 385 public void swapConference(String callId) { 386 try { 387 Log.startSession("ICA.sC", mOwnerComponentName); 388 long token = Binder.clearCallingIdentity(); 389 try { 390 synchronized (mLock) { 391 Call call = mCallIdMapper.getCall(callId); 392 if (call != null) { 393 call.swapConference(); 394 } else { 395 Log.w(this, "swapConference, unknown call id: %s", callId); 396 } 397 } 398 } finally { 399 Binder.restoreCallingIdentity(token); 400 } 401 } finally { 402 Log.endSession(); 403 } 404 } 405 406 @Override 407 public void pullExternalCall(String callId) { 408 try { 409 Log.startSession("ICA.pEC", mOwnerComponentName); 410 long token = Binder.clearCallingIdentity(); 411 try { 412 synchronized (mLock) { 413 Call call = mCallIdMapper.getCall(callId); 414 if (call != null) { 415 call.pullExternalCall(); 416 } else { 417 Log.w(this, "pullExternalCall, unknown call id: %s", callId); 418 } 419 } 420 } finally { 421 Binder.restoreCallingIdentity(token); 422 } 423 } finally { 424 Log.endSession(); 425 } 426 } 427 428 @Override 429 public void sendCallEvent(String callId, String event, int targetSdkVer, Bundle extras) { 430 try { 431 Log.startSession("ICA.sCE", mOwnerComponentName); 432 long token = Binder.clearCallingIdentity(); 433 try { 434 synchronized (mLock) { 435 Call call = mCallIdMapper.getCall(callId); 436 if (call != null) { 437 call.sendCallEvent(event, targetSdkVer, extras); 438 } else { 439 Log.w(this, "sendCallEvent, unknown call id: %s", callId); 440 } 441 } 442 } finally { 443 Binder.restoreCallingIdentity(token); 444 } 445 } finally { 446 Log.endSession(); 447 } 448 } 449 450 @Override 451 public void putExtras(String callId, Bundle extras) { 452 try { 453 Log.startSession("ICA.pE", mOwnerComponentName); 454 long token = Binder.clearCallingIdentity(); 455 try { 456 synchronized (mLock) { 457 Call call = mCallIdMapper.getCall(callId); 458 if (call != null) { 459 call.putExtras(Call.SOURCE_INCALL_SERVICE, extras); 460 } else { 461 Log.w(this, "putExtras, unknown call id: %s", callId); 462 } 463 } 464 } finally { 465 Binder.restoreCallingIdentity(token); 466 } 467 } finally { 468 Log.endSession(); 469 } 470 } 471 472 @Override 473 public void removeExtras(String callId, List<String> keys) { 474 try { 475 Log.startSession("ICA.rE", mOwnerComponentName); 476 long token = Binder.clearCallingIdentity(); 477 try { 478 synchronized (mLock) { 479 Call call = mCallIdMapper.getCall(callId); 480 if (call != null) { 481 call.removeExtras(Call.SOURCE_INCALL_SERVICE, keys); 482 } else { 483 Log.w(this, "removeExtra, unknown call id: %s", callId); 484 } 485 } 486 } finally { 487 Binder.restoreCallingIdentity(token); 488 } 489 } finally { 490 Log.endSession(); 491 } 492 } 493 494 @Override 495 public void turnOnProximitySensor() { 496 try { 497 Log.startSession("ICA.tOnPS", mOwnerComponentName); 498 long token = Binder.clearCallingIdentity(); 499 try { 500 synchronized (mLock) { 501 mCallsManager.turnOnProximitySensor(); 502 } 503 } finally { 504 Binder.restoreCallingIdentity(token); 505 } 506 } finally { 507 Log.endSession(); 508 } 509 } 510 511 @Override 512 public void turnOffProximitySensor(boolean screenOnImmediately) { 513 try { 514 Log.startSession("ICA.tOffPS", mOwnerComponentName); 515 long token = Binder.clearCallingIdentity(); 516 try { 517 synchronized (mLock) { 518 mCallsManager.turnOffProximitySensor(screenOnImmediately); 519 } 520 } finally { 521 Binder.restoreCallingIdentity(token); 522 } 523 } finally { 524 Log.endSession(); 525 } 526 } 527 528 @Override 529 public void sendRttRequest(String callId) { 530 try { 531 Log.startSession("ICA.sRR"); 532 long token = Binder.clearCallingIdentity(); 533 try { 534 synchronized (mLock) { 535 Call call = mCallIdMapper.getCall(callId); 536 if (call != null) { 537 call.sendRttRequest(); 538 } else { 539 Log.w(this, "stopRtt(): call %s not found", callId); 540 } 541 } 542 } finally { 543 Binder.restoreCallingIdentity(token); 544 } 545 } finally { 546 Log.endSession(); 547 } 548 } 549 550 @Override 551 public void respondToRttRequest(String callId, int id, boolean accept) { 552 try { 553 Log.startSession("ICA.rTRR"); 554 long token = Binder.clearCallingIdentity(); 555 try { 556 synchronized (mLock) { 557 Call call = mCallIdMapper.getCall(callId); 558 if (call != null) { 559 call.handleRttRequestResponse(id, accept); 560 } else { 561 Log.w(this, "respondToRttRequest(): call %s not found", callId); 562 } 563 } 564 } finally { 565 Binder.restoreCallingIdentity(token); 566 } 567 } finally { 568 Log.endSession(); 569 } 570 } 571 572 @Override 573 public void stopRtt(String callId) { 574 try { 575 Log.startSession("ICA.sRTT"); 576 long token = Binder.clearCallingIdentity(); 577 try { 578 synchronized (mLock) { 579 Call call = mCallIdMapper.getCall(callId); 580 if (call != null) { 581 call.stopRtt(); 582 } else { 583 Log.w(this, "stopRtt(): call %s not found", callId); 584 } 585 } 586 } finally { 587 Binder.restoreCallingIdentity(token); 588 } 589 } finally { 590 Log.endSession(); 591 } 592 } 593 594 @Override 595 public void setRttMode(String callId, int mode) { 596 try { 597 Log.startSession("ICA.sRM"); 598 long token = Binder.clearCallingIdentity(); 599 try { 600 synchronized (mLock) { 601 // TODO 602 } 603 } finally { 604 Binder.restoreCallingIdentity(token); 605 } 606 } finally { 607 Log.endSession(); 608 } 609 } 610 611 @Override 612 public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState, 613 Bundle extras) { 614 try { 615 Log.startSession("ICA.hT", mOwnerComponentName); 616 long token = Binder.clearCallingIdentity(); 617 try { 618 synchronized (mLock) { 619 Call call = mCallIdMapper.getCall(callId); 620 if (call != null) { 621 call.handoverTo(destAcct, videoState, extras); 622 } else { 623 Log.w(this, "handoverTo, unknown call id: %s", callId); 624 } 625 } 626 } finally { 627 Binder.restoreCallingIdentity(token); 628 } 629 } finally { 630 Log.endSession(); 631 } 632 } 633 } 634