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 android.annotation.SystemApi;
20 import android.graphics.drawable.Icon;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.text.TextUtils;
26 
27 import java.lang.String;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31 
32 /**
33  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
34  * want those calls to be integrated into the dialer and in-call UI should build an instance of
35  * this class and register it with the system using {@link TelecomManager}.
36  * <p>
37  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
38  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
39  * should supply a valid {@link PhoneAccountHandle} that references the connection service
40  * implementation Telecom will use to interact with the app.
41  */
42 public final class PhoneAccount implements Parcelable {
43 
44     /**
45      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
46      * maximum permitted length of a call subject specified via the
47      * {@link TelecomManager#EXTRA_CALL_SUBJECT} extra on an
48      * {@link android.content.Intent#ACTION_CALL} intent.  Ultimately a {@link ConnectionService} is
49      * responsible for enforcing the maximum call subject length when sending the message, however
50      * this extra is provided so that the user interface can proactively limit the length of the
51      * call subject as the user types it.
52      */
53     public static final String EXTRA_CALL_SUBJECT_MAX_LENGTH =
54             "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
55 
56     /**
57      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
58      * character encoding to be used when determining the length of messages.
59      * The user interface can use this when determining the number of characters the user may type
60      * in a call subject.  If empty-string, the call subject message size limit will be enforced on
61      * a 1:1 basis.  That is, each character will count towards the messages size limit as a single
62      * character.  If a character encoding is specified, the message size limit will be based on the
63      * number of bytes in the message per the specified encoding.  See
64      * {@link #EXTRA_CALL_SUBJECT_MAX_LENGTH} for more information on the call subject maximum
65      * length.
66      */
67     public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING =
68             "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
69 
70     /**
71      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
72      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
73      * will be allowed to manage phone calls including using its own proprietary phone-call
74      * implementation (like VoIP calling) to make calls instead of the telephony stack.
75      * <p>
76      * When a user opts to place a call using the SIM-based telephony stack, the
77      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
78      * if the user has explicitly selected it to be used as the default connection manager.
79      * <p>
80      * See {@link #getCapabilities}
81      */
82     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
83 
84     /**
85      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
86      * traditional SIM-based telephony calls. This account will be treated as a distinct method
87      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
88      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
89      * or place calls from the built-in telephony stack.
90      * <p>
91      * See {@link #getCapabilities}
92      * <p>
93      */
94     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
95 
96     /**
97      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
98      * subscription.
99      * <p>
100      * Only the Android framework can register a {@code PhoneAccount} having this capability.
101      * <p>
102      * See {@link #getCapabilities}
103      */
104     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
105 
106     /**
107      * Flag indicating that this {@code PhoneAccount} is currently able to place video calls.
108      * <p>
109      * See also {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING} which indicates whether the
110      * {@code PhoneAccount} supports placing video calls.
111      * <p>
112      * See {@link #getCapabilities}
113      */
114     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
115 
116     /**
117      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
118      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
119      * <p>
120      * See {@link #getCapabilities}
121      */
122     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
123 
124     /**
125      * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
126      * should only be used by system apps (and will be ignored for all other apps trying to use it).
127      * <p>
128      * See {@link #getCapabilities}
129      * @hide
130      */
131     @SystemApi
132     public static final int CAPABILITY_MULTI_USER = 0x20;
133 
134     /**
135      * Flag indicating that this {@code PhoneAccount} supports a subject for Calls.  This means a
136      * caller is able to specify a short subject line for an outgoing call.  A capable receiving
137      * device displays the call subject on the incoming call screen.
138      * <p>
139      * See {@link #getCapabilities}
140      */
141     public static final int CAPABILITY_CALL_SUBJECT = 0x40;
142 
143     /**
144      * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
145      * <p>
146      * See {@link #getCapabilities}
147      * @hide
148      */
149     public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
150 
151     /**
152      * Flag indicating that for this {@code PhoneAccount}, the ability to make a video call to a
153      * number relies on presence.  Should only be set if the {@code PhoneAccount} also has
154      * {@link #CAPABILITY_VIDEO_CALLING}.
155      * <p>
156      * When set, the {@link ConnectionService} is responsible for toggling the
157      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the
158      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether
159      * a contact's phone number supports video calling.
160      * <p>
161      * See {@link #getCapabilities}
162      */
163     public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100;
164 
165     /**
166      * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed.
167      * <p>
168      * When set, Telecom will allow emergency video calls to be placed.  When not set, Telecom will
169      * convert all outgoing video calls to emergency numbers to audio-only.
170      * @hide
171      */
172     public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
173 
174     /**
175      * Flag indicating that this {@link PhoneAccount} supports video calling.
176      * This is not an indication that the {@link PhoneAccount} is currently able to make a video
177      * call, but rather that it has the ability to make video calls (but not necessarily at this
178      * time).
179      * <p>
180      * Whether a {@link PhoneAccount} can make a video call is ultimately controlled by
181      * {@link #CAPABILITY_VIDEO_CALLING}, which indicates whether the {@link PhoneAccount} is
182      * currently capable of making a video call.  Consider a case where, for example, a
183      * {@link PhoneAccount} supports making video calls (e.g.
184      * {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}), but a current lack of network connectivity
185      * prevents video calls from being made (e.g. {@link #CAPABILITY_VIDEO_CALLING}).
186      * <p>
187      * See {@link #getCapabilities}
188      */
189     public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400;
190 
191     /**
192      * Flag indicating that this {@link PhoneAccount} is responsible for managing its own
193      * {@link Connection}s.  This type of {@link PhoneAccount} is ideal for use with standalone
194      * calling apps which do not wish to use the default phone app for {@link Connection} UX,
195      * but which want to leverage the call and audio routing capabilities of the Telecom framework.
196      * <p>
197      * When set, {@link Connection}s created by the self-managed {@link ConnectionService} will not
198      * be surfaced to implementations of the {@link InCallService} API.  Thus it is the
199      * responsibility of a self-managed {@link ConnectionService} to provide a user interface for
200      * its {@link Connection}s.
201      * <p>
202      * Self-managed {@link Connection}s will, however, be displayed on connected Bluetooth devices.
203      */
204     public static final int CAPABILITY_SELF_MANAGED = 0x800;
205 
206     /**
207      * Flag indicating that this {@link PhoneAccount} is capable of making a call with an
208      * RTT (Real-time text) session.
209      * When set, Telecom will attempt to open an RTT session on outgoing calls that specify
210      * that they should be placed with an RTT session , and the in-call app will be displayed
211      * with text entry fields for RTT. Likewise, the in-call app can request that an RTT
212      * session be opened during a call if this bit is set.
213      */
214     public static final int CAPABILITY_RTT = 0x1000;
215 
216     /* NEXT CAPABILITY: 0x2000 */
217 
218     /**
219      * URI scheme for telephone number URIs.
220      */
221     public static final String SCHEME_TEL = "tel";
222 
223     /**
224      * URI scheme for voicemail URIs.
225      */
226     public static final String SCHEME_VOICEMAIL = "voicemail";
227 
228     /**
229      * URI scheme for SIP URIs.
230      */
231     public static final String SCHEME_SIP = "sip";
232 
233     /**
234      * Indicating no icon tint is set.
235      * @hide
236      */
237     public static final int NO_ICON_TINT = 0;
238 
239     /**
240      * Indicating no hightlight color is set.
241      */
242     public static final int NO_HIGHLIGHT_COLOR = 0;
243 
244     /**
245      * Indicating no resource ID is set.
246      */
247     public static final int NO_RESOURCE_ID = -1;
248 
249     private final PhoneAccountHandle mAccountHandle;
250     private final Uri mAddress;
251     private final Uri mSubscriptionAddress;
252     private final int mCapabilities;
253     private final int mHighlightColor;
254     private final CharSequence mLabel;
255     private final CharSequence mShortDescription;
256     private final List<String> mSupportedUriSchemes;
257     private final int mSupportedAudioRoutes;
258     private final Icon mIcon;
259     private final Bundle mExtras;
260     private boolean mIsEnabled;
261     private String mGroupId;
262 
263     /**
264      * Helper class for creating a {@link PhoneAccount}.
265      */
266     public static class Builder {
267 
268         private PhoneAccountHandle mAccountHandle;
269         private Uri mAddress;
270         private Uri mSubscriptionAddress;
271         private int mCapabilities;
272         private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
273         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
274         private CharSequence mLabel;
275         private CharSequence mShortDescription;
276         private List<String> mSupportedUriSchemes = new ArrayList<String>();
277         private Icon mIcon;
278         private Bundle mExtras;
279         private boolean mIsEnabled = false;
280         private String mGroupId = "";
281 
282         /**
283          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
284          */
Builder(PhoneAccountHandle accountHandle, CharSequence label)285         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
286             this.mAccountHandle = accountHandle;
287             this.mLabel = label;
288         }
289 
290         /**
291          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
292          * {@link PhoneAccount}.
293          *
294          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
295          */
Builder(PhoneAccount phoneAccount)296         public Builder(PhoneAccount phoneAccount) {
297             mAccountHandle = phoneAccount.getAccountHandle();
298             mAddress = phoneAccount.getAddress();
299             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
300             mCapabilities = phoneAccount.getCapabilities();
301             mHighlightColor = phoneAccount.getHighlightColor();
302             mLabel = phoneAccount.getLabel();
303             mShortDescription = phoneAccount.getShortDescription();
304             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
305             mIcon = phoneAccount.getIcon();
306             mIsEnabled = phoneAccount.isEnabled();
307             mExtras = phoneAccount.getExtras();
308             mGroupId = phoneAccount.getGroupId();
309             mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
310         }
311 
312         /**
313          * Sets the label. See {@link PhoneAccount#getLabel()}.
314          *
315          * @param label The label of the phone account.
316          * @return The builder.
317          * @hide
318          */
setLabel(CharSequence label)319         public Builder setLabel(CharSequence label) {
320             this.mLabel = label;
321             return this;
322         }
323 
324         /**
325          * Sets the address. See {@link PhoneAccount#getAddress}.
326          *
327          * @param value The address of the phone account.
328          * @return The builder.
329          */
setAddress(Uri value)330         public Builder setAddress(Uri value) {
331             this.mAddress = value;
332             return this;
333         }
334 
335         /**
336          * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
337          *
338          * @param value The subscription address.
339          * @return The builder.
340          */
setSubscriptionAddress(Uri value)341         public Builder setSubscriptionAddress(Uri value) {
342             this.mSubscriptionAddress = value;
343             return this;
344         }
345 
346         /**
347          * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
348          *
349          * @param value The capabilities to set.
350          * @return The builder.
351          */
setCapabilities(int value)352         public Builder setCapabilities(int value) {
353             this.mCapabilities = value;
354             return this;
355         }
356 
357         /**
358          * Sets the icon. See {@link PhoneAccount#getIcon}.
359          *
360          * @param icon The icon to set.
361          */
setIcon(Icon icon)362         public Builder setIcon(Icon icon) {
363             mIcon = icon;
364             return this;
365         }
366 
367         /**
368          * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
369          *
370          * @param value The highlight color.
371          * @return The builder.
372          */
setHighlightColor(int value)373         public Builder setHighlightColor(int value) {
374             this.mHighlightColor = value;
375             return this;
376         }
377 
378         /**
379          * Sets the short description. See {@link PhoneAccount#getShortDescription}.
380          *
381          * @param value The short description.
382          * @return The builder.
383          */
setShortDescription(CharSequence value)384         public Builder setShortDescription(CharSequence value) {
385             this.mShortDescription = value;
386             return this;
387         }
388 
389         /**
390          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
391          *
392          * @param uriScheme The URI scheme.
393          * @return The builder.
394          */
addSupportedUriScheme(String uriScheme)395         public Builder addSupportedUriScheme(String uriScheme) {
396             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
397                 this.mSupportedUriSchemes.add(uriScheme);
398             }
399             return this;
400         }
401 
402         /**
403          * Specifies the URI schemes supported by the {@link PhoneAccount}.
404          *
405          * @param uriSchemes The URI schemes.
406          * @return The builder.
407          */
setSupportedUriSchemes(List<String> uriSchemes)408         public Builder setSupportedUriSchemes(List<String> uriSchemes) {
409             mSupportedUriSchemes.clear();
410 
411             if (uriSchemes != null && !uriSchemes.isEmpty()) {
412                 for (String uriScheme : uriSchemes) {
413                     addSupportedUriScheme(uriScheme);
414                 }
415             }
416             return this;
417         }
418 
419         /**
420          * Specifies the extras associated with the {@link PhoneAccount}.
421          * <p>
422          * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer},
423          * and {@link Boolean}.  Extras which are not of these types are ignored.
424          *
425          * @param extras
426          * @return
427          */
setExtras(Bundle extras)428         public Builder setExtras(Bundle extras) {
429             mExtras = extras;
430             return this;
431         }
432 
433         /**
434          * Sets the enabled state of the phone account.
435          *
436          * @param isEnabled The enabled state.
437          * @return The builder.
438          * @hide
439          */
setIsEnabled(boolean isEnabled)440         public Builder setIsEnabled(boolean isEnabled) {
441             mIsEnabled = isEnabled;
442             return this;
443         }
444 
445         /**
446          * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is
447          * registered to Telecom, it will replace another {@link PhoneAccount} that is already
448          * registered in Telecom and take on the current user defaults and enabled status. There can
449          * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a
450          * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only
451          * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced.
452          * @param groupId The group Id of the {@link PhoneAccount} that will replace any other
453          * registered {@link PhoneAccount} in Telecom with the same Group Id.
454          * @return The builder
455          * @hide
456          */
setGroupId(String groupId)457         public Builder setGroupId(String groupId) {
458             if (groupId != null) {
459                 mGroupId = groupId;
460             } else {
461                 mGroupId = "";
462             }
463             return this;
464         }
465 
466         /**
467          * Sets the audio routes supported by this {@link PhoneAccount}.
468          *
469          * @param routes bit mask of available routes.
470          * @return The builder.
471          * @hide
472          */
setSupportedAudioRoutes(int routes)473         public Builder setSupportedAudioRoutes(int routes) {
474             mSupportedAudioRoutes = routes;
475             return this;
476         }
477 
478         /**
479          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
480          *
481          * @return The {@link PhoneAccount}.
482          */
build()483         public PhoneAccount build() {
484             // If no supported URI schemes were defined, assume "tel" is supported.
485             if (mSupportedUriSchemes.isEmpty()) {
486                 addSupportedUriScheme(SCHEME_TEL);
487             }
488 
489             return new PhoneAccount(
490                     mAccountHandle,
491                     mAddress,
492                     mSubscriptionAddress,
493                     mCapabilities,
494                     mIcon,
495                     mHighlightColor,
496                     mLabel,
497                     mShortDescription,
498                     mSupportedUriSchemes,
499                     mExtras,
500                     mSupportedAudioRoutes,
501                     mIsEnabled,
502                     mGroupId);
503         }
504     }
505 
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)506     private PhoneAccount(
507             PhoneAccountHandle account,
508             Uri address,
509             Uri subscriptionAddress,
510             int capabilities,
511             Icon icon,
512             int highlightColor,
513             CharSequence label,
514             CharSequence shortDescription,
515             List<String> supportedUriSchemes,
516             Bundle extras,
517             int supportedAudioRoutes,
518             boolean isEnabled,
519             String groupId) {
520         mAccountHandle = account;
521         mAddress = address;
522         mSubscriptionAddress = subscriptionAddress;
523         mCapabilities = capabilities;
524         mIcon = icon;
525         mHighlightColor = highlightColor;
526         mLabel = label;
527         mShortDescription = shortDescription;
528         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
529         mExtras = extras;
530         mSupportedAudioRoutes = supportedAudioRoutes;
531         mIsEnabled = isEnabled;
532         mGroupId = groupId;
533     }
534 
builder( PhoneAccountHandle accountHandle, CharSequence label)535     public static Builder builder(
536             PhoneAccountHandle accountHandle,
537             CharSequence label) {
538         return new Builder(accountHandle, label);
539     }
540 
541     /**
542      * Returns a builder initialized with the current {@link PhoneAccount} instance.
543      *
544      * @return The builder.
545      */
toBuilder()546     public Builder toBuilder() { return new Builder(this); }
547 
548     /**
549      * The unique identifier of this {@code PhoneAccount}.
550      *
551      * @return A {@code PhoneAccountHandle}.
552      */
getAccountHandle()553     public PhoneAccountHandle getAccountHandle() {
554         return mAccountHandle;
555     }
556 
557     /**
558      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
559      * represents the destination from which outgoing calls using this {@code PhoneAccount}
560      * will appear to come, if applicable, and the destination to which incoming calls using this
561      * {@code PhoneAccount} may be addressed.
562      *
563      * @return A address expressed as a {@code Uri}, for example, a phone number.
564      */
getAddress()565     public Uri getAddress() {
566         return mAddress;
567     }
568 
569     /**
570      * The raw callback number used for this {@code PhoneAccount}, as distinct from
571      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
572      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
573      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
574      * has been used to alter the callback number.
575      * <p>
576      *
577      * @return The subscription number, suitable for display to the user.
578      */
getSubscriptionAddress()579     public Uri getSubscriptionAddress() {
580         return mSubscriptionAddress;
581     }
582 
583     /**
584      * The capabilities of this {@code PhoneAccount}.
585      *
586      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
587      */
getCapabilities()588     public int getCapabilities() {
589         return mCapabilities;
590     }
591 
592     /**
593      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
594      * bit mask.
595      *
596      * @param capability The capabilities to check.
597      * @return {@code true} if the phone account has the capability.
598      */
hasCapabilities(int capability)599     public boolean hasCapabilities(int capability) {
600         return (mCapabilities & capability) == capability;
601     }
602 
603     /**
604      * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask.
605      *
606      * @param route The routes to check.
607      * @return {@code true} if the phone account has the routes.
608      * @hide
609      */
hasAudioRoutes(int routes)610     public boolean hasAudioRoutes(int routes) {
611         return (mSupportedAudioRoutes & routes) == routes;
612     }
613 
614     /**
615      * A short label describing a {@code PhoneAccount}.
616      *
617      * @return A label for this {@code PhoneAccount}.
618      */
getLabel()619     public CharSequence getLabel() {
620         return mLabel;
621     }
622 
623     /**
624      * A short paragraph describing this {@code PhoneAccount}.
625      *
626      * @return A description for this {@code PhoneAccount}.
627      */
getShortDescription()628     public CharSequence getShortDescription() {
629         return mShortDescription;
630     }
631 
632     /**
633      * The URI schemes supported by this {@code PhoneAccount}.
634      *
635      * @return The URI schemes.
636      */
getSupportedUriSchemes()637     public List<String> getSupportedUriSchemes() {
638         return mSupportedUriSchemes;
639     }
640 
641     /**
642      * The extras associated with this {@code PhoneAccount}.
643      * <p>
644      * A {@link ConnectionService} may provide implementation specific information about the
645      * {@link PhoneAccount} via the extras.
646      *
647      * @return The extras.
648      */
getExtras()649     public Bundle getExtras() {
650         return mExtras;
651     }
652 
653     /**
654      * The audio routes supported by this {@code PhoneAccount}.
655      *
656      * @hide
657      */
getSupportedAudioRoutes()658     public int getSupportedAudioRoutes() {
659         return mSupportedAudioRoutes;
660     }
661 
662     /**
663      * The icon to represent this {@code PhoneAccount}.
664      *
665      * @return The icon.
666      */
getIcon()667     public Icon getIcon() {
668         return mIcon;
669     }
670 
671     /**
672      * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
673      * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
674      *
675      * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
676      */
isEnabled()677     public boolean isEnabled() {
678         return mIsEnabled;
679     }
680 
681     /**
682      * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an
683      * empty {@link String} if the {@link PhoneAccount} is not in a group. If this
684      * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered
685      * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced,
686      * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}.
687      * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced.
688      *
689      * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group.
690      * @hide
691      */
getGroupId()692     public String getGroupId() {
693         return mGroupId;
694     }
695 
696     /**
697      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
698      * scheme.
699      *
700      * @param uriScheme The URI scheme to check.
701      * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
702      * specified URI scheme.
703      */
supportsUriScheme(String uriScheme)704     public boolean supportsUriScheme(String uriScheme) {
705         if (mSupportedUriSchemes == null || uriScheme == null) {
706             return false;
707         }
708 
709         for (String scheme : mSupportedUriSchemes) {
710             if (scheme != null && scheme.equals(uriScheme)) {
711                 return true;
712             }
713         }
714         return false;
715     }
716 
717     /**
718      * A highlight color to use in displaying information about this {@code PhoneAccount}.
719      *
720      * @return A hexadecimal color value.
721      */
getHighlightColor()722     public int getHighlightColor() {
723         return mHighlightColor;
724     }
725 
726     /**
727      * Sets the enabled state of the phone account.
728      * @hide
729      */
setIsEnabled(boolean isEnabled)730     public void setIsEnabled(boolean isEnabled) {
731         mIsEnabled = isEnabled;
732     }
733 
734     /**
735      * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise.
736      * @hide
737      */
isSelfManaged()738     public boolean isSelfManaged() {
739         return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED;
740     }
741 
742     //
743     // Parcelable implementation
744     //
745 
746     @Override
describeContents()747     public int describeContents() {
748         return 0;
749     }
750 
751     @Override
writeToParcel(Parcel out, int flags)752     public void writeToParcel(Parcel out, int flags) {
753         if (mAccountHandle == null) {
754             out.writeInt(0);
755         } else {
756             out.writeInt(1);
757             mAccountHandle.writeToParcel(out, flags);
758         }
759         if (mAddress == null) {
760             out.writeInt(0);
761         } else {
762             out.writeInt(1);
763             mAddress.writeToParcel(out, flags);
764         }
765         if (mSubscriptionAddress == null) {
766             out.writeInt(0);
767         } else {
768             out.writeInt(1);
769             mSubscriptionAddress.writeToParcel(out, flags);
770         }
771         out.writeInt(mCapabilities);
772         out.writeInt(mHighlightColor);
773         out.writeCharSequence(mLabel);
774         out.writeCharSequence(mShortDescription);
775         out.writeStringList(mSupportedUriSchemes);
776 
777         if (mIcon == null) {
778             out.writeInt(0);
779         } else {
780             out.writeInt(1);
781             mIcon.writeToParcel(out, flags);
782         }
783         out.writeByte((byte) (mIsEnabled ? 1 : 0));
784         out.writeBundle(mExtras);
785         out.writeString(mGroupId);
786         out.writeInt(mSupportedAudioRoutes);
787     }
788 
789     public static final Creator<PhoneAccount> CREATOR
790             = new Creator<PhoneAccount>() {
791         @Override
792         public PhoneAccount createFromParcel(Parcel in) {
793             return new PhoneAccount(in);
794         }
795 
796         @Override
797         public PhoneAccount[] newArray(int size) {
798             return new PhoneAccount[size];
799         }
800     };
801 
PhoneAccount(Parcel in)802     private PhoneAccount(Parcel in) {
803         if (in.readInt() > 0) {
804             mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
805         } else {
806             mAccountHandle = null;
807         }
808         if (in.readInt() > 0) {
809             mAddress = Uri.CREATOR.createFromParcel(in);
810         } else {
811             mAddress = null;
812         }
813         if (in.readInt() > 0) {
814             mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
815         } else {
816             mSubscriptionAddress = null;
817         }
818         mCapabilities = in.readInt();
819         mHighlightColor = in.readInt();
820         mLabel = in.readCharSequence();
821         mShortDescription = in.readCharSequence();
822         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
823         if (in.readInt() > 0) {
824             mIcon = Icon.CREATOR.createFromParcel(in);
825         } else {
826             mIcon = null;
827         }
828         mIsEnabled = in.readByte() == 1;
829         mExtras = in.readBundle();
830         mGroupId = in.readString();
831         mSupportedAudioRoutes = in.readInt();
832     }
833 
834     @Override
toString()835     public String toString() {
836         StringBuilder sb = new StringBuilder().append("[[")
837                 .append(mIsEnabled ? 'X' : ' ')
838                 .append("] PhoneAccount: ")
839                 .append(mAccountHandle)
840                 .append(" Capabilities: ")
841                 .append(capabilitiesToString())
842                 .append(" Audio Routes: ")
843                 .append(audioRoutesToString())
844                 .append(" Schemes: ");
845         for (String scheme : mSupportedUriSchemes) {
846             sb.append(scheme)
847                     .append(" ");
848         }
849         sb.append(" Extras: ");
850         sb.append(mExtras);
851         sb.append(" GroupId: ");
852         sb.append(Log.pii(mGroupId));
853         sb.append("]");
854         return sb.toString();
855     }
856 
857     /**
858      * Generates a string representation of a capabilities bitmask.
859      *
860      * @param capabilities The capabilities bitmask.
861      * @return String representation of the capabilities bitmask.
862      */
capabilitiesToString()863     private String capabilitiesToString() {
864         StringBuilder sb = new StringBuilder();
865         if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
866             sb.append("SelfManaged ");
867         }
868         if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
869             sb.append("SuppVideo ");
870         }
871         if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
872             sb.append("Video ");
873         }
874         if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
875             sb.append("Presence ");
876         }
877         if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) {
878             sb.append("CallProvider ");
879         }
880         if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) {
881             sb.append("CallSubject ");
882         }
883         if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) {
884             sb.append("ConnectionMgr ");
885         }
886         if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) {
887             sb.append("EmergOnly ");
888         }
889         if (hasCapabilities(CAPABILITY_MULTI_USER)) {
890             sb.append("MultiUser ");
891         }
892         if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
893             sb.append("PlaceEmerg ");
894         }
895         if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
896             sb.append("EmergVideo ");
897         }
898         if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
899             sb.append("SimSub ");
900         }
901         return sb.toString();
902     }
903 
audioRoutesToString()904     private String audioRoutesToString() {
905         StringBuilder sb = new StringBuilder();
906 
907         if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) {
908             sb.append("B");
909         }
910         if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) {
911             sb.append("E");
912         }
913         if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) {
914             sb.append("S");
915         }
916         if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) {
917             sb.append("W");
918         }
919 
920         return sb.toString();
921     }
922 }
923