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