• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 
17 package android.telecom;
18 
19 import static android.Manifest.permission.MODIFY_PHONE_STATE;
20 
21 import android.annotation.FlaggedApi;
22 import android.annotation.NonNull;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.content.Intent;
26 import android.graphics.drawable.Icon;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 import android.telephony.CarrierConfigManager;
32 import android.telephony.TelephonyManager;
33 import android.text.TextUtils;
34 import android.util.ArraySet;
35 
36 import com.android.internal.telephony.flags.Flags;
37 
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.Set;
43 
44 /**
45  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
46  * want those calls to be integrated into the dialer and in-call UI should build an instance of
47  * this class and register it with the system using {@link TelecomManager}.
48  * <p>
49  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
50  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
51  * should supply a valid {@link PhoneAccountHandle} that references the connection service
52  * implementation Telecom will use to interact with the app.
53  */
54 public final class PhoneAccount implements Parcelable {
55 
56     /**
57      * Integer extra which determines the order in which {@link PhoneAccount}s are sorted
58      *
59      * This is an extras key set via {@link Builder#setExtras} which determines the order in which
60      * {@link PhoneAccount}s from the same {@link ConnectionService} are sorted. The accounts
61      * are sorted in ascending order by this key, and this ordering is used to
62      * determine priority when a call can be placed via multiple accounts.
63      *
64      * When multiple {@link PhoneAccount}s are supplied with the same sort order key, no ordering is
65      * guaranteed between those {@link PhoneAccount}s. Additionally, no ordering is guaranteed
66      * between {@link PhoneAccount}s that do not supply this extra, and all such accounts
67      * will be sorted after the accounts that do supply this extra.
68      *
69      * An example of a sort order key is slot index (see {@link TelephonyManager#getSlotIndex()}),
70      * which is the one used by the cell Telephony stack.
71      * @hide
72      */
73     @SystemApi
74     public static final String EXTRA_SORT_ORDER =
75             "android.telecom.extra.SORT_ORDER";
76 
77     /**
78      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
79      * maximum permitted length of a call subject specified via the
80      * {@link TelecomManager#EXTRA_CALL_SUBJECT} extra on an
81      * {@link android.content.Intent#ACTION_CALL} intent.  Ultimately a {@link ConnectionService} is
82      * responsible for enforcing the maximum call subject length when sending the message, however
83      * this extra is provided so that the user interface can proactively limit the length of the
84      * call subject as the user types it.
85      */
86     public static final String EXTRA_CALL_SUBJECT_MAX_LENGTH =
87             "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
88 
89     /**
90      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
91      * character encoding to be used when determining the length of messages.
92      * The user interface can use this when determining the number of characters the user may type
93      * in a call subject.  If empty-string, the call subject message size limit will be enforced on
94      * a 1:1 basis.  That is, each character will count towards the messages size limit as a single
95      * character.  If a character encoding is specified, the message size limit will be based on the
96      * number of bytes in the message per the specified encoding.  See
97      * {@link #EXTRA_CALL_SUBJECT_MAX_LENGTH} for more information on the call subject maximum
98      * length.
99      */
100     public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING =
101             "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
102 
103     /**
104      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
105      * indicates that all calls from this {@link PhoneAccount} should be treated as VoIP calls
106      * rather than cellular calls by the Telecom audio handling logic.
107      */
108     public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE =
109             "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
110 
111     /**
112      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
113      * indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
114      * connection (see {@code android.telecom.Call#handoverTo()}) to this {@link PhoneAccount} from
115      * a {@link PhoneAccount} specifying {@link #EXTRA_SUPPORTS_HANDOVER_FROM}.
116      * <p>
117      * A handover request is initiated by the user from the default dialer app to indicate a desire
118      * to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
119      */
120     public static final String EXTRA_SUPPORTS_HANDOVER_TO =
121             "android.telecom.extra.SUPPORTS_HANDOVER_TO";
122 
123     /**
124      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
125      * indicates whether this {@link PhoneAccount} supports using a fallback if video calling is
126      * not available. This extra is for device level support, {@link
127      * android.telephony.CarrierConfigManager#KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL} should also
128      * be checked to ensure it is not disabled by individual carrier.
129      *
130      * @hide
131      */
132     public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK =
133             "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
134 
135     /**
136      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
137      * indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
138      * connection from this {@link PhoneAccount} to another {@link PhoneAccount}.
139      * (see {@code android.telecom.Call#handoverTo()}) which specifies
140      * {@link #EXTRA_SUPPORTS_HANDOVER_TO}.
141      * <p>
142      * A handover request is initiated by the user from the default dialer app to indicate a desire
143      * to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
144      */
145     public static final String EXTRA_SUPPORTS_HANDOVER_FROM =
146             "android.telecom.extra.SUPPORTS_HANDOVER_FROM";
147 
148 
149     /**
150      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
151      * indicates whether a Self-Managed {@link PhoneAccount} should log its calls to the call log.
152      * Self-Managed {@link PhoneAccount}s are responsible for their own notifications, so the system
153      * will not create a notification when a missed call is logged.
154      * <p>
155      * By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log.
156      * Setting this extra to {@code true} provides a means for them to log their calls.
157      * <p>
158      * Note: Only calls where the {@link Call.Details#getHandle()} {@link Uri#getScheme()} is
159      * {@link #SCHEME_SIP} or {@link #SCHEME_TEL} will be logged at the current time.
160      */
161     public static final String EXTRA_LOG_SELF_MANAGED_CALLS =
162             "android.telecom.extra.LOG_SELF_MANAGED_CALLS";
163 
164     /**
165      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
166      * indicates whether calls for a {@link PhoneAccount} should generate a "call recording tone"
167      * when the user is recording audio on the device.
168      * <p>
169      * The call recording tone is played over the telephony audio stream so that the remote party
170      * has an audible indication that it is possible their call is being recorded using a call
171      * recording app on the device.
172      * <p>
173      * This extra only has an effect for calls placed via Telephony (e.g.
174      * {@link #CAPABILITY_SIM_SUBSCRIPTION}).
175      * <p>
176      * The call recording tone is a 1400 hz tone which repeats every 15 seconds while recording is
177      * in progress.
178      * @hide
179      */
180     @SystemApi
181     public static final String EXTRA_PLAY_CALL_RECORDING_TONE =
182             "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
183 
184     /**
185      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()} which
186      * indicates whether calls for a {@link PhoneAccount} should skip call filtering.
187      * <p>
188      * If not specified, this will default to false; all calls will undergo call filtering unless
189      * specifically exempted (e.g. {@link Connection#PROPERTY_EMERGENCY_CALLBACK_MODE}.) However,
190      * this may be used to skip call filtering when it has already been performed on another device.
191      * @hide
192      */
193     @SystemApi
194     @FlaggedApi(com.android.server.telecom.flags.Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES)
195     public static final String EXTRA_SKIP_CALL_FILTERING =
196         "android.telecom.extra.SKIP_CALL_FILTERING";
197 
198     /**
199      * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
200      * indicates whether a Self-managed {@link PhoneAccount} want to expose its calls to all
201      * {@link InCallService} which declares the metadata
202      * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS}.
203      */
204     public static final String EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE =
205             "android.telecom.extra.ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE";
206 
207     /**
208      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
209      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
210      * will be allowed to manage phone calls including using its own proprietary phone-call
211      * implementation (like VoIP calling) to make calls instead of the telephony stack.
212      * <p>
213      * When a user opts to place a call using the SIM-based telephony stack, the
214      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
215      * if the user has explicitly selected it to be used as the default connection manager.
216      * <p>
217      * See {@link #getCapabilities}
218      */
219     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
220 
221     /**
222      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
223      * traditional SIM-based telephony calls. This account will be treated as a distinct method
224      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
225      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
226      * or place calls from the built-in telephony stack.
227      * <p>
228      * See {@link #getCapabilities}
229      * <p>
230      */
231     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
232 
233     /**
234      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
235      * subscription.
236      * <p>
237      * Only the Android framework can register a {@code PhoneAccount} having this capability.
238      * <p>
239      * See {@link #getCapabilities}
240      */
241     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
242 
243     /**
244      * Flag indicating that this {@code PhoneAccount} is currently able to place video calls.
245      * <p>
246      * See also {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING} which indicates whether the
247      * {@code PhoneAccount} supports placing video calls.
248      * <p>
249      * See {@link #getCapabilities}
250      */
251     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
252 
253     /**
254      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
255      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
256      * <p>
257      * See {@link #getCapabilities}
258      */
259     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
260 
261     /**
262      * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
263      * should only be used by system apps (and will be ignored for all other apps trying to use it).
264      * <p>
265      * See {@link #getCapabilities}
266      * @hide
267      */
268     @SystemApi
269     public static final int CAPABILITY_MULTI_USER = 0x20;
270 
271     /**
272      * Flag indicating that this {@code PhoneAccount} supports a subject for Calls.  This means a
273      * caller is able to specify a short subject line for an outgoing call.  A capable receiving
274      * device displays the call subject on the incoming call screen.
275      * <p>
276      * See {@link #getCapabilities}
277      */
278     public static final int CAPABILITY_CALL_SUBJECT = 0x40;
279 
280     /**
281      * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
282      * <p>
283      * See {@link #getCapabilities}
284      * @hide
285      */
286     @SystemApi
287     public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
288 
289     /**
290      * Flag indicating that for this {@code PhoneAccount}, the ability to make a video call to a
291      * number relies on presence.  Should only be set if the {@code PhoneAccount} also has
292      * {@link #CAPABILITY_VIDEO_CALLING}.
293      * <p>
294      * Note: As of Android 12, using the
295      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the
296      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether
297      * a contact's phone number supports video calling has been deprecated and should only be used
298      * on devices where {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set. On newer
299      * devices, applications must use {@link android.telephony.ims.RcsUceAdapter} instead to
300      * determine whether or not a contact's phone number supports carrier video calling.
301      * <p>
302      * See {@link #getCapabilities}
303      */
304     public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100;
305 
306     /**
307      * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed.
308      * <p>
309      * When set, Telecom will allow emergency video calls to be placed.  When not set, Telecom will
310      * convert all outgoing video calls to emergency numbers to audio-only.
311      * @hide
312      */
313     @SystemApi
314     public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
315 
316     /**
317      * Flag indicating that this {@link PhoneAccount} supports video calling.
318      * This is not an indication that the {@link PhoneAccount} is currently able to make a video
319      * call, but rather that it has the ability to make video calls (but not necessarily at this
320      * time).
321      * <p>
322      * Whether a {@link PhoneAccount} can make a video call is ultimately controlled by
323      * {@link #CAPABILITY_VIDEO_CALLING}, which indicates whether the {@link PhoneAccount} is
324      * currently capable of making a video call.  Consider a case where, for example, a
325      * {@link PhoneAccount} supports making video calls (e.g.
326      * {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}), but a current lack of network connectivity
327      * prevents video calls from being made (e.g. {@link #CAPABILITY_VIDEO_CALLING}).
328      * <p>
329      * See {@link #getCapabilities}
330      */
331     public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400;
332 
333     /**
334      * Flag indicating that this {@link PhoneAccount} is responsible for managing its own
335      * {@link Connection}s.  This type of {@link PhoneAccount} is ideal for use with standalone
336      * calling apps which do not wish to use the default phone app for {@link Connection} UX,
337      * but which want to leverage the call and audio routing capabilities of the Telecom framework.
338      * <p>
339      * When set, {@link Connection}s created by the self-managed {@link ConnectionService} will not
340      * be surfaced to implementations of the {@link InCallService} API.  Thus it is the
341      * responsibility of a self-managed {@link ConnectionService} to provide a user interface for
342      * its {@link Connection}s.
343      * <p>
344      * Self-managed {@link Connection}s will, however, be displayed on connected Bluetooth devices.
345      */
346     public static final int CAPABILITY_SELF_MANAGED = 0x800;
347 
348     /**
349      * Flag indicating that this {@link PhoneAccount} is capable of making a call with an
350      * RTT (Real-time text) session.
351      * When set, Telecom will attempt to open an RTT session on outgoing calls that specify
352      * that they should be placed with an RTT session , and the in-call app will be displayed
353      * with text entry fields for RTT. Likewise, the in-call app can request that an RTT
354      * session be opened during a call if this bit is set.
355      */
356     public static final int CAPABILITY_RTT = 0x1000;
357 
358     /**
359      * Flag indicating that this {@link PhoneAccount} is the preferred SIM subscription for
360      * emergency calls. A {@link PhoneAccount} that sets this capability must also
361      * set the {@link #CAPABILITY_SIM_SUBSCRIPTION} and {@link #CAPABILITY_PLACE_EMERGENCY_CALLS}
362      * capabilities. There must only be one emergency preferred {@link PhoneAccount} on the device.
363      * <p>
364      * When set, Telecom will prefer this {@link PhoneAccount} over others for emergency calling,
365      * even if the emergency call was placed with a specific {@link PhoneAccount} set using the
366      * extra{@link TelecomManager#EXTRA_PHONE_ACCOUNT_HANDLE} in
367      * {@link Intent#ACTION_CALL_EMERGENCY} or {@link TelecomManager#placeCall(Uri, Bundle)}.
368      *
369      * @hide
370      */
371     @SystemApi
372     public static final int CAPABILITY_EMERGENCY_PREFERRED = 0x2000;
373 
374     /**
375      * An adhoc conference call is established by providing a list of addresses to
376      * {@code TelecomManager#startConference(List<Uri>, int videoState)} where the
377      * {@link ConnectionService} is responsible for connecting all indicated participants
378      * to a conference simultaneously.
379      * This is in contrast to conferences formed by merging calls together (e.g. using
380      * {@link android.telecom.Call#mergeConference()}).
381      */
382     public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 0x4000;
383 
384     /**
385      * Flag indicating whether this {@link PhoneAccount} is capable of supporting the call composer
386      * functionality for enriched calls.
387      */
388     public static final int CAPABILITY_CALL_COMPOSER = 0x8000;
389 
390     /**
391      * Flag indicating that this {@link PhoneAccount} provides SIM-based voice calls, potentially as
392      * an over-the-top solution such as wi-fi calling.
393      *
394      * <p>Similar to {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}, this capability indicates this
395      * {@link PhoneAccount} has the ability to make voice calls (but not necessarily at this time).
396      * Whether this {@link PhoneAccount} can make a voice call is ultimately controlled by {@link
397      * #CAPABILITY_VOICE_CALLING_AVAILABLE}, which indicates whether this {@link PhoneAccount} is
398      * currently capable of making a voice call. Consider a case where, for example, a {@link
399      * PhoneAccount} supports making voice calls (e.g. {@link
400      * #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}), but a current lack of network connectivity
401      * prevents voice calls from being made (e.g. {@link #CAPABILITY_VOICE_CALLING_AVAILABLE}).
402      *
403      * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link
404      * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the
405      * associated requirements.
406      *
407      * @see #CAPABILITY_VOICE_CALLING_AVAILABLE
408      * @see #getCapabilities
409      */
410     public static final int CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS = 0x10000;
411 
412     /**
413      * Flag indicating that this {@link PhoneAccount} is <em>currently</em> able to place SIM-based
414      * voice calls, similar to {@link #CAPABILITY_VIDEO_CALLING}.
415      *
416      * <p>See also {@link #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}, which indicates whether
417      * the {@code PhoneAccount} supports placing SIM-based voice calls or not.
418      *
419      * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link
420      * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the
421      * associated requirements.
422      *
423      * @see #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS
424      * @see #getCapabilities
425      */
426     public static final int CAPABILITY_VOICE_CALLING_AVAILABLE = 0x20000;
427 
428 
429     /**
430      * Flag indicating that this {@link PhoneAccount} supports the use TelecomManager APIs that
431      * utilize {@link android.os.OutcomeReceiver}s or {@link java.util.function.Consumer}s.
432      * Be aware, if this capability is set, {@link #CAPABILITY_SELF_MANAGED} will be amended by
433      * Telecom when this {@link PhoneAccount} is registered via
434      * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}.
435      *
436      * <p>
437      * {@link android.os.OutcomeReceiver}s and {@link java.util.function.Consumer}s represent
438      * transactional operations because the operation can succeed or fail.  An app wishing to use
439      * transactional operations should define behavior for a successful and failed TelecomManager
440      * API call.
441      *
442      * @see #CAPABILITY_SELF_MANAGED
443      * @see #getCapabilities
444      */
445     public static final int CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS = 0x40000;
446 
447     /**
448      * Flag indicating that this voip app {@link PhoneAccount} supports the call streaming session
449      * to stream call audio to another remote device via streaming app.
450      *
451      * @see #getCapabilities
452      */
453     public static final int CAPABILITY_SUPPORTS_CALL_STREAMING = 0x80000;
454 
455     /* NEXT CAPABILITY: [0x100000, 0x200000, 0x400000] */
456 
457     /**
458      * URI scheme for telephone number URIs.
459      */
460     public static final String SCHEME_TEL = "tel";
461 
462     /**
463      * URI scheme for voicemail URIs.
464      */
465     public static final String SCHEME_VOICEMAIL = "voicemail";
466 
467     /**
468      * URI scheme for SIP URIs.
469      */
470     public static final String SCHEME_SIP = "sip";
471 
472     /**
473      * Indicating no icon tint is set.
474      * @hide
475      */
476     public static final int NO_ICON_TINT = 0;
477 
478     /**
479      * Indicating no hightlight color is set.
480      */
481     public static final int NO_HIGHLIGHT_COLOR = 0;
482 
483     /**
484      * Indicating no resource ID is set.
485      */
486     public static final int NO_RESOURCE_ID = -1;
487 
488     private final PhoneAccountHandle mAccountHandle;
489     private final Uri mAddress;
490     private final Uri mSubscriptionAddress;
491     private final int mCapabilities;
492     private final int mHighlightColor;
493     private final CharSequence mLabel;
494     private final CharSequence mShortDescription;
495     private final List<String> mSupportedUriSchemes;
496     private final int mSupportedAudioRoutes;
497     private final Icon mIcon;
498     private final Bundle mExtras;
499     private boolean mIsEnabled;
500     private String mGroupId;
501     private final Set<PhoneAccountHandle> mSimultaneousCallingRestriction;
502 
503     @Override
equals(Object o)504     public boolean equals(Object o) {
505         if (this == o) return true;
506         if (o == null || getClass() != o.getClass()) return false;
507         PhoneAccount that = (PhoneAccount) o;
508         return mCapabilities == that.mCapabilities &&
509                 mHighlightColor == that.mHighlightColor &&
510                 mSupportedAudioRoutes == that.mSupportedAudioRoutes &&
511                 mIsEnabled == that.mIsEnabled &&
512                 Objects.equals(mAccountHandle, that.mAccountHandle) &&
513                 Objects.equals(mAddress, that.mAddress) &&
514                 Objects.equals(mSubscriptionAddress, that.mSubscriptionAddress) &&
515                 Objects.equals(mLabel, that.mLabel) &&
516                 Objects.equals(mShortDescription, that.mShortDescription) &&
517                 Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) &&
518                 areBundlesEqual(mExtras, that.mExtras) &&
519                 Objects.equals(mGroupId, that.mGroupId)
520                 && Objects.equals(mSimultaneousCallingRestriction,
521                         that.mSimultaneousCallingRestriction);
522     }
523 
524     @Override
hashCode()525     public int hashCode() {
526         return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities,
527                 mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes,
528                 mSupportedAudioRoutes,
529                 mExtras, mIsEnabled, mGroupId, mSimultaneousCallingRestriction);
530     }
531 
532     /**
533      * Helper class for creating a {@link PhoneAccount}.
534      */
535     public static class Builder {
536 
537         private PhoneAccountHandle mAccountHandle;
538         private Uri mAddress;
539         private Uri mSubscriptionAddress;
540         private int mCapabilities;
541         private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
542         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
543         private CharSequence mLabel;
544         private CharSequence mShortDescription;
545         private List<String> mSupportedUriSchemes = new ArrayList<String>();
546         private Icon mIcon;
547         private Bundle mExtras;
548         private boolean mIsEnabled = false;
549         private String mGroupId = "";
550         private Set<PhoneAccountHandle> mSimultaneousCallingRestriction = null;
551 
552         /**
553          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
554          * <p>
555          * Note: each CharSequence or String field is limited to 256 characters. This check is
556          * enforced when registering the PhoneAccount via
557          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
558          * {@link IllegalArgumentException} to be thrown if the character field limit is over 256.
559          */
Builder(PhoneAccountHandle accountHandle, CharSequence label)560         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
561             this.mAccountHandle = accountHandle;
562             this.mLabel = label;
563         }
564 
565         /**
566          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
567          * {@link PhoneAccount}.
568          *
569          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
570          */
Builder(PhoneAccount phoneAccount)571         public Builder(PhoneAccount phoneAccount) {
572             mAccountHandle = phoneAccount.getAccountHandle();
573             mAddress = phoneAccount.getAddress();
574             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
575             mCapabilities = phoneAccount.getCapabilities();
576             mHighlightColor = phoneAccount.getHighlightColor();
577             mLabel = phoneAccount.getLabel();
578             mShortDescription = phoneAccount.getShortDescription();
579             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
580             mIcon = phoneAccount.getIcon();
581             mIsEnabled = phoneAccount.isEnabled();
582             mExtras = phoneAccount.getExtras();
583             mGroupId = phoneAccount.getGroupId();
584             mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
585             if (phoneAccount.hasSimultaneousCallingRestriction()) {
586                 mSimultaneousCallingRestriction = phoneAccount.getSimultaneousCallingRestriction();
587             }
588         }
589 
590         /**
591          * Sets the label. See {@link PhoneAccount#getLabel()}.
592          * <p>
593          * Note: Each CharSequence or String field is limited to 256 characters. This check is
594          * enforced when registering the PhoneAccount via
595          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
596          * {@link IllegalArgumentException} to be thrown if the character field limit is over 256.
597          *
598          * @param label The label of the phone account.
599          * @return The builder.
600          * @hide
601          */
setLabel(CharSequence label)602         public Builder setLabel(CharSequence label) {
603             this.mLabel = label;
604             return this;
605         }
606 
607         /**
608          * Sets the address. See {@link PhoneAccount#getAddress}.
609          * <p>
610          * Note: The entire URI value is limited to 256 characters. This check is
611          * enforced when registering the PhoneAccount via
612          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
613          * {@link IllegalArgumentException} to be thrown if URI is over 256.
614          *
615          * @param value The address of the phone account.
616          * @return The builder.
617          */
setAddress(Uri value)618         public Builder setAddress(Uri value) {
619             this.mAddress = value;
620             return this;
621         }
622 
623         /**
624          * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
625          *
626          * @param value The subscription address.
627          * @return The builder.
628          */
setSubscriptionAddress(Uri value)629         public Builder setSubscriptionAddress(Uri value) {
630             this.mSubscriptionAddress = value;
631             return this;
632         }
633 
634         /**
635          * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
636          *
637          * @param value The capabilities to set.
638          * @return The builder.
639          */
setCapabilities(int value)640         public Builder setCapabilities(int value) {
641             this.mCapabilities = value;
642             return this;
643         }
644 
645         /**
646          * Sets the icon. See {@link PhoneAccount#getIcon}.
647          * <p>
648          * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory.
649          * This check is enforced when registering the PhoneAccount via
650          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
651          *
652          * @param icon The icon to set.
653          */
setIcon(Icon icon)654         public Builder setIcon(Icon icon) {
655             mIcon = icon;
656             return this;
657         }
658 
659         /**
660          * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
661          *
662          * @param value The highlight color.
663          * @return The builder.
664          */
setHighlightColor(int value)665         public Builder setHighlightColor(int value) {
666             this.mHighlightColor = value;
667             return this;
668         }
669 
670         /**
671          * Sets the short description. See {@link PhoneAccount#getShortDescription}.
672          * <p>
673          * Note: Each CharSequence or String field is limited to 256 characters. This check is
674          * enforced when registering the PhoneAccount via
675          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
676          * {@link IllegalArgumentException} to be thrown if the character field limit is over 256.
677          *
678          * @param value The short description.
679          * @return The builder.
680          */
setShortDescription(CharSequence value)681         public Builder setShortDescription(CharSequence value) {
682             this.mShortDescription = value;
683             return this;
684         }
685 
686         /**
687          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
688          *
689          * <p>
690          * Each URI scheme is limited to 256 characters.  Adding a scheme over 256 characters will
691          * cause an {@link IllegalArgumentException} to be thrown when the account is registered.
692          *
693          * @param uriScheme The URI scheme.
694          * @return The builder.
695          */
addSupportedUriScheme(String uriScheme)696         public Builder addSupportedUriScheme(String uriScheme) {
697             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
698                 this.mSupportedUriSchemes.add(uriScheme);
699             }
700             return this;
701         }
702 
703         /**
704          * Specifies the URI schemes supported by the {@link PhoneAccount}.
705          *
706          * <p>
707          * A max of 10 URI schemes can be added per account.  Additionally, each URI scheme is
708          * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any
709          * scheme will cause an {@link IllegalArgumentException} to be thrown when the account
710          * is registered.
711          *
712          * @param uriSchemes The URI schemes.
713          * @return The builder.
714          */
setSupportedUriSchemes(List<String> uriSchemes)715         public Builder setSupportedUriSchemes(List<String> uriSchemes) {
716             mSupportedUriSchemes.clear();
717 
718             if (uriSchemes != null && !uriSchemes.isEmpty()) {
719                 for (String uriScheme : uriSchemes) {
720                     addSupportedUriScheme(uriScheme);
721                 }
722             }
723             return this;
724         }
725 
726         /**
727          * Specifies the extras associated with the {@link PhoneAccount}.
728          * <p>
729          * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer},
730          * and {@link Boolean}.  Extras which are not of these types are ignored.
731          * <p>
732          * Note: Each Bundle (Key, Value) String field is limited to 256 characters. Additionally,
733          * the bundle is limited to 100 (Key, Value) pairs total.  This check is
734          * enforced when registering the PhoneAccount via
735          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
736          * {@link IllegalArgumentException} to be thrown if the character field limit is over 256
737          * or more than 100 (Key, Value) pairs are in the Bundle.
738          *
739          * @param extras
740          * @return
741          */
setExtras(Bundle extras)742         public Builder setExtras(Bundle extras) {
743             mExtras = extras;
744             return this;
745         }
746 
747         /**
748          * Sets the enabled state of the phone account.
749          *
750          * @param isEnabled The enabled state.
751          * @return The builder.
752          * @hide
753          */
setIsEnabled(boolean isEnabled)754         public Builder setIsEnabled(boolean isEnabled) {
755             mIsEnabled = isEnabled;
756             return this;
757         }
758 
759         /**
760          * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is
761          * registered to Telecom, it will replace another {@link PhoneAccount} that is already
762          * registered in Telecom and take on the current user defaults and enabled status. There can
763          * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a
764          * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only
765          * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced.
766          * <p>
767          * Note: This is an API specific to the Telephony stack; the group Id will be ignored for
768          * callers not holding the correct permission.
769          * <p>
770          * Additionally, each CharSequence or String field is limited to 256 characters.
771          * This check is enforced when registering the PhoneAccount via
772          * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
773          * {@link IllegalArgumentException} to be thrown if the character field limit is over 256.
774          *
775          * @param groupId The group Id of the {@link PhoneAccount} that will replace any other
776          * registered {@link PhoneAccount} in Telecom with the same Group Id.
777          * @return The builder
778          * @hide
779          */
780         @SystemApi
781         @RequiresPermission(MODIFY_PHONE_STATE)
setGroupId(@onNull String groupId)782         public @NonNull Builder setGroupId(@NonNull String groupId) {
783             if (groupId != null) {
784                 mGroupId = groupId;
785             } else {
786                 mGroupId = "";
787             }
788             return this;
789         }
790 
791         /**
792          * Sets the audio routes supported by this {@link PhoneAccount}.
793          *
794          * @param routes bit mask of available routes.
795          * @return The builder.
796          * @hide
797          */
setSupportedAudioRoutes(int routes)798         public Builder setSupportedAudioRoutes(int routes) {
799             mSupportedAudioRoutes = routes;
800             return this;
801         }
802 
803         /**
804          * Restricts the ability of this {@link PhoneAccount} to ONLY support simultaneous calling
805          * with the other {@link PhoneAccountHandle}s in this Set.
806          * <p>
807          * If two or more {@link PhoneAccount}s support calling simultaneously, it means that
808          * Telecom allows the user to place additional outgoing calls and receive additional
809          * incoming calls using other {@link PhoneAccount}s while this PhoneAccount also has one or
810          * more active calls.
811          * <p>
812          * If this setter method is never called or cleared using
813          * {@link #clearSimultaneousCallingRestriction()}, there is no restriction and all
814          * {@link PhoneAccount}s registered to Telecom by this package support simultaneous calling.
815          * If this setter is called and set as an empty Set, then this {@link PhoneAccount} does
816          * not support simultaneous calling with any other {@link PhoneAccount}s registered by the
817          * same application.
818          * <p>
819          * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that
820          * were registered by the same application. Simultaneous calling across applications is
821          * always possible as long as the {@link Connection} supports hold. If a
822          * {@link PhoneAccountHandle} is included here and the package name doesn't match this
823          * application's package name, {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
824          * will throw a {@link SecurityException}.
825          *
826          * @param handles The other {@link PhoneAccountHandle}s that support calling simultaneously
827          * with this one. Use {@link #clearSimultaneousCallingRestriction()} to remove the
828          * restriction and allow simultaneous calling to be supported across all
829          * {@link PhoneAccount}s registered by this package.
830          * @return The Builder used to set up the new PhoneAccount.
831          */
832         @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
setSimultaneousCallingRestriction( @onNull Set<PhoneAccountHandle> handles)833         public @NonNull Builder setSimultaneousCallingRestriction(
834                 @NonNull Set<PhoneAccountHandle> handles) {
835             if (handles == null) {
836                 throw new IllegalArgumentException("the Set of PhoneAccountHandles must not be "
837                         + "null");
838             }
839             mSimultaneousCallingRestriction = handles;
840             return this;
841         }
842 
843         /**
844          * Clears a previously set simultaneous calling restriction set when
845          * {@link PhoneAccount.Builder#Builder(PhoneAccount)} is used to create a new PhoneAccount
846          * from an existing one.
847          *
848          * @return The Builder used to set up the new PhoneAccount.
849          * @see #setSimultaneousCallingRestriction(Set)
850          */
851         @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
clearSimultaneousCallingRestriction()852         public @NonNull Builder clearSimultaneousCallingRestriction() {
853             mSimultaneousCallingRestriction = null;
854             return this;
855         }
856 
857         /**
858          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
859          *
860          * @return The {@link PhoneAccount}.
861          */
build()862         public PhoneAccount build() {
863             // If no supported URI schemes were defined, assume "tel" is supported.
864             if (mSupportedUriSchemes.isEmpty()) {
865                 addSupportedUriScheme(SCHEME_TEL);
866             }
867 
868             return new PhoneAccount(
869                     mAccountHandle,
870                     mAddress,
871                     mSubscriptionAddress,
872                     mCapabilities,
873                     mIcon,
874                     mHighlightColor,
875                     mLabel,
876                     mShortDescription,
877                     mSupportedUriSchemes,
878                     mExtras,
879                     mSupportedAudioRoutes,
880                     mIsEnabled,
881                     mGroupId,
882                     mSimultaneousCallingRestriction);
883         }
884     }
885 
PhoneAccount( PhoneAccountHandle account, Uri address, Uri subscriptionAddress, int capabilities, Icon icon, int highlightColor, CharSequence label, CharSequence shortDescription, List<String> supportedUriSchemes, Bundle extras, int supportedAudioRoutes, boolean isEnabled, String groupId, Set<PhoneAccountHandle> simultaneousCallingRestriction)886     private PhoneAccount(
887             PhoneAccountHandle account,
888             Uri address,
889             Uri subscriptionAddress,
890             int capabilities,
891             Icon icon,
892             int highlightColor,
893             CharSequence label,
894             CharSequence shortDescription,
895             List<String> supportedUriSchemes,
896             Bundle extras,
897             int supportedAudioRoutes,
898             boolean isEnabled,
899             String groupId,
900             Set<PhoneAccountHandle> simultaneousCallingRestriction) {
901         mAccountHandle = account;
902         mAddress = address;
903         mSubscriptionAddress = subscriptionAddress;
904         mCapabilities = capabilities;
905         mIcon = icon;
906         mHighlightColor = highlightColor;
907         mLabel = label;
908         mShortDescription = shortDescription;
909         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
910         mExtras = extras;
911         mSupportedAudioRoutes = supportedAudioRoutes;
912         mIsEnabled = isEnabled;
913         mGroupId = groupId;
914         mSimultaneousCallingRestriction = simultaneousCallingRestriction;
915     }
916 
builder( PhoneAccountHandle accountHandle, CharSequence label)917     public static Builder builder(
918             PhoneAccountHandle accountHandle,
919             CharSequence label) {
920         return new Builder(accountHandle, label);
921     }
922 
923     /**
924      * Returns a builder initialized with the current {@link PhoneAccount} instance.
925      *
926      * @return The builder.
927      */
toBuilder()928     public Builder toBuilder() { return new Builder(this); }
929 
930     /**
931      * The unique identifier of this {@code PhoneAccount}.
932      *
933      * @return A {@code PhoneAccountHandle}.
934      */
getAccountHandle()935     public PhoneAccountHandle getAccountHandle() {
936         return mAccountHandle;
937     }
938 
939     /**
940      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
941      * represents the destination from which outgoing calls using this {@code PhoneAccount}
942      * will appear to come, if applicable, and the destination to which incoming calls using this
943      * {@code PhoneAccount} may be addressed.
944      *
945      * @return A address expressed as a {@code Uri}, for example, a phone number.
946      */
getAddress()947     public Uri getAddress() {
948         return mAddress;
949     }
950 
951     /**
952      * The raw callback number used for this {@code PhoneAccount}, as distinct from
953      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
954      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
955      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
956      * has been used to alter the callback number.
957      * <p>
958      *
959      * @return The subscription number, suitable for display to the user.
960      */
getSubscriptionAddress()961     public Uri getSubscriptionAddress() {
962         return mSubscriptionAddress;
963     }
964 
965     /**
966      * The capabilities of this {@code PhoneAccount}.
967      *
968      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
969      */
getCapabilities()970     public int getCapabilities() {
971         return mCapabilities;
972     }
973 
974     /**
975      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
976      * bit mask.
977      *
978      * @param capability The capabilities to check.
979      * @return {@code true} if the phone account has the capability.
980      */
hasCapabilities(int capability)981     public boolean hasCapabilities(int capability) {
982         return (mCapabilities & capability) == capability;
983     }
984 
985     /**
986      * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask.
987      *
988      * @param route The routes to check.
989      * @return {@code true} if the phone account has the routes.
990      * @hide
991      */
hasAudioRoutes(int routes)992     public boolean hasAudioRoutes(int routes) {
993         return (mSupportedAudioRoutes & routes) == routes;
994     }
995 
996     /**
997      * A short label describing a {@code PhoneAccount}.
998      *
999      * @return A label for this {@code PhoneAccount}.
1000      */
getLabel()1001     public CharSequence getLabel() {
1002         return mLabel;
1003     }
1004 
1005     /**
1006      * A short paragraph describing this {@code PhoneAccount}.
1007      *
1008      * @return A description for this {@code PhoneAccount}.
1009      */
getShortDescription()1010     public CharSequence getShortDescription() {
1011         return mShortDescription;
1012     }
1013 
1014     /**
1015      * The URI schemes supported by this {@code PhoneAccount}.
1016      *
1017      * @return The URI schemes.
1018      */
getSupportedUriSchemes()1019     public List<String> getSupportedUriSchemes() {
1020         return mSupportedUriSchemes;
1021     }
1022 
1023     /**
1024      * The extras associated with this {@code PhoneAccount}.
1025      * <p>
1026      * A {@link ConnectionService} may provide implementation specific information about the
1027      * {@link PhoneAccount} via the extras.
1028      *
1029      * @return The extras.
1030      */
getExtras()1031     public Bundle getExtras() {
1032         return mExtras;
1033     }
1034 
1035     /**
1036      * The audio routes supported by this {@code PhoneAccount}.
1037      *
1038      * @hide
1039      */
getSupportedAudioRoutes()1040     public int getSupportedAudioRoutes() {
1041         return mSupportedAudioRoutes;
1042     }
1043 
1044     /**
1045      * The icon to represent this {@code PhoneAccount}.
1046      *
1047      * @return The icon.
1048      */
getIcon()1049     public Icon getIcon() {
1050         return mIcon;
1051     }
1052 
1053     /**
1054      * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
1055      * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
1056      *
1057      * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
1058      */
isEnabled()1059     public boolean isEnabled() {
1060         return mIsEnabled;
1061     }
1062 
1063     /**
1064      * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an
1065      * empty {@link String} if the {@link PhoneAccount} is not in a group. If this
1066      * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered
1067      * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced,
1068      * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}.
1069      * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced.
1070      *
1071      * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group.
1072      * @hide
1073      */
getGroupId()1074     public String getGroupId() {
1075         return mGroupId;
1076     }
1077 
1078     /**
1079      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
1080      * scheme.
1081      *
1082      * @param uriScheme The URI scheme to check.
1083      * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
1084      * specified URI scheme.
1085      */
supportsUriScheme(String uriScheme)1086     public boolean supportsUriScheme(String uriScheme) {
1087         if (mSupportedUriSchemes == null || uriScheme == null) {
1088             return false;
1089         }
1090 
1091         for (String scheme : mSupportedUriSchemes) {
1092             if (scheme != null && scheme.equals(uriScheme)) {
1093                 return true;
1094             }
1095         }
1096         return false;
1097     }
1098 
1099     /**
1100      * A highlight color to use in displaying information about this {@code PhoneAccount}.
1101      *
1102      * @return A hexadecimal color value.
1103      */
getHighlightColor()1104     public int getHighlightColor() {
1105         return mHighlightColor;
1106     }
1107 
1108     /**
1109      * Sets the enabled state of the phone account.
1110      * @hide
1111      */
setIsEnabled(boolean isEnabled)1112     public void setIsEnabled(boolean isEnabled) {
1113         mIsEnabled = isEnabled;
1114     }
1115 
1116     /**
1117      * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise.
1118      * @hide
1119      */
isSelfManaged()1120     public boolean isSelfManaged() {
1121         return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED;
1122     }
1123 
1124     /**
1125      * If a restriction is set (see {@link #hasSimultaneousCallingRestriction()}), this method
1126      * returns the Set of {@link PhoneAccountHandle}s that are allowed to support calls
1127      * simultaneously with this {@link PhoneAccount}.
1128      * <p>
1129      * If this {@link PhoneAccount} is busy with one or more ongoing calls, a restriction is set on
1130      * this PhoneAccount (see {@link #hasSimultaneousCallingRestriction()} to check),  and a new
1131      * incoming or outgoing call is received or placed on a PhoneAccount that is not in this Set,
1132      * Telecom will reject or cancel the pending call in favor of keeping the ongoing call alive.
1133      * <p>
1134      * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that
1135      * were registered by the same application. Simultaneous calling across applications is
1136      * always possible as long as the {@link Connection} supports hold.
1137      *
1138      * @return the Set of {@link PhoneAccountHandle}s that this {@link PhoneAccount} supports
1139      * simultaneous calls with.
1140      * @throws IllegalStateException If there is no restriction set on this {@link PhoneAccount}
1141      * and this method is called. Whether or not there is a restriction can be checked using
1142      * {@link #hasSimultaneousCallingRestriction()}.
1143      */
1144     @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
getSimultaneousCallingRestriction()1145     public @NonNull Set<PhoneAccountHandle> getSimultaneousCallingRestriction() {
1146         if (mSimultaneousCallingRestriction == null) {
1147             throw new IllegalStateException("This method can not be called if there is no "
1148                     + "simultaneous calling restriction. See #hasSimultaneousCallingRestriction");
1149         }
1150         return mSimultaneousCallingRestriction;
1151     }
1152 
1153     /**
1154      * Whether or not this {@link PhoneAccount} contains a simultaneous calling restriction on it.
1155      *
1156      * @return {@code true} if this PhoneAccount contains a simultaneous calling restriction,
1157      * {@code false} if it does not. Use {@link #getSimultaneousCallingRestriction()} to query which
1158      * other {@link PhoneAccount}s support simultaneous calling with this one.
1159      * @see #getSimultaneousCallingRestriction() for more information on how the sinultaneous
1160      * calling restriction works.
1161      */
1162     @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS)
hasSimultaneousCallingRestriction()1163     public boolean hasSimultaneousCallingRestriction() {
1164         return mSimultaneousCallingRestriction != null;
1165     }
1166 
1167     //
1168     // Parcelable implementation
1169     //
1170 
1171     @Override
describeContents()1172     public int describeContents() {
1173         return 0;
1174     }
1175 
1176     @Override
writeToParcel(Parcel out, int flags)1177     public void writeToParcel(Parcel out, int flags) {
1178         if (mAccountHandle == null) {
1179             out.writeInt(0);
1180         } else {
1181             out.writeInt(1);
1182             mAccountHandle.writeToParcel(out, flags);
1183         }
1184         if (mAddress == null) {
1185             out.writeInt(0);
1186         } else {
1187             out.writeInt(1);
1188             mAddress.writeToParcel(out, flags);
1189         }
1190         if (mSubscriptionAddress == null) {
1191             out.writeInt(0);
1192         } else {
1193             out.writeInt(1);
1194             mSubscriptionAddress.writeToParcel(out, flags);
1195         }
1196         out.writeInt(mCapabilities);
1197         out.writeInt(mHighlightColor);
1198         out.writeCharSequence(mLabel);
1199         out.writeCharSequence(mShortDescription);
1200         out.writeStringList(mSupportedUriSchemes);
1201 
1202         if (mIcon == null) {
1203             out.writeInt(0);
1204         } else {
1205             out.writeInt(1);
1206             mIcon.writeToParcel(out, flags);
1207         }
1208         out.writeByte((byte) (mIsEnabled ? 1 : 0));
1209         out.writeBundle(mExtras);
1210         out.writeString(mGroupId);
1211         out.writeInt(mSupportedAudioRoutes);
1212         if (mSimultaneousCallingRestriction == null) {
1213             out.writeBoolean(false);
1214         } else {
1215             out.writeBoolean(true);
1216             out.writeTypedList(mSimultaneousCallingRestriction.stream().toList());
1217         }
1218     }
1219 
1220     public static final @android.annotation.NonNull Creator<PhoneAccount> CREATOR
1221             = new Creator<PhoneAccount>() {
1222         @Override
1223         public PhoneAccount createFromParcel(Parcel in) {
1224             return new PhoneAccount(in);
1225         }
1226 
1227         @Override
1228         public PhoneAccount[] newArray(int size) {
1229             return new PhoneAccount[size];
1230         }
1231     };
1232 
PhoneAccount(Parcel in)1233     private PhoneAccount(Parcel in) {
1234         if (in.readInt() > 0) {
1235             mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
1236         } else {
1237             mAccountHandle = null;
1238         }
1239         if (in.readInt() > 0) {
1240             mAddress = Uri.CREATOR.createFromParcel(in);
1241         } else {
1242             mAddress = null;
1243         }
1244         if (in.readInt() > 0) {
1245             mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
1246         } else {
1247             mSubscriptionAddress = null;
1248         }
1249         mCapabilities = in.readInt();
1250         mHighlightColor = in.readInt();
1251         mLabel = in.readCharSequence();
1252         mShortDescription = in.readCharSequence();
1253         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
1254         if (in.readInt() > 0) {
1255             mIcon = Icon.CREATOR.createFromParcel(in);
1256         } else {
1257             mIcon = null;
1258         }
1259         mIsEnabled = in.readByte() == 1;
1260         mExtras = in.readBundle();
1261         mGroupId = in.readString();
1262         mSupportedAudioRoutes = in.readInt();
1263         if (in.readBoolean()) {
1264             List<PhoneAccountHandle> list = new ArrayList<>();
1265             in.readTypedList(list, PhoneAccountHandle.CREATOR);
1266             mSimultaneousCallingRestriction = new ArraySet<>(list);
1267         } else {
1268             mSimultaneousCallingRestriction = null;
1269         }
1270     }
1271 
1272     @Override
toString()1273     public String toString() {
1274         StringBuilder sb = new StringBuilder().append("[[")
1275                 .append(mIsEnabled ? 'X' : ' ')
1276                 .append("] PhoneAccount: ")
1277                 .append(mAccountHandle)
1278                 .append(" Capabilities: ")
1279                 .append(capabilitiesToString())
1280                 .append(" Audio Routes: ")
1281                 .append(audioRoutesToString())
1282                 .append(" Schemes: ");
1283         for (String scheme : mSupportedUriSchemes) {
1284             sb.append(scheme)
1285                     .append(" ");
1286         }
1287         sb.append(" Extras: ");
1288         sb.append(mExtras);
1289         sb.append(" GroupId: ");
1290         sb.append(Log.pii(mGroupId));
1291         sb.append(" SC Restrictions: ");
1292         if (hasSimultaneousCallingRestriction()) {
1293             sb.append("[ ");
1294             for (PhoneAccountHandle handle : mSimultaneousCallingRestriction) {
1295                 sb.append(handle);
1296                 sb.append(" ");
1297             }
1298             sb.append("]");
1299         } else {
1300             sb.append("[NONE]");
1301         }
1302         sb.append("]");
1303         return sb.toString();
1304     }
1305 
1306     /**
1307      * Generates a string representation of a capabilities bitmask.
1308      *
1309      * @return String representation of the capabilities bitmask.
1310      * @hide
1311      */
capabilitiesToString()1312     public String capabilitiesToString() {
1313         StringBuilder sb = new StringBuilder();
1314         if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
1315             sb.append("SelfManaged ");
1316         }
1317         if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
1318             sb.append("SuppVideo ");
1319         }
1320         if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
1321             sb.append("Video ");
1322         }
1323         if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
1324             sb.append("Presence ");
1325         }
1326         if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) {
1327             sb.append("CallProvider ");
1328         }
1329         if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) {
1330             sb.append("CallSubject ");
1331         }
1332         if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) {
1333             sb.append("ConnectionMgr ");
1334         }
1335         if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) {
1336             sb.append("EmergOnly ");
1337         }
1338         if (hasCapabilities(CAPABILITY_MULTI_USER)) {
1339             sb.append("MultiUser ");
1340         }
1341         if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
1342             sb.append("PlaceEmerg ");
1343         }
1344         if (hasCapabilities(CAPABILITY_EMERGENCY_PREFERRED)) {
1345             sb.append("EmerPrefer ");
1346         }
1347         if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
1348             sb.append("EmergVideo ");
1349         }
1350         if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
1351             sb.append("SimSub ");
1352         }
1353         if (hasCapabilities(CAPABILITY_RTT)) {
1354             sb.append("Rtt ");
1355         }
1356         if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) {
1357             sb.append("AdhocConf ");
1358         }
1359         if (hasCapabilities(CAPABILITY_CALL_COMPOSER)) {
1360             sb.append("CallComposer ");
1361         }
1362         if (hasCapabilities(CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS)) {
1363             sb.append("SuppVoice ");
1364         }
1365         if (hasCapabilities(CAPABILITY_VOICE_CALLING_AVAILABLE)) {
1366             sb.append("Voice ");
1367         }
1368         if (hasCapabilities(CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS)) {
1369             sb.append("TransactOps ");
1370         }
1371         if (hasCapabilities(CAPABILITY_SUPPORTS_CALL_STREAMING)) {
1372             sb.append("Stream ");
1373         }
1374         return sb.toString();
1375     }
1376 
audioRoutesToString()1377     private String audioRoutesToString() {
1378         StringBuilder sb = new StringBuilder();
1379 
1380         if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) {
1381             sb.append("B");
1382         }
1383         if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) {
1384             sb.append("E");
1385         }
1386         if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) {
1387             sb.append("S");
1388         }
1389         if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) {
1390             sb.append("W");
1391         }
1392 
1393         return sb.toString();
1394     }
1395 
1396     /**
1397      * Determines if two {@link Bundle}s are equal.
1398      * @param extras First {@link Bundle} to check.
1399      * @param newExtras {@link Bundle} to compare against.
1400      * @return {@code true} if the {@link Bundle}s are equal, {@code false} otherwise.
1401      */
areBundlesEqual(Bundle extras, Bundle newExtras)1402     private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
1403         if (extras == null || newExtras == null) {
1404             return extras == newExtras;
1405         }
1406 
1407         if (extras.size() != newExtras.size()) {
1408             return false;
1409         }
1410 
1411         for(String key : extras.keySet()) {
1412             if (key != null) {
1413                 final Object value = extras.get(key);
1414                 final Object newValue = newExtras.get(key);
1415                 if (!Objects.equals(value, newValue)) {
1416                     return false;
1417                 }
1418             }
1419         }
1420         return true;
1421     }
1422 }
1423