blob: 6d879817b21dd4297f9168c4059e698a9647ce9d [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 /**
119 * The call can be completely transferred from one endpoint to another
120 */
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
125 * {@link PhoneAccountHandle}, call {@link Direction}, display name, and {@link Uri} address
126 * 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 /**
168 * @param callType see {@link CallType} for valid arguments
169 * @return Builder
170 */
171 @NonNull
172 public Builder setCallType(@CallType int callType) {
173 if (!isInRange(AUDIO_CALL, VIDEO_CALL, callType)) {
174 throw new IllegalArgumentException(TextUtils.formatSimple("CallType=[%d] is"
175 + " invalid. CallTypes value should be within [%d, %d]",
176 callType, AUDIO_CALL, VIDEO_CALL));
177 }
178 mCallType = callType;
179 return this;
180 }
181
182 /**
183 * @param callCapabilities see {@link CallCapability} for valid arguments
184 * @return Builder
185 */
186 @NonNull
187 public Builder setCallCapabilities(@CallCapability int callCapabilities) {
188 mCallCapabilities = callCapabilities;
189 return this;
190 }
191
192 /**
193 * Build an instance of {@link CallAttributes} based on the last values passed to the
194 * setters or default values.
195 *
196 * @return an instance of {@link CallAttributes}
197 */
198 @NonNull
199 public CallAttributes build() {
200 return new CallAttributes(mPhoneAccountHandle, mDisplayName, mAddress, mDirection,
201 mCallType, mCallCapabilities);
202 }
203
204 /** @hide */
205 private boolean isInRange(int floor, int ceiling, int value) {
206 return value >= floor && value <= ceiling;
207 }
208 }
209
210 /**
211 * The {@link PhoneAccountHandle} that should be registered to Telecom to allow calls. The
212 * {@link PhoneAccountHandle} should be registered before creating a CallAttributes instance.
213 *
214 * @return the {@link PhoneAccountHandle} for this package that allows this call to be created
215 */
216 @NonNull public PhoneAccountHandle getPhoneAccountHandle() {
217 return mPhoneAccountHandle;
218 }
219
220 /**
221 * @return display name of the incoming caller or the person being called for an outgoing call
222 */
223 @NonNull public CharSequence getDisplayName() {
224 return mDisplayName;
225 }
226
227 /**
228 * @return address of the incoming caller
229 * or the address of the person being called for an outgoing call
230 */
231 @NonNull public Uri getAddress() {
232 return mAddress;
233 }
234
235 /**
236 * @return the direction of the new call.
237 */
238 public @Direction int getDirection() {
239 return mDirection;
240 }
241
242 /**
243 * @return Information related to data being transmitted (voice, video, etc. )
244 */
245 public @CallType int getCallType() {
246 return mCallType;
247 }
248
249 /**
250 * @return The allowed capabilities of the new call
251 */
252 public @CallCapability int getCallCapabilities() {
253 return mCallCapabilities;
254 }
255
256 @Override
257 public int describeContents() {
258 return 0;
259 }
260
261 @Override
262 public void writeToParcel(@Nullable Parcel dest, int flags) {
263 dest.writeParcelable(mPhoneAccountHandle, flags);
264 dest.writeCharSequence(mDisplayName);
265 dest.writeParcelable(mAddress, flags);
266 dest.writeInt(mDirection);
267 dest.writeInt(mCallType);
268 dest.writeInt(mCallCapabilities);
269 }
270
271 /**
272 * Responsible for creating CallAttribute objects for deserialized Parcels.
273 */
274 public static final @android.annotation.NonNull
275 Parcelable.Creator<CallAttributes> CREATOR =
276 new Parcelable.Creator<>() {
277 @Override
278 public CallAttributes createFromParcel(Parcel source) {
279 return new CallAttributes(source.readParcelable(getClass().getClassLoader(),
280 android.telecom.PhoneAccountHandle.class),
281 source.readCharSequence(),
282 source.readParcelable(getClass().getClassLoader(),
283 android.net.Uri.class),
284 source.readInt(),
285 source.readInt(),
286 source.readInt());
287 }
288
289 @Override
290 public CallAttributes[] newArray(int size) {
291 return new CallAttributes[size];
292 }
293 };
294
295 /**
296 * {@inheritDoc}
297 */
298 @Override
299 public String toString() {
300 StringBuilder sb = new StringBuilder();
301
302 sb.append("{ CallAttributes: [phoneAccountHandle: ")
303 .append(mPhoneAccountHandle) /* PhoneAccountHandle#toString handles PII */
304 .append("], [contactName: ")
305 .append(Log.pii(mDisplayName))
306 .append("], [address=")
307 .append(Log.pii(mAddress))
308 .append("], [direction=")
309 .append(mDirection)
310 .append("], [callType=")
311 .append(mCallType)
312 .append("], [mCallCapabilities=")
313 .append(mCallCapabilities)
314 .append("] }");
315
316 return sb.toString();
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 @Override
323 public boolean equals(Object obj) {
324 if (obj == null || obj.getClass() != this.getClass()) {
325 return false;
326 }
327 CallAttributes that = (CallAttributes) obj;
328 return this.mDirection == that.mDirection
329 && this.mCallType == that.mCallType
330 && this.mCallCapabilities == that.mCallCapabilities
331 && Objects.equals(this.mPhoneAccountHandle, that.mPhoneAccountHandle)
332 && Objects.equals(this.mAddress, that.mAddress)
333 && Objects.equals(this.mDisplayName, that.mDisplayName);
334 }
335
336 /**
337 * {@inheritDoc}
338 */
339 @Override
340 public int hashCode() {
341 return Objects.hash(mPhoneAccountHandle, mAddress, mDisplayName,
342 mDirection, mCallType, mCallCapabilities);
343 }
344}