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