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