PhoneAccount.java revision 3ace54b895c97f0e98e989667238be9c96c3b40c
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.Context;
21import android.content.pm.PackageManager;
22import android.content.res.Resources.NotFoundException;
23import android.graphics.drawable.Drawable;
24import android.net.Uri;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.text.TextUtils;
28
29import java.lang.String;
30import java.util.ArrayList;
31import java.util.Collections;
32import java.util.List;
33import 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
41public 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    /**
112     * Indicating no color is set.
113     */
114    public static final int NO_COLOR = -1;
115
116    private final PhoneAccountHandle mAccountHandle;
117    private final Uri mAddress;
118    private final Uri mSubscriptionAddress;
119    private final int mCapabilities;
120    private final int mIconResId;
121    private final int mColor;
122    private final CharSequence mLabel;
123    private final CharSequence mShortDescription;
124    private final List<String> mSupportedUriSchemes;
125
126    public static class Builder {
127        private PhoneAccountHandle mAccountHandle;
128        private Uri mAddress;
129        private Uri mSubscriptionAddress;
130        private int mCapabilities;
131        private int mIconResId;
132        private int mColor = NO_COLOR;
133        private CharSequence mLabel;
134        private CharSequence mShortDescription;
135        private List<String> mSupportedUriSchemes = new ArrayList<String>();
136
137        public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
138            this.mAccountHandle = accountHandle;
139            this.mLabel = label;
140        }
141
142        /**
143         * Creates an instance of the {@link PhoneAccount.Builder} from an existing
144         * {@link PhoneAccount}.
145         *
146         * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
147         */
148        public Builder(PhoneAccount phoneAccount) {
149            mAccountHandle = phoneAccount.getAccountHandle();
150            mAddress = phoneAccount.getAddress();
151            mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
152            mCapabilities = phoneAccount.getCapabilities();
153            mIconResId = phoneAccount.getIconResId();
154            mColor = phoneAccount.getColor();
155            mLabel = phoneAccount.getLabel();
156            mShortDescription = phoneAccount.getShortDescription();
157            mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
158        }
159
160        public Builder setAddress(Uri value) {
161            this.mAddress = value;
162            return this;
163        }
164
165        public Builder setSubscriptionAddress(Uri value) {
166            this.mSubscriptionAddress = value;
167            return this;
168        }
169
170        public Builder setCapabilities(int value) {
171            this.mCapabilities = value;
172            return this;
173        }
174
175        public Builder setIconResId(int value) {
176            this.mIconResId = value;
177            return this;
178        }
179
180        public Builder setColor(int value) {
181            this.mColor = value;
182            return this;
183        }
184
185        public Builder setShortDescription(CharSequence value) {
186            this.mShortDescription = value;
187            return this;
188        }
189
190        /**
191         * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
192         *
193         * @param uriScheme The URI scheme.
194         * @return The Builder.
195         * @hide
196         */
197        public Builder addSupportedUriScheme(String uriScheme) {
198            if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
199                this.mSupportedUriSchemes.add(uriScheme);
200            }
201            return this;
202        }
203
204        /**
205         * Specifies the URI schemes supported by the {@link PhoneAccount}.
206         *
207         * @param uriSchemes The URI schemes.
208         * @return The Builder.
209         */
210        public Builder setSupportedUriSchemes(List<String> uriSchemes) {
211            mSupportedUriSchemes.clear();
212
213            if (uriSchemes != null && !uriSchemes.isEmpty()) {
214                for (String uriScheme : uriSchemes) {
215                    addSupportedUriScheme(uriScheme);
216                }
217            }
218            return this;
219        }
220
221        /**
222         * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
223         *
224         * @return The {@link PhoneAccount}.
225         */
226        public PhoneAccount build() {
227            // If no supported URI schemes were defined, assume "tel" is supported.
228            if (mSupportedUriSchemes.isEmpty()) {
229                addSupportedUriScheme(SCHEME_TEL);
230            }
231
232            return new PhoneAccount(
233                    mAccountHandle,
234                    mAddress,
235                    mSubscriptionAddress,
236                    mCapabilities,
237                    mIconResId,
238                    mColor,
239                    mLabel,
240                    mShortDescription,
241                    mSupportedUriSchemes);
242        }
243    }
244
245    private PhoneAccount(
246            PhoneAccountHandle account,
247            Uri address,
248            Uri subscriptionAddress,
249            int capabilities,
250            int iconResId,
251            int color,
252            CharSequence label,
253            CharSequence shortDescription,
254            List<String> supportedUriSchemes) {
255        mAccountHandle = account;
256        mAddress = address;
257        mSubscriptionAddress = subscriptionAddress;
258        mCapabilities = capabilities;
259        mIconResId = iconResId;
260        mColor = color;
261        mLabel = label;
262        mShortDescription = shortDescription;
263        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
264    }
265
266    public static Builder builder(
267            PhoneAccountHandle accountHandle,
268            CharSequence label) {
269        return new Builder(accountHandle, label);
270    }
271
272    /**
273     * Returns a builder initialized with the current {@link PhoneAccount} instance.
274     *
275     * @return The builder.
276     * @hide
277     */
278    public Builder toBuilder() { return new Builder(this); }
279
280    /**
281     * The unique identifier of this {@code PhoneAccount}.
282     *
283     * @return A {@code PhoneAccountHandle}.
284     */
285    public PhoneAccountHandle getAccountHandle() {
286        return mAccountHandle;
287    }
288
289    /**
290     * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
291     * represents the destination from which outgoing calls using this {@code PhoneAccount}
292     * will appear to come, if applicable, and the destination to which incoming calls using this
293     * {@code PhoneAccount} may be addressed.
294     *
295     * @return A address expressed as a {@code Uri}, for example, a phone number.
296     */
297    public Uri getAddress() {
298        return mAddress;
299    }
300
301    /**
302     * The raw callback number used for this {@code PhoneAccount}, as distinct from
303     * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
304     * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
305     *
306     * @return The subscription number, suitable for display to the user.
307     */
308    public Uri getSubscriptionAddress() {
309        return mSubscriptionAddress;
310    }
311
312    /**
313     * The capabilities of this {@code PhoneAccount}.
314     *
315     * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
316     */
317    public int getCapabilities() {
318        return mCapabilities;
319    }
320
321    /**
322     * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
323     * bit mask.
324     *
325     * @param capability The capabilities to check.
326     * @return {@code True} if the phone account has the capability.
327     */
328    public boolean hasCapabilities(int capability) {
329        return (mCapabilities & capability) == capability;
330    }
331
332    /**
333     * A short label describing a {@code PhoneAccount}.
334     *
335     * @return A label for this {@code PhoneAccount}.
336     */
337    public CharSequence getLabel() {
338        return mLabel;
339    }
340
341    /**
342     * A short paragraph describing this {@code PhoneAccount}.
343     *
344     * @return A description for this {@code PhoneAccount}.
345     */
346    public CharSequence getShortDescription() {
347        return mShortDescription;
348    }
349
350    /**
351     * The URI schemes supported by this {@code PhoneAccount}.
352     *
353     * @return The URI schemes.
354     */
355    public List<String> getSupportedUriSchemes() {
356        return mSupportedUriSchemes;
357    }
358
359    /**
360     * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
361     * scheme.
362     *
363     * @param uriScheme The URI scheme to check.
364     * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
365     * specified URI scheme.
366     */
367    public boolean supportsUriScheme(String uriScheme) {
368        if (mSupportedUriSchemes == null || uriScheme == null) {
369            return false;
370        }
371
372        for (String scheme : mSupportedUriSchemes) {
373            if (scheme != null && scheme.equals(uriScheme)) {
374                return true;
375            }
376        }
377        return false;
378    }
379
380    /**
381     * The icon resource ID for the icon of this {@code PhoneAccount}.
382     *
383     * @return A resource ID.
384     */
385    public int getIconResId() {
386        return mIconResId;
387    }
388
389    /**
390     * A highlight color to use in displaying information about this {@code PhoneAccount}.
391     *
392     * @return A hexadecimal color value.
393     */
394    public int getColor() {
395        return mColor;
396    }
397
398    /**
399     * An icon to represent this {@code PhoneAccount} in a user interface.
400     *
401     * @return An icon for this {@code PhoneAccount}.
402     */
403    public Drawable getIcon(Context context) {
404        return getIcon(context, mIconResId);
405    }
406
407    private Drawable getIcon(Context context, int resId) {
408        Context packageContext;
409        try {
410            packageContext = context.createPackageContext(
411                    mAccountHandle.getComponentName().getPackageName(), 0);
412        } catch (PackageManager.NameNotFoundException e) {
413            Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName());
414            return null;
415        }
416        try {
417            return packageContext.getDrawable(resId);
418        } catch (NotFoundException|MissingResourceException e) {
419            Log.e(this, e, "Cannot find icon %d in package %s",
420                    resId, mAccountHandle.getComponentName().getPackageName());
421            return null;
422        }
423    }
424
425    //
426    // Parcelable implementation
427    //
428
429    @Override
430    public int describeContents() {
431        return 0;
432    }
433
434    @Override
435    public void writeToParcel(Parcel out, int flags) {
436        out.writeParcelable(mAccountHandle, 0);
437        out.writeParcelable(mAddress, 0);
438        out.writeParcelable(mSubscriptionAddress, 0);
439        out.writeInt(mCapabilities);
440        out.writeInt(mIconResId);
441        out.writeInt(mColor);
442        out.writeCharSequence(mLabel);
443        out.writeCharSequence(mShortDescription);
444        out.writeList(mSupportedUriSchemes);
445    }
446
447    public static final Creator<PhoneAccount> CREATOR
448            = new Creator<PhoneAccount>() {
449        @Override
450        public PhoneAccount createFromParcel(Parcel in) {
451            return new PhoneAccount(in);
452        }
453
454        @Override
455        public PhoneAccount[] newArray(int size) {
456            return new PhoneAccount[size];
457        }
458    };
459
460    private PhoneAccount(Parcel in) {
461        ClassLoader classLoader = PhoneAccount.class.getClassLoader();
462
463        mAccountHandle = in.readParcelable(getClass().getClassLoader());
464        mAddress = in.readParcelable(getClass().getClassLoader());
465        mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
466        mCapabilities = in.readInt();
467        mIconResId = in.readInt();
468        mColor = in.readInt();
469        mLabel = in.readCharSequence();
470        mShortDescription = in.readCharSequence();
471
472        List<String> supportedUriSchemes = new ArrayList<>();
473        in.readList(supportedUriSchemes, classLoader);
474        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
475    }
476}
477