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