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