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