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