blob: afd34fc74e4301bdd839f9ccdda5dc2aa709acc1 [file] [log] [blame]
Thomas Stuart9bfb2432022-09-27 15:02:07 -07001/*
2 * Copyright (C) 2022 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 android.telecom;
18
Thomas Stuart26b9bc72024-01-04 15:14:15 -080019import android.annotation.FlaggedApi;
Thomas Stuart9bfb2432022-09-27 15:02:07 -070020import android.annotation.IntDef;
21import android.annotation.NonNull;
22import android.annotation.Nullable;
23import android.net.Uri;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.text.TextUtils;
27
Thomas Stuart26b9bc72024-01-04 15:14:15 -080028import com.android.server.telecom.flags.Flags;
29
Anton Hanssonfaf2ba92023-11-09 19:11:54 +000030import java.lang.annotation.Retention;
31import java.lang.annotation.RetentionPolicy;
Thomas Stuart9bfb2432022-09-27 15:02:07 -070032import java.util.Objects;
33
34/**
35 * CallAttributes represents a set of properties that define a new Call. Apps should build an
36 * instance of this class and use {@link TelecomManager#addCall} to start a new call with Telecom.
37 *
38 * <p>
39 * Apps should first register a {@link PhoneAccount} via {@link TelecomManager#registerPhoneAccount}
40 * and use the same {@link PhoneAccountHandle} registered with Telecom when creating an
41 * instance of CallAttributes.
42 */
43public final class CallAttributes implements Parcelable {
44
45 /** PhoneAccountHandle associated with the App managing calls **/
46 private final PhoneAccountHandle mPhoneAccountHandle;
47
48 /** Display name of the person on the other end of the call **/
49 private final CharSequence mDisplayName;
50
51 /** Address of the call. Note, this can be extended to a meeting link **/
52 private final Uri mAddress;
53
54 /** The direction (Outgoing/Incoming) of the new Call **/
55 @Direction private final int mDirection;
56
57 /** Information related to data being transmitted (voice, video, etc. ) **/
58 @CallType private final int mCallType;
59
60 /** Allows a package to opt into capabilities on the telecom side, on a per-call basis **/
61 @CallCapability private final int mCallCapabilities;
62
63 /** @hide **/
64 public static final String CALL_CAPABILITIES_KEY = "TelecomCapabilities";
65
Grace Jia13284d12022-12-01 14:02:17 -080066 /** @hide **/
Tyler Gunndd2001c2023-05-08 00:08:33 +000067 public static final String DISPLAY_NAME_KEY = "DisplayName";
68
69 /** @hide **/
Thomas Stuartf959db02023-04-05 16:59:01 -070070 public static final String CALLER_PID_KEY = "CallerPid";
71
72 /** @hide **/
73 public static final String CALLER_UID_KEY = "CallerUid";
Grace Jia13284d12022-12-01 14:02:17 -080074
Thomas Stuart9bfb2432022-09-27 15:02:07 -070075 private CallAttributes(@NonNull PhoneAccountHandle phoneAccountHandle,
76 @NonNull CharSequence displayName,
77 @NonNull Uri address,
78 int direction,
79 int callType,
80 int callCapabilities) {
81 mPhoneAccountHandle = phoneAccountHandle;
82 mDisplayName = displayName;
83 mAddress = address;
84 mDirection = direction;
85 mCallType = callType;
86 mCallCapabilities = callCapabilities;
87 }
88
89 /** @hide */
90 @IntDef(value = {DIRECTION_INCOMING, DIRECTION_OUTGOING})
Anton Hanssonfaf2ba92023-11-09 19:11:54 +000091 @Retention(RetentionPolicy.SOURCE)
Thomas Stuart9bfb2432022-09-27 15:02:07 -070092 public @interface Direction {
93 }
94 /**
95 * Indicates that the call is an incoming call.
96 */
97 public static final int DIRECTION_INCOMING = 1;
98 /**
99 * Indicates that the call is an outgoing call.
100 */
101 public static final int DIRECTION_OUTGOING = 2;
102
103 /** @hide */
104 @IntDef(value = {AUDIO_CALL, VIDEO_CALL})
Anton Hanssonfaf2ba92023-11-09 19:11:54 +0000105 @Retention(RetentionPolicy.SOURCE)
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700106 public @interface CallType {
107 }
108 /**
109 * Used when answering or dialing a call to indicate that the call does not have a video
110 * component
111 */
112 public static final int AUDIO_CALL = 1;
113 /**
114 * Indicates video transmission is supported
115 */
116 public static final int VIDEO_CALL = 2;
117
118 /** @hide */
Thomas Stuart26b9bc72024-01-04 15:14:15 -0800119 @IntDef(value = {SUPPORTS_SET_INACTIVE, SUPPORTS_STREAM, SUPPORTS_TRANSFER,
120 SUPPORTS_VIDEO_CALLING}, flag = true)
Anton Hanssonfaf2ba92023-11-09 19:11:54 +0000121 @Retention(RetentionPolicy.SOURCE)
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700122 public @interface CallCapability {
123 }
124 /**
125 * The call being created can be set to inactive (traditionally referred to as hold). This
126 * means that once a new call goes active, if the active call needs to be held in order to
127 * place or receive an incoming call, the active call will be placed on hold. otherwise, the
128 * active call may be disconnected.
129 */
130 public static final int SUPPORTS_SET_INACTIVE = 1 << 1;
131 /**
132 * The call can be streamed from a root device to another device to continue the call without
133 * completely transferring it.
134 */
135 public static final int SUPPORTS_STREAM = 1 << 2;
136 /**
Tyler Gunn10d15032023-02-07 10:13:25 -0800137 * The call can be completely transferred from one endpoint to another.
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700138 */
139 public static final int SUPPORTS_TRANSFER = 1 << 3;
Thomas Stuart26b9bc72024-01-04 15:14:15 -0800140 /**
141 * The call supports video calling. This allows clients to gate video calling on a per call
142 * basis as opposed to re-registering the phone account.
143 */
144 @FlaggedApi(Flags.FLAG_TRANSACTIONAL_VIDEO_STATE)
145 public static final int SUPPORTS_VIDEO_CALLING = 1 << 4;
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700146
147 /**
148 * Build an instance of {@link CallAttributes}. In order to build a valid instance, a
Tyler Gunn10d15032023-02-07 10:13:25 -0800149 * {@link PhoneAccountHandle}, call direction, display name, and {@link Uri} address
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700150 * are required.
151 *
152 * <p>
153 * Note: Pass in the same {@link PhoneAccountHandle} that was used to register a
154 * {@link PhoneAccount} with Telecom. see {@link TelecomManager#registerPhoneAccount}
155 */
156 public static final class Builder {
157 // required and final fields
158 private final PhoneAccountHandle mPhoneAccountHandle;
159 @Direction private final int mDirection;
160 private final CharSequence mDisplayName;
161 private final Uri mAddress;
162 // optional fields
163 @CallType private int mCallType = CallAttributes.AUDIO_CALL;
164 @CallCapability private int mCallCapabilities = SUPPORTS_SET_INACTIVE;
165
166 /**
167 * Constructor for the CallAttributes.Builder class
168 *
169 * @param phoneAccountHandle that belongs to package registered with Telecom
170 * @param callDirection of the new call that will be added to Telecom
171 * @param displayName of the caller for incoming calls or initiating user for outgoing calls
172 * @param address of the caller for incoming calls or destination for outgoing calls
173 */
174 public Builder(@NonNull PhoneAccountHandle phoneAccountHandle,
175 @Direction int callDirection, @NonNull CharSequence displayName,
176 @NonNull Uri address) {
177 if (!isInRange(DIRECTION_INCOMING, DIRECTION_OUTGOING, callDirection)) {
178 throw new IllegalArgumentException(TextUtils.formatSimple("CallDirection=[%d] is"
179 + " invalid. CallDirections value should be within [%d, %d]",
180 callDirection, DIRECTION_INCOMING, DIRECTION_OUTGOING));
181 }
182 Objects.requireNonNull(phoneAccountHandle);
183 Objects.requireNonNull(displayName);
184 Objects.requireNonNull(address);
185 mPhoneAccountHandle = phoneAccountHandle;
186 mDirection = callDirection;
187 mDisplayName = displayName;
188 mAddress = address;
189 }
190
191 /**
Tyler Gunn10d15032023-02-07 10:13:25 -0800192 * Sets the type of call; uses to indicate if a call is a video call or audio call.
193 * @param callType The call type.
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700194 * @return Builder
195 */
196 @NonNull
197 public Builder setCallType(@CallType int callType) {
198 if (!isInRange(AUDIO_CALL, VIDEO_CALL, callType)) {
199 throw new IllegalArgumentException(TextUtils.formatSimple("CallType=[%d] is"
200 + " invalid. CallTypes value should be within [%d, %d]",
201 callType, AUDIO_CALL, VIDEO_CALL));
202 }
203 mCallType = callType;
204 return this;
205 }
206
207 /**
Tyler Gunn10d15032023-02-07 10:13:25 -0800208 * Sets the capabilities of this call. Use this to indicate whether your app supports
209 * holding, streaming and call transfers.
210 * @param callCapabilities Bitmask of call capabilities.
Thomas Stuart9bfb2432022-09-27 15:02:07 -0700211 * @return Builder
212 */
213 @NonNull
214 public Builder setCallCapabilities(@CallCapability int callCapabilities) {
215 mCallCapabilities = callCapabilities;
216 return this;
217 }
218
219 /**
220 * Build an instance of {@link CallAttributes} based on the last values passed to the
221 * setters or default values.
222 *
223 * @return an instance of {@link CallAttributes}
224 */
225 @NonNull
226 public CallAttributes build() {
227 return new CallAttributes(mPhoneAccountHandle, mDisplayName, mAddress, mDirection,
228 mCallType, mCallCapabilities);
229 }
230
231 /** @hide */
232 private boolean isInRange(int floor, int ceiling, int value) {
233 return value >= floor && value <= ceiling;
234 }
235 }
236
237 /**
238 * The {@link PhoneAccountHandle} that should be registered to Telecom to allow calls. The
239 * {@link PhoneAccountHandle} should be registered before creating a CallAttributes instance.
240 *
241 * @return the {@link PhoneAccountHandle} for this package that allows this call to be created
242 */
243 @NonNull public PhoneAccountHandle getPhoneAccountHandle() {
244 return mPhoneAccountHandle;
245 }
246
247 /**
248 * @return display name of the incoming caller or the person being called for an outgoing call
249 */
250 @NonNull public CharSequence getDisplayName() {
251 return mDisplayName;
252 }
253
254 /**
255 * @return address of the incoming caller
256 * or the address of the person being called for an outgoing call
257 */
258 @NonNull public Uri getAddress() {
259 return mAddress;
260 }
261
262 /**
263 * @return the direction of the new call.
264 */
265 public @Direction int getDirection() {
266 return mDirection;
267 }
268
269 /**
270 * @return Information related to data being transmitted (voice, video, etc. )
271 */
272 public @CallType int getCallType() {
273 return mCallType;
274 }
275
276 /**
277 * @return The allowed capabilities of the new call
278 */
279 public @CallCapability int getCallCapabilities() {
280 return mCallCapabilities;
281 }
282
283 @Override
284 public int describeContents() {
285 return 0;
286 }
287
288 @Override
289 public void writeToParcel(@Nullable Parcel dest, int flags) {
290 dest.writeParcelable(mPhoneAccountHandle, flags);
291 dest.writeCharSequence(mDisplayName);
292 dest.writeParcelable(mAddress, flags);
293 dest.writeInt(mDirection);
294 dest.writeInt(mCallType);
295 dest.writeInt(mCallCapabilities);
296 }
297
298 /**
299 * Responsible for creating CallAttribute objects for deserialized Parcels.
300 */
301 public static final @android.annotation.NonNull
302 Parcelable.Creator<CallAttributes> CREATOR =
303 new Parcelable.Creator<>() {
304 @Override
305 public CallAttributes createFromParcel(Parcel source) {
306 return new CallAttributes(source.readParcelable(getClass().getClassLoader(),
307 android.telecom.PhoneAccountHandle.class),
308 source.readCharSequence(),
309 source.readParcelable(getClass().getClassLoader(),
310 android.net.Uri.class),
311 source.readInt(),
312 source.readInt(),
313 source.readInt());
314 }
315
316 @Override
317 public CallAttributes[] newArray(int size) {
318 return new CallAttributes[size];
319 }
320 };
321
322 /**
323 * {@inheritDoc}
324 */
325 @Override
326 public String toString() {
327 StringBuilder sb = new StringBuilder();
328
329 sb.append("{ CallAttributes: [phoneAccountHandle: ")
330 .append(mPhoneAccountHandle) /* PhoneAccountHandle#toString handles PII */
331 .append("], [contactName: ")
332 .append(Log.pii(mDisplayName))
333 .append("], [address=")
334 .append(Log.pii(mAddress))
335 .append("], [direction=")
336 .append(mDirection)
337 .append("], [callType=")
338 .append(mCallType)
339 .append("], [mCallCapabilities=")
340 .append(mCallCapabilities)
341 .append("] }");
342
343 return sb.toString();
344 }
345
346 /**
347 * {@inheritDoc}
348 */
349 @Override
350 public boolean equals(Object obj) {
351 if (obj == null || obj.getClass() != this.getClass()) {
352 return false;
353 }
354 CallAttributes that = (CallAttributes) obj;
355 return this.mDirection == that.mDirection
356 && this.mCallType == that.mCallType
357 && this.mCallCapabilities == that.mCallCapabilities
358 && Objects.equals(this.mPhoneAccountHandle, that.mPhoneAccountHandle)
359 && Objects.equals(this.mAddress, that.mAddress)
360 && Objects.equals(this.mDisplayName, that.mDisplayName);
361 }
362
363 /**
364 * {@inheritDoc}
365 */
366 @Override
367 public int hashCode() {
368 return Objects.hash(mPhoneAccountHandle, mAddress, mDisplayName,
369 mDirection, mCallType, mCallCapabilities);
370 }
371}