1 /* 2 * Copyright (C) 2016 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 static android.telecom.Call.Details.DIRECTION_INCOMING; 20 import static android.telecom.Call.Details.DIRECTION_OUTGOING; 21 import static android.telecom.Call.Details.DIRECTION_UNKNOWN; 22 23 import android.net.Uri; 24 import android.os.Bundle; 25 import android.telecom.Connection; 26 import android.telecom.DisconnectCause; 27 import android.telecom.ParcelableCall; 28 import android.telecom.ParcelableRttCall; 29 import android.telecom.TelecomManager; 30 import android.telephony.ims.ImsCallProfile; 31 import android.text.TextUtils; 32 33 import java.util.ArrayList; 34 import java.util.Collections; 35 import java.util.Iterator; 36 import java.util.List; 37 38 /** 39 * Utilities dealing with {@link ParcelableCall}. 40 */ 41 public class ParcelableCallUtils { 42 private static final int CALL_STATE_OVERRIDE_NONE = -1; 43 44 /** 45 * A list of extra keys which should be removed from a {@link ParcelableCall} when it is being 46 * generated for the purpose of sending to a incallservice other than the system incallservice. 47 * By convention we only pass keys namespaced with android.*, however there are some keys which 48 * should not be passed to non-system incallservice apps either. 49 */ 50 private static List<String> EXTRA_KEYS_TO_SANITIZE; 51 static { 52 EXTRA_KEYS_TO_SANITIZE = new ArrayList<>(); 53 EXTRA_KEYS_TO_SANITIZE.add(android.telecom.Connection.EXTRA_SIP_INVITE); 54 } 55 56 /** 57 * A list of extra keys which should be added to {@link ParcelableCall} when it is being 58 * generated for the purpose of sending to a CallScreeningService which has access to these 59 * restricted keys. 60 */ 61 private static List<String> RESTRICTED_CALL_SCREENING_EXTRA_KEYS; 62 static { 63 RESTRICTED_CALL_SCREENING_EXTRA_KEYS = new ArrayList<>(); 64 RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(android.telecom.Connection.EXTRA_SIP_INVITE); 65 RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(ImsCallProfile.EXTRA_IS_BUSINESS_CALL); 66 RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(ImsCallProfile.EXTRA_ASSERTED_DISPLAY_NAME); 67 } 68 69 public static class Converter { toParcelableCall(Call call, boolean includeVideoProvider, PhoneAccountRegistrar phoneAccountRegistrar)70 public ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider, 71 PhoneAccountRegistrar phoneAccountRegistrar) { 72 return ParcelableCallUtils.toParcelableCall( 73 call, includeVideoProvider, phoneAccountRegistrar, false, false, false); 74 } 75 toParcelableCallForScreening(Call call, boolean areRestrictedExtrasIncluded)76 public ParcelableCall toParcelableCallForScreening(Call call, 77 boolean areRestrictedExtrasIncluded) { 78 return ParcelableCallUtils.toParcelableCallForScreening(call, 79 areRestrictedExtrasIncluded); 80 } 81 } 82 83 /** 84 * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance. 85 * 86 * @param call The {@link Call} to parcel. 87 * @param includeVideoProvider {@code true} if the video provider should be parcelled with the 88 * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()} 89 * method creates a {@link VideoCallImpl} instance on access it is important for the 90 * recipient of the {@link ParcelableCall} to know if the video provider changed. 91 * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}. 92 * @param supportsExternalCalls Indicates whether the call should be parcelled for an 93 * {@link InCallService} which supports external calls or not. 94 * @param includeRttCall {@code true} if the RTT call should be included, {@code false} 95 * otherwise. 96 * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice, 97 * {@code false} otherwise. When parceling for the system incallservice, the entire call extras 98 * is included. When parceling for anything other than the system incallservice, some extra key 99 * values will be stripped for privacy sake. 100 */ toParcelableCall( Call call, boolean includeVideoProvider, PhoneAccountRegistrar phoneAccountRegistrar, boolean supportsExternalCalls, boolean includeRttCall, boolean isForSystemInCallService)101 public static ParcelableCall toParcelableCall( 102 Call call, 103 boolean includeVideoProvider, 104 PhoneAccountRegistrar phoneAccountRegistrar, 105 boolean supportsExternalCalls, 106 boolean includeRttCall, 107 boolean isForSystemInCallService) { 108 return toParcelableCall(call, includeVideoProvider, phoneAccountRegistrar, 109 supportsExternalCalls, CALL_STATE_OVERRIDE_NONE /* overrideState */, 110 includeRttCall, isForSystemInCallService); 111 } 112 113 /** 114 * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance. 115 * 116 * @param call The {@link Call} to parcel. 117 * @param includeVideoProvider {@code true} if the video provider should be parcelled with the 118 * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()} 119 * method creates a {@link VideoCallImpl} instance on access it is important for the 120 * recipient of the {@link ParcelableCall} to know if the video provider changed. 121 * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}. 122 * @param supportsExternalCalls Indicates whether the call should be parcelled for an 123 * {@link InCallService} which supports external calls or not. 124 * @param overrideState When not {@link #CALL_STATE_OVERRIDE_NONE}, use the provided state as an 125 * override to whatever is defined in the call. 126 * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice, 127 * {@code false} otherwise. When parceling for the system incallservice, the entire call extras 128 * is included. When parceling for anything other than the system incallservice, some extra key 129 * values will be stripped for privacy sake. 130 * @return The {@link ParcelableCall} containing all call information from the {@link Call}. 131 */ toParcelableCall( Call call, boolean includeVideoProvider, PhoneAccountRegistrar phoneAccountRegistrar, boolean supportsExternalCalls, int overrideState, boolean includeRttCall, boolean isForSystemInCallService)132 public static ParcelableCall toParcelableCall( 133 Call call, 134 boolean includeVideoProvider, 135 PhoneAccountRegistrar phoneAccountRegistrar, 136 boolean supportsExternalCalls, 137 int overrideState, 138 boolean includeRttCall, 139 boolean isForSystemInCallService) { 140 int state; 141 if (overrideState == CALL_STATE_OVERRIDE_NONE) { 142 state = getParcelableState(call, supportsExternalCalls); 143 } else { 144 state = overrideState; 145 } 146 int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities()); 147 int properties = convertConnectionToCallProperties(call.getConnectionProperties()); 148 int supportedAudioRoutes = call.getSupportedAudioRoutes(); 149 150 if (call.isConference()) { 151 properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE; 152 } 153 154 if (call.isWorkCall()) { 155 properties |= android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL; 156 } 157 158 if (call.getIsVoipAudioMode()) { 159 properties |= android.telecom.Call.Details.PROPERTY_VOIP_AUDIO_MODE; 160 } 161 162 if (call.isTransactionalCall()) { 163 properties |= android.telecom.Call.Details.PROPERTY_IS_TRANSACTIONAL; 164 } 165 166 // If this is a single-SIM device, the "default SIM" will always be the only SIM. 167 boolean isDefaultSmsAccount = phoneAccountRegistrar != null && 168 phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount()); 169 if (call.isRespondViaSmsCapable() && isDefaultSmsAccount) { 170 capabilities |= android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT; 171 } 172 173 if (call.isEmergencyCall()) { 174 capabilities = removeCapability( 175 capabilities, android.telecom.Call.Details.CAPABILITY_MUTE); 176 } 177 178 if (state == android.telecom.Call.STATE_DIALING) { 179 capabilities = removeCapability(capabilities, 180 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); 181 capabilities = removeCapability(capabilities, 182 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); 183 } 184 185 String parentCallId = null; 186 Call parentCall = call.getParentCall(); 187 if (parentCall != null) { 188 parentCallId = parentCall.getId(); 189 } 190 191 List<Call> childCalls = call.getChildCalls(); 192 List<String> childCallIds = new ArrayList<>(); 193 if (!childCalls.isEmpty()) { 194 for (Call child : childCalls) { 195 childCallIds.add(child.getId()); 196 } 197 } 198 199 Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ? 200 call.getHandle() : null; 201 String callerDisplayName = call.getCallerDisplayNamePresentation() == 202 TelecomManager.PRESENTATION_ALLOWED ? call.getCallerDisplayName() : null; 203 204 Uri contactPhotoUri = call.getContactPhotoUri(); 205 206 List<Call> conferenceableCalls = call.getConferenceableCalls(); 207 List<String> conferenceableCallIds = new ArrayList<String>(conferenceableCalls.size()); 208 for (Call otherCall : conferenceableCalls) { 209 conferenceableCallIds.add(otherCall.getId()); 210 } 211 212 ParcelableRttCall rttCall = includeRttCall ? getParcelableRttCall(call) : null; 213 int callDirection; 214 if (call.isIncoming()) { 215 callDirection = DIRECTION_INCOMING; 216 } else if (call.isUnknown()) { 217 callDirection = DIRECTION_UNKNOWN; 218 } else { 219 callDirection = DIRECTION_OUTGOING; 220 } 221 222 String activeChildCallId = null; 223 if (call.getConferenceLevelActiveCall() != null) { 224 activeChildCallId = call.getConferenceLevelActiveCall().getId(); 225 } 226 227 Bundle extras; 228 if (isForSystemInCallService) { 229 extras = call.getExtras(); 230 } else { 231 extras = sanitizeExtras(call.getExtras()); 232 } 233 234 return new ParcelableCall.ParcelableCallBuilder() 235 .setId(call.getId()) 236 .setState(state) 237 .setDisconnectCause(call.getDisconnectCause()) 238 .setCannedSmsResponses(call.getCannedSmsResponses()) 239 .setCapabilities(capabilities) 240 .setProperties(properties) 241 .setSupportedAudioRoutes(supportedAudioRoutes) 242 .setConnectTimeMillis(call.getConnectTimeMillis()) 243 .setHandle(handle) 244 .setHandlePresentation(call.getHandlePresentation()) 245 .setCallerDisplayName(callerDisplayName) 246 .setCallerDisplayNamePresentation(call.getCallerDisplayNamePresentation()) 247 .setGatewayInfo(call.getGatewayInfo()) 248 .setAccountHandle(call.getTargetPhoneAccount()) 249 .setIsVideoCallProviderChanged(includeVideoProvider) 250 .setVideoCallProvider(includeVideoProvider ? call.getVideoProvider() : null) 251 .setIsRttCallChanged(includeRttCall) 252 .setRttCall(rttCall) 253 .setParentCallId(parentCallId) 254 .setChildCallIds(childCallIds) 255 .setStatusHints(call.getStatusHints()) 256 .setVideoState(call.getVideoState()) 257 .setConferenceableCallIds(conferenceableCallIds) 258 .setIntentExtras(call.getIntentExtras()) 259 .setExtras(extras) 260 .setCreationTimeMillis(call.getCreationTimeMillis()) 261 .setCallDirection(callDirection) 262 .setCallerNumberVerificationStatus(call.getCallerNumberVerificationStatus()) 263 .setContactDisplayName(call.getName()) 264 .setActiveChildCallId(activeChildCallId) 265 .setContactPhotoUri(contactPhotoUri) 266 .createParcelableCall(); 267 } 268 269 /** 270 * Creates a ParcelableCall with the bare minimum properties required for a 271 * {@link android.telecom.CallScreeningService}. We ONLY expose the following: 272 * <ul> 273 * <li>Call Id (not exposed to public, but needed to associated calls)</li> 274 * <li>Call directoin</li> 275 * <li>Creation time</li> 276 * <li>Connection time</li> 277 * <li>Handle (phone number)</li> 278 * <li>Handle (phone number) presentation</li> 279 * <li>Caller number verification status (verstat)</li> 280 * </ul> 281 * All other fields are nulled or set to 0 values. 282 * Where the call screening service is part of the system incallservice, the 283 * {@link Connection#EXTRA_SIP_INVITE} header information is also sent to the call screening 284 * service (since the system incallservice has access to this anyways). 285 * @param call The telecom call to send to a call screening service. 286 * @param areRestrictedExtrasIncluded {@code true} if the set of restricted extras defined in 287 * {@link #RESTRICTED_CALL_SCREENING_EXTRA_KEYS} are to 288 * be included in the parceled call, {@code false} otherwise. 289 * @return Minimal {@link ParcelableCall} to send to the call screening service. 290 */ toParcelableCallForScreening(Call call, boolean areRestrictedExtrasIncluded)291 public static ParcelableCall toParcelableCallForScreening(Call call, 292 boolean areRestrictedExtrasIncluded) { 293 Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ? 294 call.getHandle() : null; 295 int callDirection; 296 if (call.isIncoming()) { 297 callDirection = DIRECTION_INCOMING; 298 } else if (call.isUnknown()) { 299 callDirection = DIRECTION_UNKNOWN; 300 } else { 301 callDirection = DIRECTION_OUTGOING; 302 } 303 Bundle callExtras; 304 if (areRestrictedExtrasIncluded) { 305 callExtras = sanitizeRestrictedCallExtras(call.getExtras()); 306 } else { 307 callExtras = new Bundle(); 308 } 309 310 return new ParcelableCall.ParcelableCallBuilder() 311 .setId(call.getId()) 312 .setState(getParcelableState(call, false /* supportsExternalCalls */)) 313 .setDisconnectCause(new DisconnectCause(DisconnectCause.UNKNOWN)) 314 .setCannedSmsResponses(null) 315 .setCapabilities(0) 316 .setProperties(0) 317 .setSupportedAudioRoutes(0) 318 .setConnectTimeMillis(call.getConnectTimeMillis()) 319 .setHandle(handle) 320 .setHandlePresentation(call.getHandlePresentation()) 321 .setCallerDisplayName(null) 322 .setCallerDisplayNamePresentation(0) 323 .setGatewayInfo(null) 324 .setAccountHandle(null) 325 .setIsVideoCallProviderChanged(false) 326 .setVideoCallProvider(null) 327 .setIsRttCallChanged(false) 328 .setRttCall(null) 329 .setParentCallId(null) 330 .setChildCallIds(null) 331 .setStatusHints(null) 332 .setVideoState(0) 333 .setConferenceableCallIds(Collections.emptyList()) 334 .setIntentExtras(null) 335 .setExtras(callExtras) 336 .setCreationTimeMillis(call.getCreationTimeMillis()) 337 .setCallDirection(callDirection) 338 .setCallerNumberVerificationStatus(call.getCallerNumberVerificationStatus()) 339 .setContactDisplayName(null) 340 .setActiveChildCallId(null) 341 .createParcelableCall(); 342 } 343 344 /** 345 * Sanitize the extras bundle passed in, removing keys which should not be sent to non-system 346 * incallservice apps. 347 * @param oldExtras Extras bundle to sanitize. 348 * @return The sanitized extras bundle. 349 */ sanitizeExtras(Bundle oldExtras)350 private static Bundle sanitizeExtras(Bundle oldExtras) { 351 if (oldExtras == null) { 352 return new Bundle(); 353 } 354 Bundle extras = new Bundle(oldExtras); 355 for (String key : EXTRA_KEYS_TO_SANITIZE) { 356 extras.remove(key); 357 } 358 359 // As a catch-all remove any that don't start with android namespace. 360 Iterator<String> toCheck = extras.keySet().iterator(); 361 while (toCheck.hasNext()) { 362 String extraKey = toCheck.next(); 363 if (TextUtils.isEmpty(extraKey) || !extraKey.startsWith("android.")) { 364 toCheck.remove(); 365 } 366 } 367 return extras; 368 } 369 370 /** 371 * Sanitize the extras bundle passed in, removing keys which should not be sent to call 372 * screening services which have access to the restricted extras. 373 * @param oldExtras Extras bundle to sanitize. 374 * @return The sanitized extras bundle. 375 */ sanitizeRestrictedCallExtras(Bundle oldExtras)376 private static Bundle sanitizeRestrictedCallExtras(Bundle oldExtras) { 377 if (oldExtras == null) { 378 return new Bundle(); 379 } 380 Bundle extras = new Bundle(oldExtras); 381 Iterator<String> toCheck = extras.keySet().iterator(); 382 while (toCheck.hasNext()) { 383 String extraKey = toCheck.next(); 384 if (TextUtils.isEmpty(extraKey) 385 || !RESTRICTED_CALL_SCREENING_EXTRA_KEYS.contains(extraKey)) { 386 toCheck.remove(); 387 } 388 } 389 return extras; 390 } 391 getParcelableState(Call call, boolean supportsExternalCalls)392 private static int getParcelableState(Call call, boolean supportsExternalCalls) { 393 int state = CallState.NEW; 394 switch (call.getParcelableCallState()) { 395 case CallState.ABORTED: 396 case CallState.DISCONNECTED: 397 state = android.telecom.Call.STATE_DISCONNECTED; 398 break; 399 case CallState.ACTIVE: 400 state = android.telecom.Call.STATE_ACTIVE; 401 break; 402 case CallState.CONNECTING: 403 state = android.telecom.Call.STATE_CONNECTING; 404 break; 405 case CallState.DIALING: 406 state = android.telecom.Call.STATE_DIALING; 407 break; 408 case CallState.PULLING: 409 if (supportsExternalCalls) { 410 // The InCallService supports external calls, so it must handle 411 // STATE_PULLING_CALL. 412 state = android.telecom.Call.STATE_PULLING_CALL; 413 } else { 414 // The InCallService does NOT support external calls, so remap 415 // STATE_PULLING_CALL to STATE_DIALING. In essence, pulling a call can be seen 416 // as a form of dialing, so it is appropriate for InCallServices which do not 417 // handle external calls. 418 state = android.telecom.Call.STATE_DIALING; 419 } 420 break; 421 case CallState.DISCONNECTING: 422 state = android.telecom.Call.STATE_DISCONNECTING; 423 break; 424 case CallState.NEW: 425 state = android.telecom.Call.STATE_NEW; 426 break; 427 case CallState.ON_HOLD: 428 state = android.telecom.Call.STATE_HOLDING; 429 break; 430 case CallState.RINGING: 431 case CallState.ANSWERED: 432 // TODO: does in-call UI need to see ANSWERED? 433 state = android.telecom.Call.STATE_RINGING; 434 break; 435 case CallState.SELECT_PHONE_ACCOUNT: 436 state = android.telecom.Call.STATE_SELECT_PHONE_ACCOUNT; 437 break; 438 case CallState.AUDIO_PROCESSING: 439 state = android.telecom.Call.STATE_AUDIO_PROCESSING; 440 break; 441 case CallState.SIMULATED_RINGING: 442 state = android.telecom.Call.STATE_SIMULATED_RINGING; 443 break; 444 } 445 446 return state; 447 } 448 449 private static final int[] CONNECTION_TO_CALL_CAPABILITY = new int[] { 450 Connection.CAPABILITY_HOLD, 451 android.telecom.Call.Details.CAPABILITY_HOLD, 452 453 Connection.CAPABILITY_SUPPORT_HOLD, 454 android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD, 455 456 Connection.CAPABILITY_MERGE_CONFERENCE, 457 android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE, 458 459 Connection.CAPABILITY_SWAP_CONFERENCE, 460 android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE, 461 462 Connection.CAPABILITY_RESPOND_VIA_TEXT, 463 android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT, 464 465 Connection.CAPABILITY_MUTE, 466 android.telecom.Call.Details.CAPABILITY_MUTE, 467 468 Connection.CAPABILITY_MANAGE_CONFERENCE, 469 android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE, 470 471 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX, 472 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX, 473 474 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX, 475 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX, 476 477 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, 478 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, 479 480 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX, 481 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX, 482 483 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX, 484 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX, 485 486 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, 487 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, 488 489 Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE, 490 android.telecom.Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE, 491 492 Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE, 493 android.telecom.Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE, 494 495 Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO, 496 android.telecom.Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO, 497 498 Connection.CAPABILITY_CAN_PAUSE_VIDEO, 499 android.telecom.Call.Details.CAPABILITY_CAN_PAUSE_VIDEO, 500 501 Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, 502 android.telecom.Call.Details.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, 503 504 Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, 505 android.telecom.Call.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, 506 507 Connection.CAPABILITY_CAN_PULL_CALL, 508 android.telecom.Call.Details.CAPABILITY_CAN_PULL_CALL, 509 510 Connection.CAPABILITY_SUPPORT_DEFLECT, 511 android.telecom.Call.Details.CAPABILITY_SUPPORT_DEFLECT, 512 513 Connection.CAPABILITY_ADD_PARTICIPANT, 514 android.telecom.Call.Details.CAPABILITY_ADD_PARTICIPANT, 515 516 Connection.CAPABILITY_TRANSFER, 517 android.telecom.Call.Details.CAPABILITY_TRANSFER, 518 519 Connection.CAPABILITY_TRANSFER_CONSULTATIVE, 520 android.telecom.Call.Details.CAPABILITY_TRANSFER_CONSULTATIVE, 521 522 Connection.CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT, 523 android.telecom.Call.Details.CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT 524 525 }; 526 convertConnectionToCallCapabilities(int connectionCapabilities)527 private static int convertConnectionToCallCapabilities(int connectionCapabilities) { 528 int callCapabilities = 0; 529 for (int i = 0; i < CONNECTION_TO_CALL_CAPABILITY.length; i += 2) { 530 if ((CONNECTION_TO_CALL_CAPABILITY[i] & connectionCapabilities) == 531 CONNECTION_TO_CALL_CAPABILITY[i]) { 532 533 callCapabilities |= CONNECTION_TO_CALL_CAPABILITY[i + 1]; 534 } 535 } 536 return callCapabilities; 537 } 538 539 private static final int[] CONNECTION_TO_CALL_PROPERTIES = new int[] { 540 Connection.PROPERTY_HIGH_DEF_AUDIO, 541 android.telecom.Call.Details.PROPERTY_HIGH_DEF_AUDIO, 542 543 Connection.PROPERTY_WIFI, 544 android.telecom.Call.Details.PROPERTY_WIFI, 545 546 Connection.PROPERTY_GENERIC_CONFERENCE, 547 android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE, 548 549 Connection.PROPERTY_EMERGENCY_CALLBACK_MODE, 550 android.telecom.Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE, 551 552 Connection.PROPERTY_IS_EXTERNAL_CALL, 553 android.telecom.Call.Details.PROPERTY_IS_EXTERNAL_CALL, 554 555 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY, 556 android.telecom.Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY, 557 558 Connection.PROPERTY_SELF_MANAGED, 559 android.telecom.Call.Details.PROPERTY_SELF_MANAGED, 560 561 Connection.PROPERTY_ASSISTED_DIALING, 562 android.telecom.Call.Details.PROPERTY_ASSISTED_DIALING, 563 564 Connection.PROPERTY_IS_RTT, 565 android.telecom.Call.Details.PROPERTY_RTT, 566 567 Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL, 568 android.telecom.Call.Details.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL, 569 570 Connection.PROPERTY_IS_ADHOC_CONFERENCE, 571 android.telecom.Call.Details.PROPERTY_IS_ADHOC_CONFERENCE, 572 573 Connection.PROPERTY_CROSS_SIM, 574 android.telecom.Call.Details.PROPERTY_CROSS_SIM 575 }; 576 convertConnectionToCallProperties(int connectionProperties)577 private static int convertConnectionToCallProperties(int connectionProperties) { 578 int callProperties = 0; 579 for (int i = 0; i < CONNECTION_TO_CALL_PROPERTIES.length; i += 2) { 580 if ((CONNECTION_TO_CALL_PROPERTIES[i] & connectionProperties) == 581 CONNECTION_TO_CALL_PROPERTIES[i]) { 582 583 callProperties |= CONNECTION_TO_CALL_PROPERTIES[i + 1]; 584 } 585 } 586 return callProperties; 587 } 588 589 /** 590 * Removes the specified capability from the set of capabilities bits and returns the new set. 591 */ removeCapability(int capabilities, int capability)592 private static int removeCapability(int capabilities, int capability) { 593 return capabilities & ~capability; 594 } 595 getParcelableRttCall(Call call)596 private static ParcelableRttCall getParcelableRttCall(Call call) { 597 if (!call.isRttCall()) { 598 return null; 599 } 600 return new ParcelableRttCall(call.getRttMode(), call.getInCallToCsRttPipeForInCall(), 601 call.getCsToInCallRttPipeForInCall()); 602 } 603 ParcelableCallUtils()604 private ParcelableCallUtils() {} 605 } 606