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