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.Context;
     21 import android.content.pm.PackageManager;
     22 import android.content.res.Resources.NotFoundException;
     23 import android.graphics.drawable.Drawable;
     24 import android.net.Uri;
     25 import android.os.Parcel;
     26 import android.os.Parcelable;
     27 import android.text.TextUtils;
     28 
     29 import java.lang.String;
     30 import java.util.ArrayList;
     31 import java.util.Collections;
     32 import java.util.List;
     33 import java.util.MissingResourceException;
     34 
     35 /**
     36  * Describes a distinct account, line of service or call placement method that the system
     37  * can use to place phone calls.
     38  * @hide
     39  */
     40 @SystemApi
     41 public class PhoneAccount implements Parcelable {
     42 
     43     /**
     44      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
     45      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
     46      * will be allowed to manage phone calls including using its own proprietary phone-call
     47      * implementation (like VoIP calling) to make calls instead of the telephony stack.
     48      * <p>
     49      * When a user opts to place a call using the SIM-based telephony stack, the
     50      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
     51      * if the user has explicitly selected it to be used as the default connection manager.
     52      * <p>
     53      * See {@link #getCapabilities}
     54      */
     55     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
     56 
     57     /**
     58      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
     59      * traditional SIM-based telephony calls. This account will be treated as a distinct method
     60      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
     61      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
     62      * calls from or use the built-in telephony stack to place its calls.
     63      * <p>
     64      * See {@link #getCapabilities}
     65      * <p>
     66      * {@hide}
     67      */
     68     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
     69 
     70     /**
     71      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
     72      * subscription.
     73      * <p>
     74      * Only the Android framework can register a {@code PhoneAccount} having this capability.
     75      * <p>
     76      * See {@link #getCapabilities}
     77      */
     78     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
     79 
     80     /**
     81      * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
     82      * <p>
     83      * See {@link #getCapabilities}
     84      * @hide
     85      */
     86     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
     87 
     88     /**
     89      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
     90      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
     91      * <p>
     92      * See {@link #getCapabilities}
     93      */
     94     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
     95 
     96     /**
     97      * URI scheme for telephone number URIs.
     98      */
     99     public static final String SCHEME_TEL = "tel";
    100 
    101     /**
    102      * URI scheme for voicemail URIs.
    103      */
    104     public static final String SCHEME_VOICEMAIL = "voicemail";
    105 
    106     /**
    107      * URI scheme for SIP URIs.
    108      */
    109     public static final String SCHEME_SIP = "sip";
    110 
    111     private final PhoneAccountHandle mAccountHandle;
    112     private final Uri mAddress;
    113     private final Uri mSubscriptionAddress;
    114     private final int mCapabilities;
    115     private final int mIconResId;
    116     private final CharSequence mLabel;
    117     private final CharSequence mShortDescription;
    118     private final List<String> mSupportedUriSchemes;
    119 
    120     public static class Builder {
    121         private PhoneAccountHandle mAccountHandle;
    122         private Uri mAddress;
    123         private Uri mSubscriptionAddress;
    124         private int mCapabilities;
    125         private int mIconResId;
    126         private CharSequence mLabel;
    127         private CharSequence mShortDescription;
    128         private List<String> mSupportedUriSchemes = new ArrayList<String>();
    129 
    130         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
    131             this.mAccountHandle = accountHandle;
    132             this.mLabel = label;
    133         }
    134 
    135         /**
    136          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
    137          * {@link PhoneAccount}.
    138          *
    139          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
    140          */
    141         public Builder(PhoneAccount phoneAccount) {
    142             mAccountHandle = phoneAccount.getAccountHandle();
    143             mAddress = phoneAccount.getAddress();
    144             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
    145             mCapabilities = phoneAccount.getCapabilities();
    146             mIconResId = phoneAccount.getIconResId();
    147             mLabel = phoneAccount.getLabel();
    148             mShortDescription = phoneAccount.getShortDescription();
    149             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
    150         }
    151 
    152         public Builder setAddress(Uri value) {
    153             this.mAddress = value;
    154             return this;
    155         }
    156 
    157         public Builder setSubscriptionAddress(Uri value) {
    158             this.mSubscriptionAddress = value;
    159             return this;
    160         }
    161 
    162         public Builder setCapabilities(int value) {
    163             this.mCapabilities = value;
    164             return this;
    165         }
    166 
    167         public Builder setIconResId(int value) {
    168             this.mIconResId = value;
    169             return this;
    170         }
    171 
    172         public Builder setShortDescription(CharSequence value) {
    173             this.mShortDescription = value;
    174             return this;
    175         }
    176 
    177         /**
    178          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
    179          *
    180          * @param uriScheme The URI scheme.
    181          * @return The Builder.
    182          * @hide
    183          */
    184         public Builder addSupportedUriScheme(String uriScheme) {
    185             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
    186                 this.mSupportedUriSchemes.add(uriScheme);
    187             }
    188             return this;
    189         }
    190 
    191         /**
    192          * Specifies the URI schemes supported by the {@link PhoneAccount}.
    193          *
    194          * @param uriSchemes The URI schemes.
    195          * @return The Builder.
    196          */
    197         public Builder setSupportedUriSchemes(List<String> uriSchemes) {
    198             mSupportedUriSchemes.clear();
    199 
    200             if (uriSchemes != null && !uriSchemes.isEmpty()) {
    201                 for (String uriScheme : uriSchemes) {
    202                     addSupportedUriScheme(uriScheme);
    203                 }
    204             }
    205             return this;
    206         }
    207 
    208         /**
    209          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
    210          *
    211          * @return The {@link PhoneAccount}.
    212          */
    213         public PhoneAccount build() {
    214             // If no supported URI schemes were defined, assume "tel" is supported.
    215             if (mSupportedUriSchemes.isEmpty()) {
    216                 addSupportedUriScheme(SCHEME_TEL);
    217             }
    218 
    219             return new PhoneAccount(
    220                     mAccountHandle,
    221                     mAddress,
    222                     mSubscriptionAddress,
    223                     mCapabilities,
    224                     mIconResId,
    225                     mLabel,
    226                     mShortDescription,
    227                     mSupportedUriSchemes);
    228         }
    229     }
    230 
    231     private PhoneAccount(
    232             PhoneAccountHandle account,
    233             Uri address,
    234             Uri subscriptionAddress,
    235             int capabilities,
    236             int iconResId,
    237             CharSequence label,
    238             CharSequence shortDescription,
    239             List<String> supportedUriSchemes) {
    240         mAccountHandle = account;
    241         mAddress = address;
    242         mSubscriptionAddress = subscriptionAddress;
    243         mCapabilities = capabilities;
    244         mIconResId = iconResId;
    245         mLabel = label;
    246         mShortDescription = shortDescription;
    247         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
    248     }
    249 
    250     public static Builder builder(
    251             PhoneAccountHandle accountHandle,
    252             CharSequence label) {
    253         return new Builder(accountHandle, label);
    254     }
    255 
    256     /**
    257      * Returns a builder initialized with the current {@link PhoneAccount} instance.
    258      *
    259      * @return The builder.
    260      * @hide
    261      */
    262     public Builder toBuilder() { return new Builder(this); }
    263 
    264     /**
    265      * The unique identifier of this {@code PhoneAccount}.
    266      *
    267      * @return A {@code PhoneAccountHandle}.
    268      */
    269     public PhoneAccountHandle getAccountHandle() {
    270         return mAccountHandle;
    271     }
    272 
    273     /**
    274      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
    275      * represents the destination from which outgoing calls using this {@code PhoneAccount}
    276      * will appear to come, if applicable, and the destination to which incoming calls using this
    277      * {@code PhoneAccount} may be addressed.
    278      *
    279      * @return A address expressed as a {@code Uri}, for example, a phone number.
    280      */
    281     public Uri getAddress() {
    282         return mAddress;
    283     }
    284 
    285     /**
    286      * The raw callback number used for this {@code PhoneAccount}, as distinct from
    287      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
    288      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
    289      *
    290      * @return The subscription number, suitable for display to the user.
    291      */
    292     public Uri getSubscriptionAddress() {
    293         return mSubscriptionAddress;
    294     }
    295 
    296     /**
    297      * The capabilities of this {@code PhoneAccount}.
    298      *
    299      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
    300      */
    301     public int getCapabilities() {
    302         return mCapabilities;
    303     }
    304 
    305     /**
    306      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
    307      * bit mask.
    308      *
    309      * @param capability The capabilities to check.
    310      * @return {@code True} if the phone account has the capability.
    311      */
    312     public boolean hasCapabilities(int capability) {
    313         return (mCapabilities & capability) == capability;
    314     }
    315 
    316     /**
    317      * A short label describing a {@code PhoneAccount}.
    318      *
    319      * @return A label for this {@code PhoneAccount}.
    320      */
    321     public CharSequence getLabel() {
    322         return mLabel;
    323     }
    324 
    325     /**
    326      * A short paragraph describing this {@code PhoneAccount}.
    327      *
    328      * @return A description for this {@code PhoneAccount}.
    329      */
    330     public CharSequence getShortDescription() {
    331         return mShortDescription;
    332     }
    333 
    334     /**
    335      * The URI schemes supported by this {@code PhoneAccount}.
    336      *
    337      * @return The URI schemes.
    338      */
    339     public List<String> getSupportedUriSchemes() {
    340         return mSupportedUriSchemes;
    341     }
    342 
    343     /**
    344      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
    345      * scheme.
    346      *
    347      * @param uriScheme The URI scheme to check.
    348      * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
    349      * specified URI scheme.
    350      */
    351     public boolean supportsUriScheme(String uriScheme) {
    352         if (mSupportedUriSchemes == null || uriScheme == null) {
    353             return false;
    354         }
    355 
    356         for (String scheme : mSupportedUriSchemes) {
    357             if (scheme != null && scheme.equals(uriScheme)) {
    358                 return true;
    359             }
    360         }
    361         return false;
    362     }
    363 
    364     /**
    365      * The icon resource ID for the icon of this {@code PhoneAccount}.
    366      *
    367      * @return A resource ID.
    368      */
    369     public int getIconResId() {
    370         return mIconResId;
    371     }
    372 
    373     /**
    374      * An icon to represent this {@code PhoneAccount} in a user interface.
    375      *
    376      * @return An icon for this {@code PhoneAccount}.
    377      */
    378     public Drawable getIcon(Context context) {
    379         return getIcon(context, mIconResId);
    380     }
    381 
    382     private Drawable getIcon(Context context, int resId) {
    383         Context packageContext;
    384         try {
    385             packageContext = context.createPackageContext(
    386                     mAccountHandle.getComponentName().getPackageName(), 0);
    387         } catch (PackageManager.NameNotFoundException e) {
    388             Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName());
    389             return null;
    390         }
    391         try {
    392             return packageContext.getDrawable(resId);
    393         } catch (NotFoundException|MissingResourceException e) {
    394             Log.e(this, e, "Cannot find icon %d in package %s",
    395                     resId, mAccountHandle.getComponentName().getPackageName());
    396             return null;
    397         }
    398     }
    399 
    400     //
    401     // Parcelable implementation
    402     //
    403 
    404     @Override
    405     public int describeContents() {
    406         return 0;
    407     }
    408 
    409     @Override
    410     public void writeToParcel(Parcel out, int flags) {
    411         out.writeParcelable(mAccountHandle, 0);
    412         out.writeParcelable(mAddress, 0);
    413         out.writeParcelable(mSubscriptionAddress, 0);
    414         out.writeInt(mCapabilities);
    415         out.writeInt(mIconResId);
    416         out.writeCharSequence(mLabel);
    417         out.writeCharSequence(mShortDescription);
    418         out.writeList(mSupportedUriSchemes);
    419     }
    420 
    421     public static final Creator<PhoneAccount> CREATOR
    422             = new Creator<PhoneAccount>() {
    423         @Override
    424         public PhoneAccount createFromParcel(Parcel in) {
    425             return new PhoneAccount(in);
    426         }
    427 
    428         @Override
    429         public PhoneAccount[] newArray(int size) {
    430             return new PhoneAccount[size];
    431         }
    432     };
    433 
    434     private PhoneAccount(Parcel in) {
    435         ClassLoader classLoader = PhoneAccount.class.getClassLoader();
    436 
    437         mAccountHandle = in.readParcelable(getClass().getClassLoader());
    438         mAddress = in.readParcelable(getClass().getClassLoader());
    439         mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
    440         mCapabilities = in.readInt();
    441         mIconResId = in.readInt();
    442         mLabel = in.readCharSequence();
    443         mShortDescription = in.readCharSequence();
    444 
    445         List<String> supportedUriSchemes = new ArrayList<>();
    446         in.readList(supportedUriSchemes, classLoader);
    447         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
    448     }
    449 }
    450