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.net.Uri;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 import android.text.TextUtils;
33 
34 import java.lang.String;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.MissingResourceException;
39 
40 /**
41  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
42  * want those calls to be integrated into the dialer and in-call UI should build an instance of
43  * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}.
44  * <p>
45  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
46  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
47  * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService}
48  * implementation Telecom will use to interact with the app.
49  * @hide
50  */
51 @SystemApi
52 public class PhoneAccount implements Parcelable {
53 
54     /**
55      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
56      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
57      * will be allowed to manage phone calls including using its own proprietary phone-call
58      * implementation (like VoIP calling) to make calls instead of the telephony stack.
59      * <p>
60      * When a user opts to place a call using the SIM-based telephony stack, the
61      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
62      * if the user has explicitly selected it to be used as the default connection manager.
63      * <p>
64      * See {@link #getCapabilities}
65      */
66     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
67 
68     /**
69      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
70      * traditional SIM-based telephony calls. This account will be treated as a distinct method
71      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
72      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
73      * or place calls from the built-in telephony stack.
74      * <p>
75      * See {@link #getCapabilities}
76      * <p>
77      * {@hide}
78      */
79     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
80 
81     /**
82      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
83      * subscription.
84      * <p>
85      * Only the Android framework can register a {@code PhoneAccount} having this capability.
86      * <p>
87      * See {@link #getCapabilities}
88      */
89     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
90 
91     /**
92      * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
93      * <p>
94      * See {@link #getCapabilities}
95      * @hide
96      */
97     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
98 
99     /**
100      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
101      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
102      * <p>
103      * See {@link #getCapabilities}
104      */
105     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
106 
107     /**
108      * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
109      * should only be used by system apps (and will be ignored for all other apps trying to use it).
110      * <p>
111      * See {@link #getCapabilities}
112      * @hide
113      */
114     public static final int CAPABILITY_MULTI_USER = 0x20;
115 
116     /**
117      * URI scheme for telephone number URIs.
118      */
119     public static final String SCHEME_TEL = "tel";
120 
121     /**
122      * URI scheme for voicemail URIs.
123      */
124     public static final String SCHEME_VOICEMAIL = "voicemail";
125 
126     /**
127      * URI scheme for SIP URIs.
128      */
129     public static final String SCHEME_SIP = "sip";
130 
131     /**
132      * Indicating no icon tint is set.
133      */
134     public static final int NO_ICON_TINT = 0;
135 
136     /**
137      * Indicating no hightlight color is set.
138      */
139     public static final int NO_HIGHLIGHT_COLOR = 0;
140 
141     /**
142      * Indicating no resource ID is set.
143      */
144     public static final int NO_RESOURCE_ID = -1;
145 
146     private final PhoneAccountHandle mAccountHandle;
147     private final Uri mAddress;
148     private final Uri mSubscriptionAddress;
149     private final int mCapabilities;
150     private final int mIconResId;
151     private final String mIconPackageName;
152     private final Bitmap mIconBitmap;
153     private final int mIconTint;
154     private final int mHighlightColor;
155     private final CharSequence mLabel;
156     private final CharSequence mShortDescription;
157     private final List<String> mSupportedUriSchemes;
158 
159     /**
160      * Helper class for creating a {@link PhoneAccount}.
161      */
162     public static class Builder {
163         private PhoneAccountHandle mAccountHandle;
164         private Uri mAddress;
165         private Uri mSubscriptionAddress;
166         private int mCapabilities;
167         private int mIconResId;
168         private String mIconPackageName;
169         private Bitmap mIconBitmap;
170         private int mIconTint = NO_ICON_TINT;
171         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
172         private CharSequence mLabel;
173         private CharSequence mShortDescription;
174         private List<String> mSupportedUriSchemes = new ArrayList<String>();
175 
176         /**
177          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
178          */
Builder(PhoneAccountHandle accountHandle, CharSequence label)179         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
180             this.mAccountHandle = accountHandle;
181             this.mLabel = label;
182         }
183 
184         /**
185          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
186          * {@link PhoneAccount}.
187          *
188          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
189          */
Builder(PhoneAccount phoneAccount)190         public Builder(PhoneAccount phoneAccount) {
191             mAccountHandle = phoneAccount.getAccountHandle();
192             mAddress = phoneAccount.getAddress();
193             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
194             mCapabilities = phoneAccount.getCapabilities();
195             mIconResId = phoneAccount.getIconResId();
196             mIconPackageName = phoneAccount.getIconPackageName();
197             mIconBitmap = phoneAccount.getIconBitmap();
198             mIconTint = phoneAccount.getIconTint();
199             mHighlightColor = phoneAccount.getHighlightColor();
200             mLabel = phoneAccount.getLabel();
201             mShortDescription = phoneAccount.getShortDescription();
202             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
203         }
204 
205         /** @hide */
setAccountHandle(PhoneAccountHandle accountHandle)206         public Builder setAccountHandle(PhoneAccountHandle accountHandle) {
207             mAccountHandle = accountHandle;
208             return this;
209         }
210 
211         /**
212          * Sets the address. See {@link PhoneAccount#getAddress}.
213          *
214          * @param value The address of the phone account.
215          * @return The builder.
216          */
setAddress(Uri value)217         public Builder setAddress(Uri value) {
218             this.mAddress = value;
219             return this;
220         }
221 
222         /**
223          * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
224          *
225          * @param value The subscription address.
226          * @return The builder.
227          */
setSubscriptionAddress(Uri value)228         public Builder setSubscriptionAddress(Uri value) {
229             this.mSubscriptionAddress = value;
230             return this;
231         }
232 
233         /**
234          * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
235          *
236          * @param value The capabilities to set.
237          * @return The builder.
238          */
setCapabilities(int value)239         public Builder setCapabilities(int value) {
240             this.mCapabilities = value;
241             return this;
242         }
243 
244         /**
245          * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
246          *
247          * @param packageContext The package from which to load an icon.
248          * @param iconResId The resource in {@code iconPackageName} representing the icon.
249          * @return The builder.
250          */
setIcon(Context packageContext, int iconResId)251         public Builder setIcon(Context packageContext, int iconResId) {
252             return setIcon(packageContext.getPackageName(), iconResId);
253         }
254 
255         /**
256          * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
257          *
258          * @param iconPackageName The package from which to load an icon.
259          * @param iconResId The resource in {@code iconPackageName} representing the icon.
260          * @return The builder.
261          */
setIcon(String iconPackageName, int iconResId)262         public Builder setIcon(String iconPackageName, int iconResId) {
263             return setIcon(iconPackageName, iconResId, NO_ICON_TINT);
264         }
265 
266         /**
267          * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
268          *
269          * @param packageContext The package from which to load an icon.
270          * @param iconResId The resource in {@code iconPackageName} representing the icon.
271          * @param iconTint A color with which to tint this icon.
272          * @return The builder.
273          */
setIcon(Context packageContext, int iconResId, int iconTint)274         public Builder setIcon(Context packageContext, int iconResId, int iconTint) {
275             return setIcon(packageContext.getPackageName(), iconResId, iconTint);
276         }
277 
278         /**
279          * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
280          *
281          * @param iconPackageName The package from which to load an icon.
282          * @param iconResId The resource in {@code iconPackageName} representing the icon.
283          * @param iconTint A color with which to tint this icon.
284          * @return The builder.
285          */
setIcon(String iconPackageName, int iconResId, int iconTint)286         public Builder setIcon(String iconPackageName, int iconResId, int iconTint) {
287             this.mIconPackageName = iconPackageName;
288             this.mIconResId = iconResId;
289             this.mIconTint = iconTint;
290             return this;
291         }
292 
293         /**
294          * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
295          *
296          * @param iconBitmap The icon bitmap.
297          * @return The builder.
298          */
setIcon(Bitmap iconBitmap)299         public Builder setIcon(Bitmap iconBitmap) {
300             this.mIconBitmap = iconBitmap;
301             this.mIconPackageName = null;
302             this.mIconResId = NO_RESOURCE_ID;
303             this.mIconTint = NO_ICON_TINT;
304             return this;
305         }
306 
307         /**
308          * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
309          *
310          * @param value The highlight color.
311          * @return The builder.
312          */
setHighlightColor(int value)313         public Builder setHighlightColor(int value) {
314             this.mHighlightColor = value;
315             return this;
316         }
317 
318         /**
319          * Sets the short description. See {@link PhoneAccount#getShortDescription}.
320          *
321          * @param value The short description.
322          * @return The builder.
323          */
setShortDescription(CharSequence value)324         public Builder setShortDescription(CharSequence value) {
325             this.mShortDescription = value;
326             return this;
327         }
328 
329         /**
330          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
331          *
332          * @param uriScheme The URI scheme.
333          * @return The builder.
334          * @hide
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          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
362          *
363          * @return The {@link PhoneAccount}.
364          */
build()365         public PhoneAccount build() {
366             // If no supported URI schemes were defined, assume "tel" is supported.
367             if (mSupportedUriSchemes.isEmpty()) {
368                 addSupportedUriScheme(SCHEME_TEL);
369             }
370 
371             return new PhoneAccount(
372                     mAccountHandle,
373                     mAddress,
374                     mSubscriptionAddress,
375                     mCapabilities,
376                     mIconResId,
377                     mIconPackageName,
378                     mIconBitmap,
379                     mIconTint,
380                     mHighlightColor,
381                     mLabel,
382                     mShortDescription,
383                     mSupportedUriSchemes);
384         }
385     }
386 
PhoneAccount( PhoneAccountHandle account, Uri address, Uri subscriptionAddress, int capabilities, int iconResId, String iconPackageName, Bitmap iconBitmap, int iconTint, int highlightColor, CharSequence label, CharSequence shortDescription, List<String> supportedUriSchemes)387     private PhoneAccount(
388             PhoneAccountHandle account,
389             Uri address,
390             Uri subscriptionAddress,
391             int capabilities,
392             int iconResId,
393             String iconPackageName,
394             Bitmap iconBitmap,
395             int iconTint,
396             int highlightColor,
397             CharSequence label,
398             CharSequence shortDescription,
399             List<String> supportedUriSchemes) {
400         mAccountHandle = account;
401         mAddress = address;
402         mSubscriptionAddress = subscriptionAddress;
403         mCapabilities = capabilities;
404         mIconResId = iconResId;
405         mIconPackageName = iconPackageName;
406         mIconBitmap = iconBitmap;
407         mIconTint = iconTint;
408         mHighlightColor = highlightColor;
409         mLabel = label;
410         mShortDescription = shortDescription;
411         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
412     }
413 
builder( PhoneAccountHandle accountHandle, CharSequence label)414     public static Builder builder(
415             PhoneAccountHandle accountHandle,
416             CharSequence label) {
417         return new Builder(accountHandle, label);
418     }
419 
420     /**
421      * Returns a builder initialized with the current {@link PhoneAccount} instance.
422      *
423      * @return The builder.
424      * @hide
425      */
toBuilder()426     public Builder toBuilder() { return new Builder(this); }
427 
428     /**
429      * The unique identifier of this {@code PhoneAccount}.
430      *
431      * @return A {@code PhoneAccountHandle}.
432      */
getAccountHandle()433     public PhoneAccountHandle getAccountHandle() {
434         return mAccountHandle;
435     }
436 
437     /**
438      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
439      * represents the destination from which outgoing calls using this {@code PhoneAccount}
440      * will appear to come, if applicable, and the destination to which incoming calls using this
441      * {@code PhoneAccount} may be addressed.
442      *
443      * @return A address expressed as a {@code Uri}, for example, a phone number.
444      */
getAddress()445     public Uri getAddress() {
446         return mAddress;
447     }
448 
449     /**
450      * The raw callback number used for this {@code PhoneAccount}, as distinct from
451      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
452      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
453      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
454      * has been used to alter the callback number.
455      * <p>
456      *
457      * @return The subscription number, suitable for display to the user.
458      */
getSubscriptionAddress()459     public Uri getSubscriptionAddress() {
460         return mSubscriptionAddress;
461     }
462 
463     /**
464      * The capabilities of this {@code PhoneAccount}.
465      *
466      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
467      */
getCapabilities()468     public int getCapabilities() {
469         return mCapabilities;
470     }
471 
472     /**
473      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
474      * bit mask.
475      *
476      * @param capability The capabilities to check.
477      * @return {@code True} if the phone account has the capability.
478      */
hasCapabilities(int capability)479     public boolean hasCapabilities(int capability) {
480         return (mCapabilities & capability) == capability;
481     }
482 
483     /**
484      * A short label describing a {@code PhoneAccount}.
485      *
486      * @return A label for this {@code PhoneAccount}.
487      */
getLabel()488     public CharSequence getLabel() {
489         return mLabel;
490     }
491 
492     /**
493      * A short paragraph describing this {@code PhoneAccount}.
494      *
495      * @return A description for this {@code PhoneAccount}.
496      */
getShortDescription()497     public CharSequence getShortDescription() {
498         return mShortDescription;
499     }
500 
501     /**
502      * The URI schemes supported by this {@code PhoneAccount}.
503      *
504      * @return The URI schemes.
505      */
getSupportedUriSchemes()506     public List<String> getSupportedUriSchemes() {
507         return mSupportedUriSchemes;
508     }
509 
510     /**
511      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
512      * scheme.
513      *
514      * @param uriScheme The URI scheme to check.
515      * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
516      * specified URI scheme.
517      */
supportsUriScheme(String uriScheme)518     public boolean supportsUriScheme(String uriScheme) {
519         if (mSupportedUriSchemes == null || uriScheme == null) {
520             return false;
521         }
522 
523         for (String scheme : mSupportedUriSchemes) {
524             if (scheme != null && scheme.equals(uriScheme)) {
525                 return true;
526             }
527         }
528         return false;
529     }
530 
531     /**
532      * The icon resource ID for the icon of this {@code PhoneAccount}.
533      * <p>
534      * Creators of a {@code PhoneAccount} who possess the icon in static resources should prefer
535      * this method of indicating the icon rather than using {@link #getIconBitmap()}, since it
536      * leads to less resource usage.
537      * <p>
538      * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}.
539      *
540      * @return A resource ID.
541      */
getIconResId()542     public int getIconResId() {
543         return mIconResId;
544     }
545 
546     /**
547      * The package name from which to load the icon of this {@code PhoneAccount}.
548      * <p>
549      * If this property is {@code null}, the resource {@link #getIconResId()} will be loaded from
550      * the package in the {@link ComponentName} of the {@link #getAccountHandle()}.
551      * <p>
552      * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}.
553      *
554      * @return A package name.
555      */
getIconPackageName()556     public String getIconPackageName() {
557         return mIconPackageName;
558     }
559 
560     /**
561      * A tint to apply to the icon of this {@code PhoneAccount}.
562      *
563      * @return A hexadecimal color value.
564      */
getIconTint()565     public int getIconTint() {
566         return mIconTint;
567     }
568 
569     /**
570      * A literal icon bitmap to represent this {@code PhoneAccount} in a user interface.
571      * <p>
572      * If this property is specified, it is to be considered the preferred icon. Otherwise, the
573      * resource specified by {@link #getIconResId()} should be used.
574      * <p>
575      * Clients wishing to display a {@code PhoneAccount} should use
576      * {@link #createIconDrawable(Context)}.
577      *
578      * @return A bitmap.
579      */
getIconBitmap()580     public Bitmap getIconBitmap() {
581         return mIconBitmap;
582     }
583 
584     /**
585      * A highlight color to use in displaying information about this {@code PhoneAccount}.
586      *
587      * @return A hexadecimal color value.
588      */
getHighlightColor()589     public int getHighlightColor() {
590         return mHighlightColor;
591     }
592 
593     /**
594      * Builds and returns an icon {@code Drawable} to represent this {@code PhoneAccount} in a user
595      * interface. Uses the properties {@link #getIconResId()}, {@link #getIconPackageName()}, and
596      * {@link #getIconBitmap()} as necessary.
597      *
598      * @param context A {@code Context} to use for loading {@code Drawable}s.
599      *
600      * @return An icon for this {@code PhoneAccount}.
601      */
createIconDrawable(Context context)602     public Drawable createIconDrawable(Context context) {
603         if (mIconBitmap != null) {
604             return new BitmapDrawable(context.getResources(), mIconBitmap);
605         }
606 
607         if (mIconResId != 0) {
608             try {
609                 Context packageContext = context.createPackageContext(mIconPackageName, 0);
610                 try {
611                     Drawable iconDrawable = packageContext.getDrawable(mIconResId);
612                     if (mIconTint != NO_ICON_TINT) {
613                         iconDrawable.setTint(mIconTint);
614                     }
615                     return iconDrawable;
616                 } catch (NotFoundException | MissingResourceException e) {
617                     Log.e(this, e, "Cannot find icon %d in package %s",
618                             mIconResId, mIconPackageName);
619                 }
620             } catch (PackageManager.NameNotFoundException e) {
621                 Log.w(this, "Cannot find package %s", mIconPackageName);
622             }
623         }
624 
625         return new ColorDrawable(Color.TRANSPARENT);
626     }
627 
628     //
629     // Parcelable implementation
630     //
631 
632     @Override
describeContents()633     public int describeContents() {
634         return 0;
635     }
636 
637     @Override
writeToParcel(Parcel out, int flags)638     public void writeToParcel(Parcel out, int flags) {
639         if (mAccountHandle == null) {
640             out.writeInt(0);
641         } else {
642             out.writeInt(1);
643             mAccountHandle.writeToParcel(out, flags);
644         }
645         if (mAddress == null) {
646             out.writeInt(0);
647         } else {
648             out.writeInt(1);
649             mAddress.writeToParcel(out, flags);
650         }
651         if (mSubscriptionAddress == null) {
652             out.writeInt(0);
653         } else {
654             out.writeInt(1);
655             mSubscriptionAddress.writeToParcel(out, flags);
656         }
657         out.writeInt(mCapabilities);
658         out.writeInt(mIconResId);
659         out.writeString(mIconPackageName);
660         if (mIconBitmap == null) {
661             out.writeInt(0);
662         } else {
663             out.writeInt(1);
664             mIconBitmap.writeToParcel(out, flags);
665         }
666         out.writeInt(mIconTint);
667         out.writeInt(mHighlightColor);
668         out.writeCharSequence(mLabel);
669         out.writeCharSequence(mShortDescription);
670         out.writeStringList(mSupportedUriSchemes);
671     }
672 
673     public static final Creator<PhoneAccount> CREATOR
674             = new Creator<PhoneAccount>() {
675         @Override
676         public PhoneAccount createFromParcel(Parcel in) {
677             return new PhoneAccount(in);
678         }
679 
680         @Override
681         public PhoneAccount[] newArray(int size) {
682             return new PhoneAccount[size];
683         }
684     };
685 
PhoneAccount(Parcel in)686     private PhoneAccount(Parcel in) {
687         if (in.readInt() > 0) {
688             mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
689         } else {
690             mAccountHandle = null;
691         }
692         if (in.readInt() > 0) {
693             mAddress = Uri.CREATOR.createFromParcel(in);
694         } else {
695             mAddress = null;
696         }
697         if (in.readInt() > 0) {
698             mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
699         } else {
700             mSubscriptionAddress = null;
701         }
702         mCapabilities = in.readInt();
703         mIconResId = in.readInt();
704         mIconPackageName = in.readString();
705         if (in.readInt() > 0) {
706             mIconBitmap = Bitmap.CREATOR.createFromParcel(in);
707         } else {
708             mIconBitmap = null;
709         }
710         mIconTint = in.readInt();
711         mHighlightColor = in.readInt();
712         mLabel = in.readCharSequence();
713         mShortDescription = in.readCharSequence();
714         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
715     }
716 
717     @Override
toString()718     public String toString() {
719         StringBuilder sb = new StringBuilder().append("[PhoneAccount: ")
720                 .append(mAccountHandle)
721                 .append(" Capabilities: ")
722                 .append(mCapabilities)
723                 .append(" Schemes: ");
724         for (String scheme : mSupportedUriSchemes) {
725             sb.append(scheme)
726                     .append(" ");
727         }
728         sb.append("]");
729         return sb.toString();
730     }
731 }
732