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.Parcel;
     32 import android.os.Parcelable;
     33 import android.text.TextUtils;
     34 
     35 import java.lang.String;
     36 import java.util.ArrayList;
     37 import java.util.Collections;
     38 import java.util.List;
     39 import java.util.MissingResourceException;
     40 
     41 /**
     42  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
     43  * want those calls to be integrated into the dialer and in-call UI should build an instance of
     44  * this class and register it with the system using {@link TelecomManager}.
     45  * <p>
     46  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
     47  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
     48  * should supply a valid {@link PhoneAccountHandle} that references the connection service
     49  * implementation Telecom will use to interact with the app.
     50  */
     51 public final class PhoneAccount implements Parcelable {
     52 
     53     /**
     54      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
     55      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
     56      * will be allowed to manage phone calls including using its own proprietary phone-call
     57      * implementation (like VoIP calling) to make calls instead of the telephony stack.
     58      * <p>
     59      * When a user opts to place a call using the SIM-based telephony stack, the
     60      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
     61      * if the user has explicitly selected it to be used as the default connection manager.
     62      * <p>
     63      * See {@link #getCapabilities}
     64      */
     65     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
     66 
     67     /**
     68      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
     69      * traditional SIM-based telephony calls. This account will be treated as a distinct method
     70      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
     71      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
     72      * or place calls from the built-in telephony stack.
     73      * <p>
     74      * See {@link #getCapabilities}
     75      * <p>
     76      */
     77     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
     78 
     79     /**
     80      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
     81      * subscription.
     82      * <p>
     83      * Only the Android framework can register a {@code PhoneAccount} having this capability.
     84      * <p>
     85      * See {@link #getCapabilities}
     86      */
     87     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
     88 
     89     /**
     90      * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
     91      * <p>
     92      * See {@link #getCapabilities}
     93      */
     94     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
     95 
     96     /**
     97      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
     98      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
     99      * <p>
    100      * See {@link #getCapabilities}
    101      */
    102     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
    103 
    104     /**
    105      * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
    106      * should only be used by system apps (and will be ignored for all other apps trying to use it).
    107      * <p>
    108      * See {@link #getCapabilities}
    109      * @hide
    110      */
    111     @SystemApi
    112     public static final int CAPABILITY_MULTI_USER = 0x20;
    113 
    114     /**
    115      * Flag indicating that this {@code PhoneAccount} supports a subject for Calls.  This means a
    116      * caller is able to specify a short subject line for an outgoing call.  A capable receiving
    117      * device displays the call subject on the incoming call screen.
    118      * <p>
    119      * See {@link #getCapabilities}
    120      */
    121     public static final int CAPABILITY_CALL_SUBJECT = 0x40;
    122 
    123     /**
    124      * URI scheme for telephone number URIs.
    125      */
    126     public static final String SCHEME_TEL = "tel";
    127 
    128     /**
    129      * URI scheme for voicemail URIs.
    130      */
    131     public static final String SCHEME_VOICEMAIL = "voicemail";
    132 
    133     /**
    134      * URI scheme for SIP URIs.
    135      */
    136     public static final String SCHEME_SIP = "sip";
    137 
    138     /**
    139      * Indicating no icon tint is set.
    140      * @hide
    141      */
    142     public static final int NO_ICON_TINT = 0;
    143 
    144     /**
    145      * Indicating no hightlight color is set.
    146      */
    147     public static final int NO_HIGHLIGHT_COLOR = 0;
    148 
    149     /**
    150      * Indicating no resource ID is set.
    151      */
    152     public static final int NO_RESOURCE_ID = -1;
    153 
    154     private final PhoneAccountHandle mAccountHandle;
    155     private final Uri mAddress;
    156     private final Uri mSubscriptionAddress;
    157     private final int mCapabilities;
    158     private final int mHighlightColor;
    159     private final CharSequence mLabel;
    160     private final CharSequence mShortDescription;
    161     private final List<String> mSupportedUriSchemes;
    162     private final Icon mIcon;
    163     private boolean mIsEnabled;
    164 
    165     /**
    166      * Helper class for creating a {@link PhoneAccount}.
    167      */
    168     public static class Builder {
    169         private PhoneAccountHandle mAccountHandle;
    170         private Uri mAddress;
    171         private Uri mSubscriptionAddress;
    172         private int mCapabilities;
    173         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
    174         private CharSequence mLabel;
    175         private CharSequence mShortDescription;
    176         private List<String> mSupportedUriSchemes = new ArrayList<String>();
    177         private Icon mIcon;
    178         private boolean mIsEnabled = false;
    179 
    180         /**
    181          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
    182          */
    183         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
    184             this.mAccountHandle = accountHandle;
    185             this.mLabel = label;
    186         }
    187 
    188         /**
    189          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
    190          * {@link PhoneAccount}.
    191          *
    192          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
    193          */
    194         public Builder(PhoneAccount phoneAccount) {
    195             mAccountHandle = phoneAccount.getAccountHandle();
    196             mAddress = phoneAccount.getAddress();
    197             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
    198             mCapabilities = phoneAccount.getCapabilities();
    199             mHighlightColor = phoneAccount.getHighlightColor();
    200             mLabel = phoneAccount.getLabel();
    201             mShortDescription = phoneAccount.getShortDescription();
    202             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
    203             mIcon = phoneAccount.getIcon();
    204             mIsEnabled = phoneAccount.isEnabled();
    205         }
    206 
    207         /**
    208          * Sets the address. See {@link PhoneAccount#getAddress}.
    209          *
    210          * @param value The address of the phone account.
    211          * @return The builder.
    212          */
    213         public Builder setAddress(Uri value) {
    214             this.mAddress = value;
    215             return this;
    216         }
    217 
    218         /**
    219          * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
    220          *
    221          * @param value The subscription address.
    222          * @return The builder.
    223          */
    224         public Builder setSubscriptionAddress(Uri value) {
    225             this.mSubscriptionAddress = value;
    226             return this;
    227         }
    228 
    229         /**
    230          * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
    231          *
    232          * @param value The capabilities to set.
    233          * @return The builder.
    234          */
    235         public Builder setCapabilities(int value) {
    236             this.mCapabilities = value;
    237             return this;
    238         }
    239 
    240         /**
    241          * Sets the icon. See {@link PhoneAccount#getIcon}.
    242          *
    243          * @param icon The icon to set.
    244          */
    245         public Builder setIcon(Icon icon) {
    246             mIcon = icon;
    247             return this;
    248         }
    249 
    250         /**
    251          * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
    252          *
    253          * @param value The highlight color.
    254          * @return The builder.
    255          */
    256         public Builder setHighlightColor(int value) {
    257             this.mHighlightColor = value;
    258             return this;
    259         }
    260 
    261         /**
    262          * Sets the short description. See {@link PhoneAccount#getShortDescription}.
    263          *
    264          * @param value The short description.
    265          * @return The builder.
    266          */
    267         public Builder setShortDescription(CharSequence value) {
    268             this.mShortDescription = value;
    269             return this;
    270         }
    271 
    272         /**
    273          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
    274          *
    275          * @param uriScheme The URI scheme.
    276          * @return The builder.
    277          */
    278         public Builder addSupportedUriScheme(String uriScheme) {
    279             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
    280                 this.mSupportedUriSchemes.add(uriScheme);
    281             }
    282             return this;
    283         }
    284 
    285         /**
    286          * Specifies the URI schemes supported by the {@link PhoneAccount}.
    287          *
    288          * @param uriSchemes The URI schemes.
    289          * @return The builder.
    290          */
    291         public Builder setSupportedUriSchemes(List<String> uriSchemes) {
    292             mSupportedUriSchemes.clear();
    293 
    294             if (uriSchemes != null && !uriSchemes.isEmpty()) {
    295                 for (String uriScheme : uriSchemes) {
    296                     addSupportedUriScheme(uriScheme);
    297                 }
    298             }
    299             return this;
    300         }
    301 
    302         /**
    303          * Sets the enabled state of the phone account.
    304          *
    305          * @param isEnabled The enabled state.
    306          * @return The builder.
    307          * @hide
    308          */
    309         public Builder setIsEnabled(boolean isEnabled) {
    310             mIsEnabled = isEnabled;
    311             return this;
    312         }
    313 
    314         /**
    315          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
    316          *
    317          * @return The {@link PhoneAccount}.
    318          */
    319         public PhoneAccount build() {
    320             // If no supported URI schemes were defined, assume "tel" is supported.
    321             if (mSupportedUriSchemes.isEmpty()) {
    322                 addSupportedUriScheme(SCHEME_TEL);
    323             }
    324 
    325             return new PhoneAccount(
    326                     mAccountHandle,
    327                     mAddress,
    328                     mSubscriptionAddress,
    329                     mCapabilities,
    330                     mIcon,
    331                     mHighlightColor,
    332                     mLabel,
    333                     mShortDescription,
    334                     mSupportedUriSchemes,
    335                     mIsEnabled);
    336         }
    337     }
    338 
    339     private PhoneAccount(
    340             PhoneAccountHandle account,
    341             Uri address,
    342             Uri subscriptionAddress,
    343             int capabilities,
    344             Icon icon,
    345             int highlightColor,
    346             CharSequence label,
    347             CharSequence shortDescription,
    348             List<String> supportedUriSchemes,
    349             boolean isEnabled) {
    350         mAccountHandle = account;
    351         mAddress = address;
    352         mSubscriptionAddress = subscriptionAddress;
    353         mCapabilities = capabilities;
    354         mIcon = icon;
    355         mHighlightColor = highlightColor;
    356         mLabel = label;
    357         mShortDescription = shortDescription;
    358         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
    359         mIsEnabled = isEnabled;
    360     }
    361 
    362     public static Builder builder(
    363             PhoneAccountHandle accountHandle,
    364             CharSequence label) {
    365         return new Builder(accountHandle, label);
    366     }
    367 
    368     /**
    369      * Returns a builder initialized with the current {@link PhoneAccount} instance.
    370      *
    371      * @return The builder.
    372      */
    373     public Builder toBuilder() { return new Builder(this); }
    374 
    375     /**
    376      * The unique identifier of this {@code PhoneAccount}.
    377      *
    378      * @return A {@code PhoneAccountHandle}.
    379      */
    380     public PhoneAccountHandle getAccountHandle() {
    381         return mAccountHandle;
    382     }
    383 
    384     /**
    385      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
    386      * represents the destination from which outgoing calls using this {@code PhoneAccount}
    387      * will appear to come, if applicable, and the destination to which incoming calls using this
    388      * {@code PhoneAccount} may be addressed.
    389      *
    390      * @return A address expressed as a {@code Uri}, for example, a phone number.
    391      */
    392     public Uri getAddress() {
    393         return mAddress;
    394     }
    395 
    396     /**
    397      * The raw callback number used for this {@code PhoneAccount}, as distinct from
    398      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
    399      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
    400      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
    401      * has been used to alter the callback number.
    402      * <p>
    403      *
    404      * @return The subscription number, suitable for display to the user.
    405      */
    406     public Uri getSubscriptionAddress() {
    407         return mSubscriptionAddress;
    408     }
    409 
    410     /**
    411      * The capabilities of this {@code PhoneAccount}.
    412      *
    413      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
    414      */
    415     public int getCapabilities() {
    416         return mCapabilities;
    417     }
    418 
    419     /**
    420      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
    421      * bit mask.
    422      *
    423      * @param capability The capabilities to check.
    424      * @return {@code true} if the phone account has the capability.
    425      */
    426     public boolean hasCapabilities(int capability) {
    427         return (mCapabilities & capability) == capability;
    428     }
    429 
    430     /**
    431      * A short label describing a {@code PhoneAccount}.
    432      *
    433      * @return A label for this {@code PhoneAccount}.
    434      */
    435     public CharSequence getLabel() {
    436         return mLabel;
    437     }
    438 
    439     /**
    440      * A short paragraph describing this {@code PhoneAccount}.
    441      *
    442      * @return A description for this {@code PhoneAccount}.
    443      */
    444     public CharSequence getShortDescription() {
    445         return mShortDescription;
    446     }
    447 
    448     /**
    449      * The URI schemes supported by this {@code PhoneAccount}.
    450      *
    451      * @return The URI schemes.
    452      */
    453     public List<String> getSupportedUriSchemes() {
    454         return mSupportedUriSchemes;
    455     }
    456 
    457     /**
    458      * The icon to represent this {@code PhoneAccount}.
    459      *
    460      * @return The icon.
    461      */
    462     public Icon getIcon() {
    463         return mIcon;
    464     }
    465 
    466     /**
    467      * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
    468      * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
    469      *
    470      * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
    471      */
    472     public boolean isEnabled() {
    473         return mIsEnabled;
    474     }
    475 
    476     /**
    477      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
    478      * scheme.
    479      *
    480      * @param uriScheme The URI scheme to check.
    481      * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
    482      * specified URI scheme.
    483      */
    484     public boolean supportsUriScheme(String uriScheme) {
    485         if (mSupportedUriSchemes == null || uriScheme == null) {
    486             return false;
    487         }
    488 
    489         for (String scheme : mSupportedUriSchemes) {
    490             if (scheme != null && scheme.equals(uriScheme)) {
    491                 return true;
    492             }
    493         }
    494         return false;
    495     }
    496 
    497     /**
    498      * A highlight color to use in displaying information about this {@code PhoneAccount}.
    499      *
    500      * @return A hexadecimal color value.
    501      */
    502     public int getHighlightColor() {
    503         return mHighlightColor;
    504     }
    505 
    506     /**
    507      * Sets the enabled state of the phone account.
    508      * @hide
    509      */
    510     public void setIsEnabled(boolean isEnabled) {
    511         mIsEnabled = isEnabled;
    512     }
    513 
    514     //
    515     // Parcelable implementation
    516     //
    517 
    518     @Override
    519     public int describeContents() {
    520         return 0;
    521     }
    522 
    523     @Override
    524     public void writeToParcel(Parcel out, int flags) {
    525         if (mAccountHandle == null) {
    526             out.writeInt(0);
    527         } else {
    528             out.writeInt(1);
    529             mAccountHandle.writeToParcel(out, flags);
    530         }
    531         if (mAddress == null) {
    532             out.writeInt(0);
    533         } else {
    534             out.writeInt(1);
    535             mAddress.writeToParcel(out, flags);
    536         }
    537         if (mSubscriptionAddress == null) {
    538             out.writeInt(0);
    539         } else {
    540             out.writeInt(1);
    541             mSubscriptionAddress.writeToParcel(out, flags);
    542         }
    543         out.writeInt(mCapabilities);
    544         out.writeInt(mHighlightColor);
    545         out.writeCharSequence(mLabel);
    546         out.writeCharSequence(mShortDescription);
    547         out.writeStringList(mSupportedUriSchemes);
    548 
    549         if (mIcon == null) {
    550             out.writeInt(0);
    551         } else {
    552             out.writeInt(1);
    553             mIcon.writeToParcel(out, flags);
    554         }
    555         out.writeByte((byte) (mIsEnabled ? 1 : 0));
    556     }
    557 
    558     public static final Creator<PhoneAccount> CREATOR
    559             = new Creator<PhoneAccount>() {
    560         @Override
    561         public PhoneAccount createFromParcel(Parcel in) {
    562             return new PhoneAccount(in);
    563         }
    564 
    565         @Override
    566         public PhoneAccount[] newArray(int size) {
    567             return new PhoneAccount[size];
    568         }
    569     };
    570 
    571     private PhoneAccount(Parcel in) {
    572         if (in.readInt() > 0) {
    573             mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
    574         } else {
    575             mAccountHandle = null;
    576         }
    577         if (in.readInt() > 0) {
    578             mAddress = Uri.CREATOR.createFromParcel(in);
    579         } else {
    580             mAddress = null;
    581         }
    582         if (in.readInt() > 0) {
    583             mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
    584         } else {
    585             mSubscriptionAddress = null;
    586         }
    587         mCapabilities = in.readInt();
    588         mHighlightColor = in.readInt();
    589         mLabel = in.readCharSequence();
    590         mShortDescription = in.readCharSequence();
    591         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
    592         if (in.readInt() > 0) {
    593             mIcon = Icon.CREATOR.createFromParcel(in);
    594         } else {
    595             mIcon = null;
    596         }
    597         mIsEnabled = in.readByte() == 1;
    598     }
    599 
    600     @Override
    601     public String toString() {
    602         StringBuilder sb = new StringBuilder().append("[[")
    603                 .append(mIsEnabled ? 'X' : ' ')
    604                 .append("] PhoneAccount: ")
    605                 .append(mAccountHandle)
    606                 .append(" Capabilities: ")
    607                 .append(mCapabilities)
    608                 .append(" Schemes: ");
    609         for (String scheme : mSupportedUriSchemes) {
    610             sb.append(scheme)
    611                     .append(" ");
    612         }
    613         sb.append("]");
    614         return sb.toString();
    615     }
    616 }
    617