Home | History | Annotate | Download | only in telecom
      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          */
    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          */
    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 */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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          */
    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 
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    633     public int describeContents() {
    634         return 0;
    635     }
    636 
    637     @Override
    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 
    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
    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