ParcelableCallUtils.java revision 571d5e66b8cbee023702b4b0a2a1c28663c5a7f8
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 17package com.android.server.telecom; 18 19import android.net.Uri; 20import android.telecom.Connection; 21import android.telecom.ParcelableCall; 22import android.telecom.TelecomManager; 23 24import java.util.ArrayList; 25import java.util.List; 26 27/** 28 * Utilities dealing with {@link ParcelableCall}. 29 */ 30public class ParcelableCallUtils { 31 /** 32 * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance. 33 * 34 * @param call The {@link Call} to parcel. 35 * @param includeVideoProvider {@code true} if the video provider should be parcelled with the 36 * {@link Call}, {@code false} otherwise. Since the {@link ParcelableCall#getVideoCall()} 37 * method creates a {@link VideoCallImpl} instance on access it is important for the 38 * recipient of the {@link ParcelableCall} to know if the video provider changed. 39 * @param phoneAccountRegistrar The {@link PhoneAccountRegistrar}. 40 * @return The {@link ParcelableCall} containing all call information from the {@link Call}. 41 */ 42 public static ParcelableCall toParcelableCall( 43 Call call, 44 boolean includeVideoProvider, 45 PhoneAccountRegistrar phoneAccountRegistrar) { 46 int state = getParcelableState(call); 47 int capabilities = convertConnectionToCallCapabilities(call.getConnectionCapabilities()); 48 int properties = convertConnectionToCallProperties(call.getConnectionProperties()); 49 if (call.isConference()) { 50 properties |= android.telecom.Call.Details.PROPERTY_CONFERENCE; 51 } 52 53 if (call.isWorkCall()) { 54 properties |= android.telecom.Call.Details.PROPERTY_WORK_CALL; 55 } 56 57 // If this is a single-SIM device, the "default SIM" will always be the only SIM. 58 boolean isDefaultSmsAccount = 59 phoneAccountRegistrar.isUserSelectedSmsPhoneAccount(call.getTargetPhoneAccount()); 60 if (call.isRespondViaSmsCapable() && isDefaultSmsAccount) { 61 capabilities |= android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT; 62 } 63 64 if (call.isEmergencyCall()) { 65 capabilities = removeCapability( 66 capabilities, android.telecom.Call.Details.CAPABILITY_MUTE); 67 } 68 69 if (state == android.telecom.Call.STATE_DIALING) { 70 capabilities = removeCapability(capabilities, 71 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL); 72 capabilities = removeCapability(capabilities, 73 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); 74 } 75 76 String parentCallId = null; 77 Call parentCall = call.getParentCall(); 78 if (parentCall != null) { 79 parentCallId = parentCall.getId(); 80 } 81 82 long connectTimeMillis = call.getConnectTimeMillis(); 83 List<Call> childCalls = call.getChildCalls(); 84 List<String> childCallIds = new ArrayList<>(); 85 if (!childCalls.isEmpty()) { 86 long childConnectTimeMillis = Long.MAX_VALUE; 87 for (Call child : childCalls) { 88 if (child.getConnectTimeMillis() > 0) { 89 childConnectTimeMillis = Math.min(child.getConnectTimeMillis(), 90 childConnectTimeMillis); 91 } 92 childCallIds.add(child.getId()); 93 } 94 95 if (childConnectTimeMillis != Long.MAX_VALUE) { 96 connectTimeMillis = childConnectTimeMillis; 97 } 98 } 99 100 Uri handle = call.getHandlePresentation() == TelecomManager.PRESENTATION_ALLOWED ? 101 call.getHandle() : null; 102 String callerDisplayName = call.getCallerDisplayNamePresentation() == 103 TelecomManager.PRESENTATION_ALLOWED ? call.getCallerDisplayName() : null; 104 105 List<Call> conferenceableCalls = call.getConferenceableCalls(); 106 List<String> conferenceableCallIds = new ArrayList<String>(conferenceableCalls.size()); 107 for (Call otherCall : conferenceableCalls) { 108 conferenceableCallIds.add(otherCall.getId()); 109 } 110 111 return new ParcelableCall( 112 call.getId(), 113 state, 114 call.getDisconnectCause(), 115 call.getCannedSmsResponses(), 116 capabilities, 117 properties, 118 connectTimeMillis, 119 handle, 120 call.getHandlePresentation(), 121 callerDisplayName, 122 call.getCallerDisplayNamePresentation(), 123 call.getGatewayInfo(), 124 call.getTargetPhoneAccount(), 125 includeVideoProvider, 126 includeVideoProvider ? call.getVideoProvider() : null, 127 parentCallId, 128 childCallIds, 129 call.getStatusHints(), 130 call.getVideoState(), 131 conferenceableCallIds, 132 call.getIntentExtras(), 133 call.getExtras()); 134 } 135 136 private static int getParcelableState(Call call) { 137 int state = CallState.NEW; 138 switch (call.getState()) { 139 case CallState.ABORTED: 140 case CallState.DISCONNECTED: 141 state = android.telecom.Call.STATE_DISCONNECTED; 142 break; 143 case CallState.ACTIVE: 144 state = android.telecom.Call.STATE_ACTIVE; 145 break; 146 case CallState.CONNECTING: 147 state = android.telecom.Call.STATE_CONNECTING; 148 break; 149 case CallState.DIALING: 150 state = android.telecom.Call.STATE_DIALING; 151 break; 152 case CallState.DISCONNECTING: 153 state = android.telecom.Call.STATE_DISCONNECTING; 154 break; 155 case CallState.NEW: 156 state = android.telecom.Call.STATE_NEW; 157 break; 158 case CallState.ON_HOLD: 159 state = android.telecom.Call.STATE_HOLDING; 160 break; 161 case CallState.RINGING: 162 state = android.telecom.Call.STATE_RINGING; 163 break; 164 case CallState.SELECT_PHONE_ACCOUNT: 165 state = android.telecom.Call.STATE_SELECT_PHONE_ACCOUNT; 166 break; 167 } 168 169 // If we are marked as 'locally disconnecting' then mark ourselves as disconnecting instead. 170 // Unless we're disconnect*ED*, in which case leave it at that. 171 if (call.isLocallyDisconnecting() && 172 (state != android.telecom.Call.STATE_DISCONNECTED)) { 173 state = android.telecom.Call.STATE_DISCONNECTING; 174 } 175 return state; 176 } 177 178 private static final int[] CONNECTION_TO_CALL_CAPABILITY = new int[] { 179 Connection.CAPABILITY_HOLD, 180 android.telecom.Call.Details.CAPABILITY_HOLD, 181 182 Connection.CAPABILITY_SUPPORT_HOLD, 183 android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD, 184 185 Connection.CAPABILITY_MERGE_CONFERENCE, 186 android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE, 187 188 Connection.CAPABILITY_SWAP_CONFERENCE, 189 android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE, 190 191 Connection.CAPABILITY_RESPOND_VIA_TEXT, 192 android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT, 193 194 Connection.CAPABILITY_MUTE, 195 android.telecom.Call.Details.CAPABILITY_MUTE, 196 197 Connection.CAPABILITY_MANAGE_CONFERENCE, 198 android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE, 199 200 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_RX, 201 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_RX, 202 203 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_TX, 204 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX, 205 206 Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, 207 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, 208 209 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_RX, 210 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX, 211 212 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_TX, 213 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_TX, 214 215 Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, 216 android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, 217 218 Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE, 219 android.telecom.Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE, 220 221 Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE, 222 android.telecom.Call.Details.CAPABILITY_DISCONNECT_FROM_CONFERENCE, 223 224 Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO, 225 android.telecom.Call.Details.CAPABILITY_CAN_UPGRADE_TO_VIDEO, 226 227 Connection.CAPABILITY_CAN_PAUSE_VIDEO, 228 android.telecom.Call.Details.CAPABILITY_CAN_PAUSE_VIDEO, 229 230 Connection.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, 231 android.telecom.Call.Details.CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION, 232 233 Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, 234 android.telecom.Call.Details.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, 235 236 Connection.CAPABILITY_CAN_PULL_CALL, 237 android.telecom.Call.Details.CAPABILITY_CAN_PULL_CALL 238 }; 239 240 private static int convertConnectionToCallCapabilities(int connectionCapabilities) { 241 int callCapabilities = 0; 242 for (int i = 0; i < CONNECTION_TO_CALL_CAPABILITY.length; i += 2) { 243 if ((CONNECTION_TO_CALL_CAPABILITY[i] & connectionCapabilities) == 244 CONNECTION_TO_CALL_CAPABILITY[i]) { 245 246 callCapabilities |= CONNECTION_TO_CALL_CAPABILITY[i + 1]; 247 } 248 } 249 return callCapabilities; 250 } 251 252 private static final int[] CONNECTION_TO_CALL_PROPERTIES = new int[] { 253 Connection.PROPERTY_HIGH_DEF_AUDIO, 254 android.telecom.Call.Details.PROPERTY_HIGH_DEF_AUDIO, 255 256 Connection.PROPERTY_WIFI, 257 android.telecom.Call.Details.PROPERTY_WIFI, 258 259 Connection.PROPERTY_GENERIC_CONFERENCE, 260 android.telecom.Call.Details.PROPERTY_GENERIC_CONFERENCE, 261 262 Connection.PROPERTY_SHOW_CALLBACK_NUMBER, 263 android.telecom.Call.Details.PROPERTY_EMERGENCY_CALLBACK_MODE, 264 265 Connection.PROPERTY_IS_EXTERNAL_CALL, 266 android.telecom.Call.Details.PROPERTY_IS_EXTERNAL_CALL 267 }; 268 269 private static int convertConnectionToCallProperties(int connectionProperties) { 270 int callProperties = 0; 271 for (int i = 0; i < CONNECTION_TO_CALL_PROPERTIES.length; i += 2) { 272 if ((CONNECTION_TO_CALL_PROPERTIES[i] & connectionProperties) == 273 CONNECTION_TO_CALL_PROPERTIES[i]) { 274 275 callProperties |= CONNECTION_TO_CALL_PROPERTIES[i + 1]; 276 } 277 } 278 return callProperties; 279 } 280 281 /** 282 * Removes the specified capability from the set of capabilities bits and returns the new set. 283 */ 284 private static int removeCapability(int capabilities, int capability) { 285 return capabilities & ~capability; 286 } 287 288 private ParcelableCallUtils() {} 289} 290