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