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