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