PhoneAccount.java revision 711d876fd110b33519afb5d05f5a740ade635787
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 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     * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
290     * has been used to alter the callback number.
291     * <p>
292     *
293     * @return The subscription number, suitable for display to the user.
294     */
295    public Uri getSubscriptionAddress() {
296        return mSubscriptionAddress;
297    }
298
299    /**
300     * The capabilities of this {@code PhoneAccount}.
301     *
302     * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
303     */
304    public int getCapabilities() {
305        return mCapabilities;
306    }
307
308    /**
309     * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
310     * bit mask.
311     *
312     * @param capability The capabilities to check.
313     * @return {@code True} if the phone account has the capability.
314     */
315    public boolean hasCapabilities(int capability) {
316        return (mCapabilities & capability) == capability;
317    }
318
319    /**
320     * A short label describing a {@code PhoneAccount}.
321     *
322     * @return A label for this {@code PhoneAccount}.
323     */
324    public CharSequence getLabel() {
325        return mLabel;
326    }
327
328    /**
329     * A short paragraph describing this {@code PhoneAccount}.
330     *
331     * @return A description for this {@code PhoneAccount}.
332     */
333    public CharSequence getShortDescription() {
334        return mShortDescription;
335    }
336
337    /**
338     * The URI schemes supported by this {@code PhoneAccount}.
339     *
340     * @return The URI schemes.
341     */
342    public List<String> getSupportedUriSchemes() {
343        return mSupportedUriSchemes;
344    }
345
346    /**
347     * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
348     * scheme.
349     *
350     * @param uriScheme The URI scheme to check.
351     * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
352     * specified URI scheme.
353     */
354    public boolean supportsUriScheme(String uriScheme) {
355        if (mSupportedUriSchemes == null || uriScheme == null) {
356            return false;
357        }
358
359        for (String scheme : mSupportedUriSchemes) {
360            if (scheme != null && scheme.equals(uriScheme)) {
361                return true;
362            }
363        }
364        return false;
365    }
366
367    /**
368     * The icon resource ID for the icon of this {@code PhoneAccount}.
369     *
370     * @return A resource ID.
371     */
372    public int getIconResId() {
373        return mIconResId;
374    }
375
376    /**
377     * An icon to represent this {@code PhoneAccount} in a user interface.
378     *
379     * @return An icon for this {@code PhoneAccount}.
380     */
381    public Drawable getIcon(Context context) {
382        return getIcon(context, mIconResId);
383    }
384
385    private Drawable getIcon(Context context, int resId) {
386        Context packageContext;
387        try {
388            packageContext = context.createPackageContext(
389                    mAccountHandle.getComponentName().getPackageName(), 0);
390        } catch (PackageManager.NameNotFoundException e) {
391            Log.w(this, "Cannot find package %s", mAccountHandle.getComponentName().getPackageName());
392            return null;
393        }
394        try {
395            return packageContext.getDrawable(resId);
396        } catch (NotFoundException|MissingResourceException e) {
397            Log.e(this, e, "Cannot find icon %d in package %s",
398                    resId, mAccountHandle.getComponentName().getPackageName());
399            return null;
400        }
401    }
402
403    //
404    // Parcelable implementation
405    //
406
407    @Override
408    public int describeContents() {
409        return 0;
410    }
411
412    @Override
413    public void writeToParcel(Parcel out, int flags) {
414        out.writeParcelable(mAccountHandle, 0);
415        out.writeParcelable(mAddress, 0);
416        out.writeParcelable(mSubscriptionAddress, 0);
417        out.writeInt(mCapabilities);
418        out.writeInt(mIconResId);
419        out.writeCharSequence(mLabel);
420        out.writeCharSequence(mShortDescription);
421        out.writeList(mSupportedUriSchemes);
422    }
423
424    public static final Creator<PhoneAccount> CREATOR
425            = new Creator<PhoneAccount>() {
426        @Override
427        public PhoneAccount createFromParcel(Parcel in) {
428            return new PhoneAccount(in);
429        }
430
431        @Override
432        public PhoneAccount[] newArray(int size) {
433            return new PhoneAccount[size];
434        }
435    };
436
437    private PhoneAccount(Parcel in) {
438        ClassLoader classLoader = PhoneAccount.class.getClassLoader();
439
440        mAccountHandle = in.readParcelable(getClass().getClassLoader());
441        mAddress = in.readParcelable(getClass().getClassLoader());
442        mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
443        mCapabilities = in.readInt();
444        mIconResId = in.readInt();
445        mLabel = in.readCharSequence();
446        mShortDescription = in.readCharSequence();
447
448        List<String> supportedUriSchemes = new ArrayList<>();
449        in.readList(supportedUriSchemes, classLoader);
450        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
451    }
452}
453