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