PhoneAccount.java revision 895d4b8f63389b79974dfd3e36f1ab10b5ceb4dc
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.annotation.SystemApi;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.pm.PackageManager;
23import android.content.res.Resources.NotFoundException;
24import android.graphics.Bitmap;
25import android.graphics.Color;
26import android.graphics.drawable.BitmapDrawable;
27import android.graphics.drawable.ColorDrawable;
28import android.graphics.drawable.Drawable;
29import android.graphics.drawable.Icon;
30import android.net.Uri;
31import android.os.Parcel;
32import android.os.Parcelable;
33import android.text.TextUtils;
34
35import java.lang.String;
36import java.util.ArrayList;
37import java.util.Collections;
38import java.util.List;
39import 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 */
51public 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     * URI scheme for telephone number URIs.
116     */
117    public static final String SCHEME_TEL = "tel";
118
119    /**
120     * URI scheme for voicemail URIs.
121     */
122    public static final String SCHEME_VOICEMAIL = "voicemail";
123
124    /**
125     * URI scheme for SIP URIs.
126     */
127    public static final String SCHEME_SIP = "sip";
128
129    /**
130     * Indicating no icon tint is set.
131     * @hide
132     */
133    public static final int NO_ICON_TINT = 0;
134
135    /**
136     * Indicating no hightlight color is set.
137     */
138    public static final int NO_HIGHLIGHT_COLOR = 0;
139
140    /**
141     * Indicating no resource ID is set.
142     */
143    public static final int NO_RESOURCE_ID = -1;
144
145    private final PhoneAccountHandle mAccountHandle;
146    private final Uri mAddress;
147    private final Uri mSubscriptionAddress;
148    private final int mCapabilities;
149    private final int mHighlightColor;
150    private final CharSequence mLabel;
151    private final CharSequence mShortDescription;
152    private final List<String> mSupportedUriSchemes;
153    private final Icon mIcon;
154    private boolean mIsEnabled;
155
156    /**
157     * Helper class for creating a {@link PhoneAccount}.
158     */
159    public static class Builder {
160        private PhoneAccountHandle mAccountHandle;
161        private Uri mAddress;
162        private Uri mSubscriptionAddress;
163        private int mCapabilities;
164        private int mHighlightColor = NO_HIGHLIGHT_COLOR;
165        private CharSequence mLabel;
166        private CharSequence mShortDescription;
167        private List<String> mSupportedUriSchemes = new ArrayList<String>();
168        private Icon mIcon;
169        private boolean mIsEnabled = false;
170
171        /**
172         * Creates a builder with the specified {@link PhoneAccountHandle} and label.
173         */
174        public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
175            this.mAccountHandle = accountHandle;
176            this.mLabel = label;
177        }
178
179        /**
180         * Creates an instance of the {@link PhoneAccount.Builder} from an existing
181         * {@link PhoneAccount}.
182         *
183         * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
184         */
185        public Builder(PhoneAccount phoneAccount) {
186            mAccountHandle = phoneAccount.getAccountHandle();
187            mAddress = phoneAccount.getAddress();
188            mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
189            mCapabilities = phoneAccount.getCapabilities();
190            mHighlightColor = phoneAccount.getHighlightColor();
191            mLabel = phoneAccount.getLabel();
192            mShortDescription = phoneAccount.getShortDescription();
193            mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
194            mIcon = phoneAccount.getIcon();
195            mIsEnabled = phoneAccount.isEnabled();
196        }
197
198        /**
199         * Sets the address. See {@link PhoneAccount#getAddress}.
200         *
201         * @param value The address of the phone account.
202         * @return The builder.
203         */
204        public Builder setAddress(Uri value) {
205            this.mAddress = value;
206            return this;
207        }
208
209        /**
210         * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
211         *
212         * @param value The subscription address.
213         * @return The builder.
214         */
215        public Builder setSubscriptionAddress(Uri value) {
216            this.mSubscriptionAddress = value;
217            return this;
218        }
219
220        /**
221         * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
222         *
223         * @param value The capabilities to set.
224         * @return The builder.
225         */
226        public Builder setCapabilities(int value) {
227            this.mCapabilities = value;
228            return this;
229        }
230
231        /**
232         * Sets the icon. See {@link PhoneAccount#getIcon}.
233         *
234         * @param icon The icon to set.
235         */
236        public Builder setIcon(Icon icon) {
237            mIcon = icon;
238            return this;
239        }
240
241        /**
242         * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
243         *
244         * @param value The highlight color.
245         * @return The builder.
246         */
247        public Builder setHighlightColor(int value) {
248            this.mHighlightColor = value;
249            return this;
250        }
251
252        /**
253         * Sets the short description. See {@link PhoneAccount#getShortDescription}.
254         *
255         * @param value The short description.
256         * @return The builder.
257         */
258        public Builder setShortDescription(CharSequence value) {
259            this.mShortDescription = value;
260            return this;
261        }
262
263        /**
264         * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
265         *
266         * @param uriScheme The URI scheme.
267         * @return The builder.
268         */
269        public Builder addSupportedUriScheme(String uriScheme) {
270            if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
271                this.mSupportedUriSchemes.add(uriScheme);
272            }
273            return this;
274        }
275
276        /**
277         * Specifies the URI schemes supported by the {@link PhoneAccount}.
278         *
279         * @param uriSchemes The URI schemes.
280         * @return The builder.
281         */
282        public Builder setSupportedUriSchemes(List<String> uriSchemes) {
283            mSupportedUriSchemes.clear();
284
285            if (uriSchemes != null && !uriSchemes.isEmpty()) {
286                for (String uriScheme : uriSchemes) {
287                    addSupportedUriScheme(uriScheme);
288                }
289            }
290            return this;
291        }
292
293        /**
294         * Sets the enabled state of the phone account.
295         *
296         * @param isEnabled The enabled state.
297         * @return The builder.
298         * @hide
299         */
300        public Builder setIsEnabled(boolean isEnabled) {
301            mIsEnabled = isEnabled;
302            return this;
303        }
304
305        /**
306         * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
307         *
308         * @return The {@link PhoneAccount}.
309         */
310        public PhoneAccount build() {
311            // If no supported URI schemes were defined, assume "tel" is supported.
312            if (mSupportedUriSchemes.isEmpty()) {
313                addSupportedUriScheme(SCHEME_TEL);
314            }
315
316            return new PhoneAccount(
317                    mAccountHandle,
318                    mAddress,
319                    mSubscriptionAddress,
320                    mCapabilities,
321                    mIcon,
322                    mHighlightColor,
323                    mLabel,
324                    mShortDescription,
325                    mSupportedUriSchemes,
326                    mIsEnabled);
327        }
328    }
329
330    private PhoneAccount(
331            PhoneAccountHandle account,
332            Uri address,
333            Uri subscriptionAddress,
334            int capabilities,
335            Icon icon,
336            int highlightColor,
337            CharSequence label,
338            CharSequence shortDescription,
339            List<String> supportedUriSchemes,
340            boolean isEnabled) {
341        mAccountHandle = account;
342        mAddress = address;
343        mSubscriptionAddress = subscriptionAddress;
344        mCapabilities = capabilities;
345        mIcon = icon;
346        mHighlightColor = highlightColor;
347        mLabel = label;
348        mShortDescription = shortDescription;
349        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
350        mIsEnabled = isEnabled;
351    }
352
353    public static Builder builder(
354            PhoneAccountHandle accountHandle,
355            CharSequence label) {
356        return new Builder(accountHandle, label);
357    }
358
359    /**
360     * Returns a builder initialized with the current {@link PhoneAccount} instance.
361     *
362     * @return The builder.
363     */
364    public Builder toBuilder() { return new Builder(this); }
365
366    /**
367     * The unique identifier of this {@code PhoneAccount}.
368     *
369     * @return A {@code PhoneAccountHandle}.
370     */
371    public PhoneAccountHandle getAccountHandle() {
372        return mAccountHandle;
373    }
374
375    /**
376     * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
377     * represents the destination from which outgoing calls using this {@code PhoneAccount}
378     * will appear to come, if applicable, and the destination to which incoming calls using this
379     * {@code PhoneAccount} may be addressed.
380     *
381     * @return A address expressed as a {@code Uri}, for example, a phone number.
382     */
383    public Uri getAddress() {
384        return mAddress;
385    }
386
387    /**
388     * The raw callback number used for this {@code PhoneAccount}, as distinct from
389     * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
390     * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
391     * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
392     * has been used to alter the callback number.
393     * <p>
394     *
395     * @return The subscription number, suitable for display to the user.
396     */
397    public Uri getSubscriptionAddress() {
398        return mSubscriptionAddress;
399    }
400
401    /**
402     * The capabilities of this {@code PhoneAccount}.
403     *
404     * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
405     */
406    public int getCapabilities() {
407        return mCapabilities;
408    }
409
410    /**
411     * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
412     * bit mask.
413     *
414     * @param capability The capabilities to check.
415     * @return {@code true} if the phone account has the capability.
416     */
417    public boolean hasCapabilities(int capability) {
418        return (mCapabilities & capability) == capability;
419    }
420
421    /**
422     * A short label describing a {@code PhoneAccount}.
423     *
424     * @return A label for this {@code PhoneAccount}.
425     */
426    public CharSequence getLabel() {
427        return mLabel;
428    }
429
430    /**
431     * A short paragraph describing this {@code PhoneAccount}.
432     *
433     * @return A description for this {@code PhoneAccount}.
434     */
435    public CharSequence getShortDescription() {
436        return mShortDescription;
437    }
438
439    /**
440     * The URI schemes supported by this {@code PhoneAccount}.
441     *
442     * @return The URI schemes.
443     */
444    public List<String> getSupportedUriSchemes() {
445        return mSupportedUriSchemes;
446    }
447
448    /**
449     * The icon to represent this {@code PhoneAccount}.
450     *
451     * @return The icon.
452     */
453    public Icon getIcon() {
454        return mIcon;
455    }
456
457    /**
458     * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
459     * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
460     *
461     * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
462     */
463    public boolean isEnabled() {
464        return mIsEnabled;
465    }
466
467    /**
468     * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
469     * scheme.
470     *
471     * @param uriScheme The URI scheme to check.
472     * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
473     * specified URI scheme.
474     */
475    public boolean supportsUriScheme(String uriScheme) {
476        if (mSupportedUriSchemes == null || uriScheme == null) {
477            return false;
478        }
479
480        for (String scheme : mSupportedUriSchemes) {
481            if (scheme != null && scheme.equals(uriScheme)) {
482                return true;
483            }
484        }
485        return false;
486    }
487
488    /**
489     * A highlight color to use in displaying information about this {@code PhoneAccount}.
490     *
491     * @return A hexadecimal color value.
492     */
493    public int getHighlightColor() {
494        return mHighlightColor;
495    }
496
497    /**
498     * Sets the enabled state of the phone account.
499     * @hide
500     */
501    public void setIsEnabled(boolean isEnabled) {
502        mIsEnabled = isEnabled;
503    }
504
505    //
506    // Parcelable implementation
507    //
508
509    @Override
510    public int describeContents() {
511        return 0;
512    }
513
514    @Override
515    public void writeToParcel(Parcel out, int flags) {
516        if (mAccountHandle == null) {
517            out.writeInt(0);
518        } else {
519            out.writeInt(1);
520            mAccountHandle.writeToParcel(out, flags);
521        }
522        if (mAddress == null) {
523            out.writeInt(0);
524        } else {
525            out.writeInt(1);
526            mAddress.writeToParcel(out, flags);
527        }
528        if (mSubscriptionAddress == null) {
529            out.writeInt(0);
530        } else {
531            out.writeInt(1);
532            mSubscriptionAddress.writeToParcel(out, flags);
533        }
534        out.writeInt(mCapabilities);
535        out.writeInt(mHighlightColor);
536        out.writeCharSequence(mLabel);
537        out.writeCharSequence(mShortDescription);
538        out.writeStringList(mSupportedUriSchemes);
539
540        if (mIcon == null) {
541            out.writeInt(0);
542        } else {
543            out.writeInt(1);
544            mIcon.writeToParcel(out, flags);
545        }
546        out.writeByte((byte) (mIsEnabled ? 1 : 0));
547    }
548
549    public static final Creator<PhoneAccount> CREATOR
550            = new Creator<PhoneAccount>() {
551        @Override
552        public PhoneAccount createFromParcel(Parcel in) {
553            return new PhoneAccount(in);
554        }
555
556        @Override
557        public PhoneAccount[] newArray(int size) {
558            return new PhoneAccount[size];
559        }
560    };
561
562    private PhoneAccount(Parcel in) {
563        if (in.readInt() > 0) {
564            mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
565        } else {
566            mAccountHandle = null;
567        }
568        if (in.readInt() > 0) {
569            mAddress = Uri.CREATOR.createFromParcel(in);
570        } else {
571            mAddress = null;
572        }
573        if (in.readInt() > 0) {
574            mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
575        } else {
576            mSubscriptionAddress = null;
577        }
578        mCapabilities = in.readInt();
579        mHighlightColor = in.readInt();
580        mLabel = in.readCharSequence();
581        mShortDescription = in.readCharSequence();
582        mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
583        if (in.readInt() > 0) {
584            mIcon = Icon.CREATOR.createFromParcel(in);
585        } else {
586            mIcon = null;
587        }
588        mIsEnabled = in.readByte() == 1;
589    }
590
591    @Override
592    public String toString() {
593        StringBuilder sb = new StringBuilder().append("[[")
594                .append(mIsEnabled ? 'X' : ' ')
595                .append("] PhoneAccount: ")
596                .append(mAccountHandle)
597                .append(" Capabilities: ")
598                .append(mCapabilities)
599                .append(" Schemes: ");
600        for (String scheme : mSupportedUriSchemes) {
601            sb.append(scheme)
602                    .append(" ");
603        }
604        sb.append("]");
605        return sb.toString();
606    }
607}
608