| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.server.telecom; |
| |
| import static android.telecom.Call.Details.DIRECTION_INCOMING; |
| import static android.telecom.Call.Details.DIRECTION_OUTGOING; |
| import static android.telecom.Call.Details.DIRECTION_UNKNOWN; |
| |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.telecom.Connection; |
| import android.telecom.DisconnectCause; |
| import android.telecom.ParcelableCall; |
| import android.telecom.ParcelableRttCall; |
| import android.telecom.TelecomManager; |
| import android.telephony.ims.ImsCallProfile; |
| import android.text.TextUtils; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| /** |
| * Utilities dealing with {@link ParcelableCall}. |
| */ |
| public class ParcelableCallUtils { |
| private static final int CALL_STATE_OVERRIDE_NONE = -1; |
| |
| /** |
| * A list of extra keys which should be removed from a {@link ParcelableCall} when it is being |
| * generated for the purpose of sending to a incallservice other than the system incallservice. |
| * By convention we only pass keys namespaced with android.*, however there are some keys which |
| * should not be passed to non-system incallservice apps either. |
| */ |
| private static List<String> EXTRA_KEYS_TO_SANITIZE; |
| static { |
| EXTRA_KEYS_TO_SANITIZE = new ArrayList<>(); |
| EXTRA_KEYS_TO_SANITIZE.add(android.telecom.Connection.EXTRA_SIP_INVITE); |
| } |
| |
| /** |
| * A list of extra keys which should be added to {@link ParcelableCall} when it is being |
| * generated for the purpose of sending to a CallScreeningService which has access to these |
| * restricted keys. |
| */ |
| private static List<String> RESTRICTED_CALL_SCREENING_EXTRA_KEYS; |
| static { |
| RESTRICTED_CALL_SCREENING_EXTRA_KEYS = new ArrayList<>(); |
| RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(android.telecom.Connection.EXTRA_SIP_INVITE); |
| RESTRICTED_CALL_SCREENING_EXTRA_KEYS.add(ImsCallProfile.EXTRA_IS_BUSINESS_CALL); |
| } |
| |
| public static class Converter { |
| public ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider, |
| PhoneAccountRegistrar phoneAccountRegistrar) { |
| return ParcelableCallUtils.toParcelableCall( |
| call, includeVideoProvider, phoneAccountRegistrar, false, false, false); |
| } |
| |
| public ParcelableCall toParcelableCallForScreening(Call call, |
| boolean areRestrictedExtrasIncluded) { |
| return ParcelableCallUtils.toParcelableCallForScreening(call, |
| areRestrictedExtrasIncluded); |
| } |
| } |
| |
| /** |
| * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance. |
| * |
| * @param call The {@link Call} to parcel. |
| * @param includeVideoProvider {@code true} if the video provider should be parcelled with the |
| * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()} |
| * method creates a {@link VideoCallImpl} instance on access it is important for the |
| * recipient of the {@link ParcelableCall} to know if the video provider changed. |
| * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}. |
| * @param supportsExternalCalls Indicates whether the call should be parcelled for an |
| * {@link InCallService} which supports external calls or not. |
| * @param includeRttCall {@code true} if the RTT call should be included, {@code false} |
| * otherwise. |
| * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice, |
| * {@code false} otherwise. When parceling for the system incallservice, the entire call extras |
| * is included. When parceling for anything other than the system incallservice, some extra key |
| * values will be stripped for privacy sake. |
| */ |
| public static ParcelableCall toParcelableCall( |
| Call call, |
| boolean includeVideoProvider, |
| PhoneAccountRegistrar phoneAccountRegistrar, |
| boolean supportsExternalCalls, |
| boolean includeRttCall, |
| boolean isForSystemInCallService) { |
| return toParcelableCall(call, includeVideoProvider, phoneAccountRegistrar, |
| supportsExternalCalls, CALL_STATE_OVERRIDE_NONE /* overrideState */, |
| includeRttCall, isForSystemInCallService); |
| } |
| |
| /** |
| * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance. |
| * |
| * @param call The {@link Call} to parcel. |
| * @param includeVideoProvider {@code true} if the video provider should be parcelled with the |
| * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()} |
| * method creates a {@link VideoCallImpl} instance on access it is important for the |
| * recipient of the {@link ParcelableCall} to know if the video provider changed. |
| * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}. |
| * @param supportsExternalCalls Indicates whether the call should be parcelled for an |
| * {@link InCallService} which supports external calls or not. |
| * @param overrideState When not {@link #CALL_STATE_OVERRIDE_NONE}, use the provided state as an |
| * override to whatever is defined in the call. |
| * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice, |
| * {@code false} otherwise. When parceling for the system incallservice, the entire call extras |
| * is included. When parceling for anything other than the system incallservice, some extra key |
| * values will be stripped for privacy sake. |
| * @return The {@link ParcelableCall} containing all call information from the {@link Call}. |
| */ |
| public static ParcelableCall toParcelableCall( |
| Call call, |
| boolean includeVideoProvider, |
| PhoneAccountRegistrar phoneAccountRegistrar, |
| boolean supportsExternalCalls, |
| int overrideState, |
| boolean includeRttCall, |
| boolean isForSystemInCallService) { |
| int state; |
| if (overrideState == CALL_STATE_OVERRIDE_NONE) { |
| state = getParcelableState(call, supportsExternalCalls); |
| } else { |
| state = overrideState; |
| } |
| int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities()); |
| int properties = convertConnectionToCallProperties(call.getConnectionProperties()); |
| int supportedAudioRoutes = call.getSupportedAudioRoutes(); |
| |
| if (call.isConference()) { |
| properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE; |
| } |
| |
| if (call.isWorkCall()) { |
| properties |= android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL; |
| } |
| |
| if (call.getIsVoipAudioMode()) { |
| properties |= android.telecom.Call.Details.PROPERTY_VOIP_AUDIO_MODE; |
| } |
| |
| // If this is a single-SIM device, the "default SIM" will always be the only SIM. |
| boolean isDefaultSmsAccount = phoneAccountRegistrar != null && |
| phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount()); |
| if (call.isRespondViaSmsCapable() && isDefaultSmsAccount) { |
| capabilities |= android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT; |
| } |
| |
| if (call.isEmergencyCall()) { |
| capabilities = removeCapability( |
| capabilities, android.telecom.Call.Details.CAPABILITY_MUTE); |
| } |
| |
| if (state == android.telecom.Call.STATE_DIALING) { |
| capabilities = removeCapability(capabilities, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); |
| capabilities = removeCapability(capabilities, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); |
| } |
| |
| String parentCallId = null; |
| Call parentCall = call.getParentCall(); |
| if (parentCall != null) { |
| parentCallId = parentCall.getId(); |
| } |
| |
| List<Call> childCalls = call.getChildCalls(); |
| List<String> childCallIds = new ArrayList<>(); |
| if (!childCalls.isEmpty()) { |
| for (Call child : childCalls) { |
| childCallIds.add(child.getId()); |
| } |
| } |
| |
| Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ? |
| call.getHandle() : null; |
| String callerDisplayName = call.getCallerDisplayNamePresentation() == |
| TelecomManager.PRESENTATION_ALLOWED ? call.getCallerDisplayName() : null; |
| |
| List<Call> conferenceableCalls = call.getConferenceableCalls(); |
| List<String> conferenceableCallIds = new ArrayList<String>(conferenceableCalls.size()); |
| for (Call otherCall : conferenceableCalls) { |
| conferenceableCallIds.add(otherCall.getId()); |
| } |
| |
| ParcelableRttCall rttCall = includeRttCall ? getParcelableRttCall(call) : null; |
| int callDirection; |
| if (call.isIncoming()) { |
| callDirection = DIRECTION_INCOMING; |
| } else if (call.isUnknown()) { |
| callDirection = DIRECTION_UNKNOWN; |
| } else { |
| callDirection = DIRECTION_OUTGOING; |
| } |
| |
| String activeChildCallId = null; |
| if (call.getConferenceLevelActiveCall() != null) { |
| activeChildCallId = call.getConferenceLevelActiveCall().getId(); |
| } |
| |
| Bundle extras; |
| if (isForSystemInCallService) { |
| extras = call.getExtras(); |
| } else { |
| extras = sanitizeExtras(call.getExtras()); |
| } |
| |
| return new ParcelableCall.ParcelableCallBuilder() |
| .setId(call.getId()) |
| .setState(state) |
| .setDisconnectCause(call.getDisconnectCause()) |
| .setCannedSmsResponses(call.getCannedSmsResponses()) |
| .setCapabilities(capabilities) |
| .setProperties(properties) |
| .setSupportedAudioRoutes(supportedAudioRoutes) |
| .setConnectTimeMillis(call.getConnectTimeMillis()) |
| .setHandle(handle) |
| .setHandlePresentation(call.getHandlePresentation()) |
| .setCallerDisplayName(callerDisplayName) |
| .setCallerDisplayNamePresentation(call.getCallerDisplayNamePresentation()) |
| .setGatewayInfo(call.getGatewayInfo()) |
| .setAccountHandle(call.getTargetPhoneAccount()) |
| .setIsVideoCallProviderChanged(includeVideoProvider) |
| .setVideoCallProvider(includeVideoProvider ? call.getVideoProvider() : null) |
| .setIsRttCallChanged(includeRttCall) |
| .setRttCall(rttCall) |
| .setParentCallId(parentCallId) |
| .setChildCallIds(childCallIds) |
| .setStatusHints(call.getStatusHints()) |
| .setVideoState(call.getVideoState()) |
| .setConferenceableCallIds(conferenceableCallIds) |
| .setIntentExtras(call.getIntentExtras()) |
| .setExtras(extras) |
| .setCreationTimeMillis(call.getCreationTimeMillis()) |
| .setCallDirection(callDirection) |
| .setCallerNumberVerificationStatus(call.getCallerNumberVerificationStatus()) |
| .setContactDisplayName(call.getName()) |
| .setActiveChildCallId(activeChildCallId) |
| .createParcelableCall(); |
| } |
| |
| /** |
| * Creates a ParcelableCall with the bare minimum properties required for a |
| * {@link android.telecom.CallScreeningService}. We ONLY expose the following: |
| * <ul> |
| * <li>Call Id (not exposed to public, but needed to associated calls)</li> |
| * <li>Call directoin</li> |
| * <li>Creation time</li> |
| * <li>Connection time</li> |
| * <li>Handle (phone number)</li> |
| * <li>Handle (phone number) presentation</li> |
| * <li>Caller number verification status (verstat)</li> |
| * </ul> |
| * All other fields are nulled or set to 0 values. |
| * Where the call screening service is part of the system incallservice, the |
| * {@link Connection#EXTRA_SIP_INVITE} header information is also sent to the call screening |
| * service (since the system incallservice has access to this anyways). |
| * @param call The telecom call to send to a call screening service. |
| * @param areRestrictedExtrasIncluded {@code true} if the set of restricted extras defined in |
| * {@link #RESTRICTED_CALL_SCREENING_EXTRA_KEYS} are to |
| * be included in the parceled call, {@code false} otherwise. |
| * @return Minimal {@link ParcelableCall} to send to the call screening service. |
| */ |
| public static ParcelableCall toParcelableCallForScreening(Call call, |
| boolean areRestrictedExtrasIncluded) { |
| Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ? |
| call.getHandle() : null; |
| int callDirection; |
| if (call.isIncoming()) { |
| callDirection = DIRECTION_INCOMING; |
| } else if (call.isUnknown()) { |
| callDirection = DIRECTION_UNKNOWN; |
| } else { |
| callDirection = DIRECTION_OUTGOING; |
| } |
| Bundle callExtras; |
| if (areRestrictedExtrasIncluded) { |
| callExtras = sanitizeRestrictedCallExtras(call.getExtras()); |
| } else { |
| callExtras = new Bundle(); |
| } |
| |
| return new ParcelableCall.ParcelableCallBuilder() |
| .setId(call.getId()) |
| .setState(getParcelableState(call, false /* supportsExternalCalls */)) |
| .setDisconnectCause(new DisconnectCause(DisconnectCause.UNKNOWN)) |
| .setCannedSmsResponses(null) |
| .setCapabilities(0) |
| .setProperties(0) |
| .setSupportedAudioRoutes(0) |
| .setConnectTimeMillis(call.getConnectTimeMillis()) |
| .setHandle(handle) |
| .setHandlePresentation(call.getHandlePresentation()) |
| .setCallerDisplayName(null) |
| .setCallerDisplayNamePresentation(0) |
| .setGatewayInfo(null) |
| .setAccountHandle(null) |
| .setIsVideoCallProviderChanged(false) |
| .setVideoCallProvider(null) |
| .setIsRttCallChanged(false) |
| .setRttCall(null) |
| .setParentCallId(null) |
| .setChildCallIds(null) |
| .setStatusHints(null) |
| .setVideoState(0) |
| .setConferenceableCallIds(Collections.emptyList()) |
| .setIntentExtras(null) |
| .setExtras(callExtras) |
| .setCreationTimeMillis(call.getCreationTimeMillis()) |
| .setCallDirection(callDirection) |
| .setCallerNumberVerificationStatus(call.getCallerNumberVerificationStatus()) |
| .setContactDisplayName(null) |
| .setActiveChildCallId(null) |
| .createParcelableCall(); |
| } |
| |
| /** |
| * Sanitize the extras bundle passed in, removing keys which should not be sent to non-system |
| * incallservice apps. |
| * @param oldExtras Extras bundle to sanitize. |
| * @return The sanitized extras bundle. |
| */ |
| private static Bundle sanitizeExtras(Bundle oldExtras) { |
| if (oldExtras == null) { |
| return new Bundle(); |
| } |
| Bundle extras = new Bundle(oldExtras); |
| for (String key : EXTRA_KEYS_TO_SANITIZE) { |
| extras.remove(key); |
| } |
| |
| // As a catch-all remove any that don't start with android namespace. |
| Iterator<String> toCheck = extras.keySet().iterator(); |
| while (toCheck.hasNext()) { |
| String extraKey = toCheck.next(); |
| if (TextUtils.isEmpty(extraKey) || !extraKey.startsWith("android.")) { |
| toCheck.remove(); |
| } |
| } |
| return extras; |
| } |
| |
| /** |
| * Sanitize the extras bundle passed in, removing keys which should not be sent to call |
| * screening services which have access to the restricted extras. |
| * @param oldExtras Extras bundle to sanitize. |
| * @return The sanitized extras bundle. |
| */ |
| private static Bundle sanitizeRestrictedCallExtras(Bundle oldExtras) { |
| if (oldExtras == null) { |
| return new Bundle(); |
| } |
| Bundle extras = new Bundle(oldExtras); |
| Iterator<String> toCheck = extras.keySet().iterator(); |
| while (toCheck.hasNext()) { |
| String extraKey = toCheck.next(); |
| if (TextUtils.isEmpty(extraKey) |
| || !RESTRICTED_CALL_SCREENING_EXTRA_KEYS.contains(extraKey)) { |
| toCheck.remove(); |
| } |
| } |
| return extras; |
| } |
| |
| private static int getParcelableState(Call call, boolean supportsExternalCalls) { |
| int state = CallState.NEW; |
| switch (call.getParcelableCallState()) { |
| case CallState.ABORTED: |
| case CallState.DISCONNECTED: |
| state = android.telecom.Call.STATE_DISCONNECTED; |
| break; |
| case CallState.ACTIVE: |
| state = android.telecom.Call.STATE_ACTIVE; |
| break; |
| case CallState.CONNECTING: |
| state = android.telecom.Call.STATE_CONNECTING; |
| break; |
| case CallState.DIALING: |
| state = android.telecom.Call.STATE_DIALING; |
| break; |
| case CallState.PULLING: |
| if (supportsExternalCalls) { |
| // The InCallService supports external calls, so it must handle |
| // STATE_PULLING_CALL. |
| state = android.telecom.Call.STATE_PULLING_CALL; |
| } else { |
| // The InCallService does NOT support external calls, so remap |
| // STATE_PULLING_CALL to STATE_DIALING. In essence, pulling a call can be seen |
| // as a form of dialing, so it is appropriate for InCallServices which do not |
| // handle external calls. |
| state = android.telecom.Call.STATE_DIALING; |
| } |
| break; |
| case CallState.DISCONNECTING: |
| state = android.telecom.Call.STATE_DISCONNECTING; |
| break; |
| case CallState.NEW: |
| state = android.telecom.Call.STATE_NEW; |
| break; |
| case CallState.ON_HOLD: |
| state = android.telecom.Call.STATE_HOLDING; |
| break; |
| case CallState.RINGING: |
| case CallState.ANSWERED: |
| // TODO: does in-call UI need to see ANSWERED? |
| state = android.telecom.Call.STATE_RINGING; |
| break; |
| case CallState.SELECT_PHONE_ACCOUNT: |
| state = android.telecom.Call.STATE_SELECT_PHONE_ACCOUNT; |
| break; |
| case CallState.AUDIO_PROCESSING: |
| state = android.telecom.Call.STATE_AUDIO_PROCESSING; |
| break; |
| case CallState.SIMULATED_RINGING: |
| state = android.telecom.Call.STATE_SIMULATED_RINGING; |
| break; |
| } |
| |
| return state; |
| } |
| |
| private static final int[] CONNECTION_TO_CALL_CAPABILITY = new int[] { |
| Connection.CAPABILITY_HOLD, |
| android.telecom.Call.Details.CAPABILITY_HOLD, |
| |
| Connection.CAPABILITY_SUPPORT_HOLD, |
| android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD, |
| |
| Connection.CAPABILITY_MERGE_CONFERENCE, |
| android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE, |
| |
| Connection.CAPABILITY_SWAP_CONFERENCE, |
| android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE, |
| |
| Connection.CAPABILITY_RESPOND_VIA_TEXT, |
| android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT, |
| |
| Connection.CAPABILITY_MUTE, |
| android.telecom.Call.Details.CAPABILITY_MUTE, |
| |
| Connection.CAPABILITY_MANAGE_CONFERENCE, |
| android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX, |
| |
| Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, |
| android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, |
| |
| Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE, |
| android.telecom.Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE, |
| |
| Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE, |
| android.telecom.Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE, |
| |
| Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO, |
| android.telecom.Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO, |
| |
| Connection.CAPABILITY_CAN_PAUSE_VIDEO, |
| android.telecom.Call.Details.CAPABILITY_CAN_PAUSE_VIDEO, |
| |
| Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, |
| android.telecom.Call.Details.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, |
| |
| Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, |
| android.telecom.Call.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, |
| |
| Connection.CAPABILITY_CAN_PULL_CALL, |
| android.telecom.Call.Details.CAPABILITY_CAN_PULL_CALL, |
| |
| Connection.CAPABILITY_SUPPORT_DEFLECT, |
| android.telecom.Call.Details.CAPABILITY_SUPPORT_DEFLECT, |
| |
| Connection.CAPABILITY_ADD_PARTICIPANT, |
| android.telecom.Call.Details.CAPABILITY_ADD_PARTICIPANT, |
| |
| Connection.CAPABILITY_TRANSFER, |
| android.telecom.Call.Details.CAPABILITY_TRANSFER, |
| |
| Connection.CAPABILITY_TRANSFER_CONSULTATIVE, |
| android.telecom.Call.Details.CAPABILITY_TRANSFER_CONSULTATIVE, |
| |
| Connection.CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT, |
| android.telecom.Call.Details.CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT |
| |
| }; |
| |
| private static int convertConnectionToCallCapabilities(int connectionCapabilities) { |
| int callCapabilities = 0; |
| for (int i = 0; i < CONNECTION_TO_CALL_CAPABILITY.length; i += 2) { |
| if ((CONNECTION_TO_CALL_CAPABILITY[i] & connectionCapabilities) == |
| CONNECTION_TO_CALL_CAPABILITY[i]) { |
| |
| callCapabilities |= CONNECTION_TO_CALL_CAPABILITY[i + 1]; |
| } |
| } |
| return callCapabilities; |
| } |
| |
| private static final int[] CONNECTION_TO_CALL_PROPERTIES = new int[] { |
| Connection.PROPERTY_HIGH_DEF_AUDIO, |
| android.telecom.Call.Details.PROPERTY_HIGH_DEF_AUDIO, |
| |
| Connection.PROPERTY_WIFI, |
| android.telecom.Call.Details.PROPERTY_WIFI, |
| |
| Connection.PROPERTY_GENERIC_CONFERENCE, |
| android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE, |
| |
| Connection.PROPERTY_EMERGENCY_CALLBACK_MODE, |
| android.telecom.Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE, |
| |
| Connection.PROPERTY_IS_EXTERNAL_CALL, |
| android.telecom.Call.Details.PROPERTY_IS_EXTERNAL_CALL, |
| |
| Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY, |
| android.telecom.Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY, |
| |
| Connection.PROPERTY_SELF_MANAGED, |
| android.telecom.Call.Details.PROPERTY_SELF_MANAGED, |
| |
| Connection.PROPERTY_ASSISTED_DIALING, |
| android.telecom.Call.Details.PROPERTY_ASSISTED_DIALING, |
| |
| Connection.PROPERTY_IS_RTT, |
| android.telecom.Call.Details.PROPERTY_RTT, |
| |
| Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL, |
| android.telecom.Call.Details.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL, |
| |
| Connection.PROPERTY_IS_ADHOC_CONFERENCE, |
| android.telecom.Call.Details.PROPERTY_IS_ADHOC_CONFERENCE, |
| |
| Connection.PROPERTY_CROSS_SIM, |
| android.telecom.Call.Details.PROPERTY_CROSS_SIM |
| }; |
| |
| private static int convertConnectionToCallProperties(int connectionProperties) { |
| int callProperties = 0; |
| for (int i = 0; i < CONNECTION_TO_CALL_PROPERTIES.length; i += 2) { |
| if ((CONNECTION_TO_CALL_PROPERTIES[i] & connectionProperties) == |
| CONNECTION_TO_CALL_PROPERTIES[i]) { |
| |
| callProperties |= CONNECTION_TO_CALL_PROPERTIES[i + 1]; |
| } |
| } |
| return callProperties; |
| } |
| |
| /** |
| * Removes the specified capability from the set of capabilities bits and returns the new set. |
| */ |
| private static int removeCapability(int capabilities, int capability) { |
| return capabilities & ~capability; |
| } |
| |
| private static ParcelableRttCall getParcelableRttCall(Call call) { |
| if (!call.isRttCall()) { |
| return null; |
| } |
| return new ParcelableRttCall(call.getRttMode(), call.getInCallToCsRttPipeForInCall(), |
| call.getCsToInCallRttPipeForInCall()); |
| } |
| |
| private ParcelableCallUtils() {} |
| } |