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.os.Binder; 20 import android.os.Bundle; 21 import android.telecom.PhoneAccountHandle; 22 23 import com.android.internal.telecom.IInCallAdapter; 24 25 import java.util.List; 26 27 /** 28 * Receives call commands and updates from in-call app and passes them through to CallsManager. 29 * {@link InCallController} creates an instance of this class and passes it to the in-call app after 30 * binding to it. This adapter can receive commands and updates until the in-call app is unbound. 31 */ 32 class InCallAdapter extends IInCallAdapter.Stub { 33 private final CallsManager mCallsManager; 34 private final CallIdMapper mCallIdMapper; 35 private final TelecomSystem.SyncRoot mLock; 36 private final String mOwnerComponentName; 37 38 /** Persists the specified parameters. */ 39 public InCallAdapter(CallsManager callsManager, CallIdMapper callIdMapper, 40 TelecomSystem.SyncRoot lock, String ownerComponentName) { 41 mCallsManager = callsManager; 42 mCallIdMapper = callIdMapper; 43 mLock = lock; 44 mOwnerComponentName = ownerComponentName; 45 } 46 47 @Override 48 public void answerCall(String callId, int videoState) { 49 try { 50 Log.startSession(Log.Sessions.ICA_ANSWER_CALL, mOwnerComponentName); 51 long token = Binder.clearCallingIdentity(); 52 try { 53 synchronized (mLock) { 54 Log.d(this, "answerCall(%s,%d)", callId, videoState); 55 Call call = mCallIdMapper.getCall(callId); 56 if (call != null) { 57 mCallsManager.answerCall(call, videoState); 58 } else { 59 Log.w(this, "answerCall, unknown call id: %s", callId); 60 } 61 } 62 } finally { 63 Binder.restoreCallingIdentity(token); 64 } 65 } finally { 66 Log.endSession(); 67 } 68 } 69 70 @Override 71 public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) { 72 try { 73 Log.startSession(Log.Sessions.ICA_REJECT_CALL, mOwnerComponentName); 74 long token = Binder.clearCallingIdentity(); 75 try { 76 synchronized (mLock) { 77 Log.d(this, "rejectCall(%s,%b,%s)", callId, rejectWithMessage, textMessage); 78 Call call = mCallIdMapper.getCall(callId); 79 if (call != null) { 80 mCallsManager.rejectCall(call, rejectWithMessage, textMessage); 81 } else { 82 Log.w(this, "setRingback, unknown call id: %s", callId); 83 } 84 } 85 } finally { 86 Binder.restoreCallingIdentity(token); 87 } 88 } finally { 89 Log.endSession(); 90 } 91 } 92 93 @Override 94 public void playDtmfTone(String callId, char digit) { 95 try { 96 Log.startSession("ICA.pDT", mOwnerComponentName); 97 long token = Binder.clearCallingIdentity(); 98 try { 99 synchronized (mLock) { 100 Log.d(this, "playDtmfTone(%s,%c)", callId, digit); 101 Call call = mCallIdMapper.getCall(callId); 102 if (call != null) { 103 mCallsManager.playDtmfTone(call, digit); 104 } else { 105 Log.w(this, "playDtmfTone, unknown call id: %s", callId); 106 } 107 } 108 } finally { 109 Binder.restoreCallingIdentity(token); 110 } 111 } finally { 112 Log.endSession(); 113 } 114 } 115 116 @Override 117 public void stopDtmfTone(String callId) { 118 try { 119 Log.startSession("ICA.sDT", mOwnerComponentName); 120 long token = Binder.clearCallingIdentity(); 121 try { 122 synchronized (mLock) { 123 Log.d(this, "stopDtmfTone(%s)", callId); 124 Call call = mCallIdMapper.getCall(callId); 125 if (call != null) { 126 mCallsManager.stopDtmfTone(call); 127 } else { 128 Log.w(this, "stopDtmfTone, unknown call id: %s", callId); 129 } 130 } 131 } finally { 132 Binder.restoreCallingIdentity(token); 133 } 134 } finally { 135 Log.endSession(); 136 } 137 } 138 139 @Override 140 public void postDialContinue(String callId, boolean proceed) { 141 try { 142 Log.startSession("ICA.pDC", mOwnerComponentName); 143 long token = Binder.clearCallingIdentity(); 144 try { 145 synchronized (mLock) { 146 Log.d(this, "postDialContinue(%s)", callId); 147 Call call = mCallIdMapper.getCall(callId); 148 if (call != null) { 149 mCallsManager.postDialContinue(call, proceed); 150 } else { 151 Log.w(this, "postDialContinue, unknown call id: %s", callId); 152 } 153 } 154 } finally { 155 Binder.restoreCallingIdentity(token); 156 } 157 } finally { 158 Log.endSession(); 159 } 160 } 161 162 @Override 163 public void disconnectCall(String callId) { 164 try { 165 Log.startSession(Log.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName); 166 long token = Binder.clearCallingIdentity(); 167 try { 168 synchronized (mLock) { 169 Log.v(this, "disconnectCall: %s", callId); 170 Call call = mCallIdMapper.getCall(callId); 171 if (call != null) { 172 mCallsManager.disconnectCall(call); 173 } else { 174 Log.w(this, "disconnectCall, unknown call id: %s", callId); 175 } 176 } 177 } finally { 178 Binder.restoreCallingIdentity(token); 179 } 180 } finally { 181 Log.endSession(); 182 } 183 } 184 185 @Override 186 public void holdCall(String callId) { 187 try { 188 Log.startSession(Log.Sessions.ICA_HOLD_CALL, mOwnerComponentName); 189 long token = Binder.clearCallingIdentity(); 190 try { 191 synchronized (mLock) { 192 Call call = mCallIdMapper.getCall(callId); 193 if (call != null) { 194 mCallsManager.holdCall(call); 195 } else { 196 Log.w(this, "holdCall, unknown call id: %s", callId); 197 } 198 } 199 } finally { 200 Binder.restoreCallingIdentity(token); 201 } 202 } finally { 203 Log.endSession(); 204 } 205 } 206 207 @Override 208 public void unholdCall(String callId) { 209 try { 210 Log.startSession(Log.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName); 211 long token = Binder.clearCallingIdentity(); 212 try { 213 synchronized (mLock) { 214 Call call = mCallIdMapper.getCall(callId); 215 if (call != null) { 216 mCallsManager.unholdCall(call); 217 } else { 218 Log.w(this, "unholdCall, unknown call id: %s", callId); 219 } 220 } 221 } finally { 222 Binder.restoreCallingIdentity(token); 223 } 224 } finally { 225 Log.endSession(); 226 } 227 } 228 229 @Override 230 public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle, 231 boolean setDefault) { 232 try { 233 Log.startSession("ICA.pAS", mOwnerComponentName); 234 long token = Binder.clearCallingIdentity(); 235 try { 236 synchronized (mLock) { 237 Call call = mCallIdMapper.getCall(callId); 238 if (call != null) { 239 mCallsManager.phoneAccountSelected(call, accountHandle, setDefault); 240 } else { 241 Log.w(this, "phoneAccountSelected, unknown call id: %s", callId); 242 } 243 } 244 } finally { 245 Binder.restoreCallingIdentity(token); 246 } 247 } finally { 248 Log.endSession(); 249 } 250 } 251 252 @Override 253 public void mute(boolean shouldMute) { 254 try { 255 Log.startSession(Log.Sessions.ICA_MUTE, mOwnerComponentName); 256 long token = Binder.clearCallingIdentity(); 257 try { 258 synchronized (mLock) { 259 mCallsManager.mute(shouldMute); 260 } 261 } finally { 262 Binder.restoreCallingIdentity(token); 263 } 264 } finally { 265 Log.endSession(); 266 } 267 } 268 269 @Override 270 public void setAudioRoute(int route) { 271 try { 272 Log.startSession(Log.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName); 273 long token = Binder.clearCallingIdentity(); 274 try { 275 synchronized (mLock) { 276 mCallsManager.setAudioRoute(route); 277 } 278 } finally { 279 Binder.restoreCallingIdentity(token); 280 } 281 } finally { 282 Log.endSession(); 283 } 284 } 285 286 @Override 287 public void conference(String callId, String otherCallId) { 288 try { 289 Log.startSession(Log.Sessions.ICA_CONFERENCE, mOwnerComponentName); 290 long token = Binder.clearCallingIdentity(); 291 try { 292 synchronized (mLock) { 293 Call call = mCallIdMapper.getCall(callId); 294 Call otherCall = mCallIdMapper.getCall(otherCallId); 295 if (call != null && otherCall != null) { 296 mCallsManager.conference(call, otherCall); 297 } else { 298 Log.w(this, "conference, unknown call id: %s or %s", callId, otherCallId); 299 } 300 } 301 } finally { 302 Binder.restoreCallingIdentity(token); 303 } 304 } finally { 305 Log.endSession(); 306 } 307 } 308 309 @Override 310 public void splitFromConference(String callId) { 311 try { 312 Log.startSession("ICA.sFC", mOwnerComponentName); 313 long token = Binder.clearCallingIdentity(); 314 try { 315 synchronized (mLock) { 316 Call call = mCallIdMapper.getCall(callId); 317 if (call != null) { 318 call.splitFromConference(); 319 } else { 320 Log.w(this, "splitFromConference, unknown call id: %s", callId); 321 } 322 } 323 } finally { 324 Binder.restoreCallingIdentity(token); 325 } 326 } finally { 327 Log.endSession(); 328 } 329 } 330 331 @Override 332 public void mergeConference(String callId) { 333 try { 334 Log.startSession("ICA.mC", mOwnerComponentName); 335 long token = Binder.clearCallingIdentity(); 336 try { 337 synchronized (mLock) { 338 Call call = mCallIdMapper.getCall(callId); 339 if (call != null) { 340 call.mergeConference(); 341 } else { 342 Log.w(this, "mergeConference, unknown call id: %s", callId); 343 } 344 } 345 } finally { 346 Binder.restoreCallingIdentity(token); 347 } 348 } finally { 349 Log.endSession(); 350 } 351 } 352 353 @Override 354 public void swapConference(String callId) { 355 try { 356 Log.startSession("ICA.sC", mOwnerComponentName); 357 long token = Binder.clearCallingIdentity(); 358 try { 359 synchronized (mLock) { 360 Call call = mCallIdMapper.getCall(callId); 361 if (call != null) { 362 call.swapConference(); 363 } else { 364 Log.w(this, "swapConference, unknown call id: %s", callId); 365 } 366 } 367 } finally { 368 Binder.restoreCallingIdentity(token); 369 } 370 } finally { 371 Log.endSession(); 372 } 373 } 374 375 @Override 376 public void pullExternalCall(String callId) { 377 try { 378 Log.startSession("ICA.pEC", mOwnerComponentName); 379 long token = Binder.clearCallingIdentity(); 380 try { 381 synchronized (mLock) { 382 Call call = mCallIdMapper.getCall(callId); 383 if (call != null) { 384 call.pullExternalCall(); 385 } else { 386 Log.w(this, "pullExternalCall, unknown call id: %s", callId); 387 } 388 } 389 } finally { 390 Binder.restoreCallingIdentity(token); 391 } 392 } finally { 393 Log.endSession(); 394 } 395 } 396 397 @Override 398 public void sendCallEvent(String callId, String event, Bundle extras) { 399 try { 400 Log.startSession("ICA.sCE", mOwnerComponentName); 401 long token = Binder.clearCallingIdentity(); 402 try { 403 synchronized (mLock) { 404 Call call = mCallIdMapper.getCall(callId); 405 if (call != null) { 406 call.sendCallEvent(event, extras); 407 } else { 408 Log.w(this, "sendCallEvent, unknown call id: %s", callId); 409 } 410 } 411 } finally { 412 Binder.restoreCallingIdentity(token); 413 } 414 } finally { 415 Log.endSession(); 416 } 417 } 418 419 @Override 420 public void putExtras(String callId, Bundle extras) { 421 try { 422 Log.startSession("ICA.pE", mOwnerComponentName); 423 long token = Binder.clearCallingIdentity(); 424 try { 425 synchronized (mLock) { 426 Call call = mCallIdMapper.getCall(callId); 427 if (call != null) { 428 call.putExtras(Call.SOURCE_INCALL_SERVICE, extras); 429 } else { 430 Log.w(this, "putExtras, unknown call id: %s", callId); 431 } 432 } 433 } finally { 434 Binder.restoreCallingIdentity(token); 435 } 436 } finally { 437 Log.endSession(); 438 } 439 } 440 441 @Override 442 public void removeExtras(String callId, List<String> keys) { 443 try { 444 Log.startSession("ICA.rE", mOwnerComponentName); 445 long token = Binder.clearCallingIdentity(); 446 try { 447 synchronized (mLock) { 448 Call call = mCallIdMapper.getCall(callId); 449 if (call != null) { 450 call.removeExtras(Call.SOURCE_INCALL_SERVICE, keys); 451 } else { 452 Log.w(this, "removeExtra, unknown call id: %s", callId); 453 } 454 } 455 } finally { 456 Binder.restoreCallingIdentity(token); 457 } 458 } finally { 459 Log.endSession(); 460 } 461 } 462 463 @Override 464 public void turnOnProximitySensor() { 465 try { 466 Log.startSession("ICA.tOnPS", mOwnerComponentName); 467 long token = Binder.clearCallingIdentity(); 468 try { 469 synchronized (mLock) { 470 mCallsManager.turnOnProximitySensor(); 471 } 472 } finally { 473 Binder.restoreCallingIdentity(token); 474 } 475 } finally { 476 Log.endSession(); 477 } 478 } 479 480 @Override 481 public void turnOffProximitySensor(boolean screenOnImmediately) { 482 try { 483 Log.startSession("ICA.tOffPS", mOwnerComponentName); 484 long token = Binder.clearCallingIdentity(); 485 try { 486 synchronized (mLock) { 487 mCallsManager.turnOffProximitySensor(screenOnImmediately); 488 } 489 } finally { 490 Binder.restoreCallingIdentity(token); 491 } 492 } finally { 493 Log.endSession(); 494 } 495 } 496 } 497