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