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