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.graphics.drawable.Icon;
21import android.net.Uri;
22import android.os.Bundle;
23import android.os.Parcel;
24import android.os.Parcelable;
25import android.text.TextUtils;
26
27import java.lang.String;
28import java.util.ArrayList;
29import java.util.Collections;
30import java.util.List;
31
32/**
33 * Represents a distinct method to place or receive a phone call. Apps which can place calls and
34 * want those calls to be integrated into the dialer and in-call UI should build an instance of
35 * this class and register it with the system using {@link TelecomManager}.
36 * <p>
37 * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
38 * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
39 * should supply a valid {@link PhoneAccountHandle} that references the connection service
40 * implementation Telecom will use to interact with the app.
41 */
42public final class PhoneAccount implements Parcelable {
43
44    /**
45     * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
46     * maximum permitted length of a call subject specified via the
47     * {@link TelecomManager#EXTRA_CALL_SUBJECT} extra on an
48     * {@link android.content.Intent#ACTION_CALL} intent.  Ultimately a {@link ConnectionService} is
49     * responsible for enforcing the maximum call subject length when sending the message, however
50     * this extra is provided so that the user interface can proactively limit the length of the
51     * call subject as the user types it.
52     */
53    public static final String EXTRA_CALL_SUBJECT_MAX_LENGTH =
54            "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
55
56    /**
57     * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
58     * character encoding to be used when determining the length of messages.
59     * The user interface can use this when determining the number of characters the user may type
60     * in a call subject.  If empty-string, the call subject message size limit will be enforced on
61     * a 1:1 basis.  That is, each character will count towards the messages size limit as a single
62     * character.  If a character encoding is specified, the message size limit will be based on the
63     * number of bytes in the message per the specified encoding.  See
64     * {@link #EXTRA_CALL_SUBJECT_MAX_LENGTH} for more information on the call subject maximum
65     * length.
66     */
67    public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING =
68            "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
69
70    /**
71     * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
72     * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
73     * will be allowed to manage phone calls including using its own proprietary phone-call
74     * implementation (like VoIP calling) to make calls instead of the telephony stack.
75     * <p>
76     * When a user opts to place a call using the SIM-based telephony stack, the
77     * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
78     * if the user has explicitly selected it to be used as the default connection manager.
79     * <p>
80     * See {@link #getCapabilities}
81     */
82    public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
83
84    /**
85     * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
86     * traditional SIM-based telephony calls. This account will be treated as a distinct method
87     * for placing calls alongside the traditional SIM-based telephony stack. This flag is
88     * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
89     * or place calls from the built-in telephony stack.
90     * <p>
91     * See {@link #getCapabilities}
92     * <p>
93     */
94    public static final int CAPABILITY_CALL_PROVIDER = 0x2;
95
96    /**
97     * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
98     * subscription.
99     * <p>
100     * Only the Android framework can register a {@code PhoneAccount} having this capability.
101     * <p>
102     * See {@link #getCapabilities}
103     */
104    public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
105
106    /**
107     * Flag indicating that this {@code PhoneAccount} is currently able to place video calls.
108     * <p>
109     * See also {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING} which indicates whether the
110     * {@code PhoneAccount} supports placing video calls.
111     * <p>
112     * See {@link #getCapabilities}
113     */
114    public static final int CAPABILITY_VIDEO_CALLING = 0x8;
115
116    /**
117     * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
118     * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
119     * <p>
120     * See {@link #getCapabilities}
121     */
122    public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
123
124    /**
125     * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
126     * should only be used by system apps (and will be ignored for all other apps trying to use it).
127     * <p>
128     * See {@link #getCapabilities}
129     * @hide
130     */
131    @SystemApi
132    public static final int CAPABILITY_MULTI_USER = 0x20;
133
134    /**
135     * Flag indicating that this {@code PhoneAccount} supports a subject for Calls.  This means a
136     * caller is able to specify a short subject line for an outgoing call.  A capable receiving
137     * device displays the call subject on the incoming call screen.
138     * <p>
139     * See {@link #getCapabilities}
140     */
141    public static final int CAPABILITY_CALL_SUBJECT = 0x40;
142
143    /**
144     * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
145     * <p>
146     * See {@link #getCapabilities}
147     * @hide
148     */
149    public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
150
151    /**
152     * Flag indicating that for this {@code PhoneAccount}, the ability to make a video call to a
153     * number relies on presence.  Should only be set if the {@code PhoneAccount} also has
154     * {@link #CAPABILITY_VIDEO_CALLING}.
155     * <p>
156     * When set, the {@link ConnectionService} is responsible for toggling the
157     * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the
158     * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether
159     * a contact's phone number supports video calling.
160     * <p>
161     * See {@link #getCapabilities}
162     */
163    public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100;
164
165    /**
166     * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed.
167     * <p>
168     * When set, Telecom will allow emergency video calls to be placed.  When not set, Telecom will
169     * convert all outgoing video calls to emergency numbers to audio-only.
170     * @hide
171     */
172    public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
173
174    /**
175     * Flag indicating that this {@link PhoneAccount} supports video calling.
176     * This is not an indication that the {@link PhoneAccount} is currently able to make a video
177     * call, but rather that it has the ability to make video calls (but not necessarily at this
178     * time).
179     * <p>
180     * Whether a {@link PhoneAccount} can make a video call is ultimately controlled by
181     * {@link #CAPABILITY_VIDEO_CALLING}, which indicates whether the {@link PhoneAccount} is
182     * currently capable of making a video call.  Consider a case where, for example, a
183     * {@link PhoneAccount} supports making video calls (e.g.
184     * {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}), but a current lack of network connectivity
185     * prevents video calls from being made (e.g. {@link #CAPABILITY_VIDEO_CALLING}).
186     * <p>
187     * See {@link #getCapabilities}
188     */
189    public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400;
190
191    /**
192     * Flag indicating that this {@link PhoneAccount} is responsible for managing its own
193     * {@link Connection}s.  This type of {@link PhoneAccount} is ideal for use with standalone
194     * calling apps which do not wish to use the default phone app for {@link Connection} UX,
195     * but which want to leverage the call and audio routing capabilities of the Telecom framework.
196     * <p>
197     * When set, {@link Connection}s created by the self-managed {@link ConnectionService} will not
198     * be surfaced to implementations of the {@link InCallService} API.  Thus it is the
199     * responsibility of a self-managed {@link ConnectionService} to provide a user interface for
200     * its {@link Connection}s.
201     * <p>
202     * Self-managed {@link Connection}s will, however, be displayed on connected Bluetooth devices.
203     */
204    public static final int CAPABILITY_SELF_MANAGED = 0x800;
205
206    /**
207     * Flag indicating that this {@link PhoneAccount} is capable of making a call with an
208     * RTT (Real-time text) session.
209     * When set, Telecom will attempt to open an RTT session on outgoing calls that specify
210     * that they should be placed with an RTT session , and the in-call app will be displayed
211     * with text entry fields for RTT. Likewise, the in-call app can request that an RTT
212     * session be opened during a call if this bit is set.
213     */
214    public static final int CAPABILITY_RTT = 0x1000;
215
216    /* NEXT CAPABILITY: 0x2000 */
217
218    /**
219     * URI scheme for telephone number URIs.
220     */
221    public static final String SCHEME_TEL = "tel";
222
223    /**
224     * URI scheme for voicemail URIs.
225     */
226    public static final String SCHEME_VOICEMAIL = "voicemail";
227
228    /**
229     * URI scheme for SIP URIs.
230     */
231    public static final String SCHEME_SIP = "sip";
232
233    /**
234     * Indicating no icon tint is set.
235     * @hide
236     */
237    public static final int NO_ICON_TINT = 0;
238
239    /**
240     * Indicating no hightlight color is set.
241     */
242    public static final int NO_HIGHLIGHT_COLOR = 0;
243
244    /**
245     * Indicating no resource ID is set.
246     */
247    public static final int NO_RESOURCE_ID = -1;
248
249    private final PhoneAccountHandle mAccountHandle;
250    private final Uri mAddress;
251    private final Uri mSubscriptionAddress;
252    private final int mCapabilities;
253    private final int mHighlightColor;
254    private final CharSequence mLabel;
255    private final CharSequence mShortDescription;
256    private final List<String> mSupportedUriSchemes;
257    private final int mSupportedAudioRoutes;
258    private final Icon mIcon;
259    private final Bundle mExtras;
260    private boolean mIsEnabled;
261    private String mGroupId;
262
263    /**
264     * Helper class for creating a {@link PhoneAccount}.
265     */
266    public static class Builder {
267
268        private PhoneAccountHandle mAccountHandle;
269        private Uri mAddress;
270        private Uri mSubscriptionAddress;
271        private int mCapabilities;
272        private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
273        private int mHighlightColor = NO_HIGHLIGHT_COLOR;
274        private CharSequence mLabel;
275        private CharSequence mShortDescription;
276        private List<String> mSupportedUriSchemes = new ArrayList<String>();
277        private Icon mIcon;
278        private Bundle mExtras;
279        private boolean mIsEnabled = false;
280        private String mGroupId = "";
281
282        /**
283         * Creates a builder with the specified {@link PhoneAccountHandle} and label.
284         */
285        public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
286            this.mAccountHandle = accountHandle;
287            this.mLabel = label;
288        }
289
290        /**
291         * Creates an instance of the {@link PhoneAccount.Builder} from an existing
292         * {@link PhoneAccount}.
293         *
294         * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
295         */
296        public Builder(PhoneAccount phoneAccount) {
297            mAccountHandle = phoneAccount.getAccountHandle();
298            mAddress = phoneAccount.getAddress();
299            mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
300            mCapabilities = phoneAccount.getCapabilities();
301            mHighlightColor = phoneAccount.getHighlightColor();
302            mLabel = phoneAccount.getLabel();
303            mShortDescription = phoneAccount.getShortDescription();
304            mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
305            mIcon = phoneAccount.getIcon();
306            mIsEnabled = phoneAccount.isEnabled();
307            mExtras = phoneAccount.getExtras();
308            mGroupId = phoneAccount.getGroupId();
309            mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
310        }
311
312        /**
313         * Sets the label. See {@link PhoneAccount#getLabel()}.
314         *
315         * @param label The label of the phone account.
316         * @return The builder.
317         * @hide
318         */
319        public Builder setLabel(CharSequence label) {
320            this.mLabel = label;
321            return this;
322        }
323
324        /**
325         * Sets the address. See {@link PhoneAccount#getAddress}.
326         *
327         * @param value The address of the phone account.
328         * @return The builder.
329         */
330        public Builder setAddress(Uri value) {
331            this.mAddress = value;
332            return this;
333        }
334
335        /**
336         * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
337         *
338         * @param value The subscription address.
339         * @return The builder.
340         */
341        public Builder setSubscriptionAddress(Uri value) {
342            this.mSubscriptionAddress = value;
343            return this;
344        }
345
346        /**
347         * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
348         *
349         * @param value The capabilities to set.
350         * @return The builder.
351         */
352        public Builder setCapabilities(int value) {
353            this.mCapabilities = value;
354            return this;
355        }
356
357        /**
358         * Sets the icon. See {@link PhoneAccount#getIcon}.
359         *
360         * @param icon The icon to set.
361         */
362        public Builder setIcon(Icon icon) {
363            mIcon = icon;
364            return this;
365        }
366
367        /**
368         * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
369         *
370         * @param value The highlight color.
371         * @return The builder.
372         */
373        public Builder setHighlightColor(int value) {
374            this.mHighlightColor = value;
375            return this;
376        }
377
378        /**
379         * Sets the short description. See {@link PhoneAccount#getShortDescription}.
380         *
381         * @param value The short description.
382         * @return The builder.
383         */
384        public Builder setShortDescription(CharSequence value) {
385            this.mShortDescription = value;
386            return this;
387        }
388
389        /**
390         * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
391         *
392         * @param uriScheme The URI scheme.
393         * @return The builder.
394         */
395        public Builder addSupportedUriScheme(String uriScheme) {
396            if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
397                this.mSupportedUriSchemes.add(uriScheme);
398            }
399            return this;
400        }
401
402        /**
403         * Specifies the URI schemes supported by the {@link PhoneAccount}.
404         *
405         * @param uriSchemes The URI schemes.
406         * @return The builder.
407         */
408        public Builder setSupportedUriSchemes(List<String> uriSchemes) {
409            mSupportedUriSchemes.clear();
410
411            if (uriSchemes != null && !uriSchemes.isEmpty()) {
412                for (String uriScheme : uriSchemes) {
413                    addSupportedUriScheme(uriScheme);
414                }
415            }
416            return this;
417        }
418
419        /**
420         * Specifies the extras associated with the {@link PhoneAccount}.
421         * <p>
422         * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer},
423         * and {@link Boolean}.  Extras which are not of these types are ignored.
424         *
425         * @param extras
426         * @return
427         */
428        public Builder setExtras(Bundle extras) {
429            mExtras = extras;
430            return this;
431        }
432
433        /**
434         * Sets the enabled state of the phone account.
435         *
436         * @param isEnabled The enabled state.
437         * @return The builder.
438         * @hide
439         */
440        public Builder setIsEnabled(boolean isEnabled) {
441            mIsEnabled = isEnabled;
442            return this;
443        }
444
445        /**
446         * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is
447         * registered to Telecom, it will replace another {@link PhoneAccount} that is already
448         * registered in Telecom and take on the current user defaults and enabled status. There can
449         * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a
450         * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only
451         * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced.
452         * @param groupId The group Id of the {@link PhoneAccount} that will replace any other
453         * registered {@link PhoneAccount} in Telecom with the same Group Id.
454         * @return The builder
455         * @hide
456         */
457        public Builder setGroupId(String groupId) {
458            if (groupId != null) {
459                mGroupId = groupId;
460            } else {
461                mGroupId = "";
462            }
463            return this;
464        }
465
466        /**
467         * Sets the audio routes supported by this {@link PhoneAccount}.
468         *
469         * @param routes bit mask of available routes.
470         * @return The builder.
471         * @hide
472         */
473        public Builder setSupportedAudioRoutes(int routes) {
474            mSupportedAudioRoutes = routes;
475            return this;
476        }
477
478        /**
479         * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
480         *
481         * @return The {@link PhoneAccount}.
482         */
483        public PhoneAccount build() {
484            // If no supported URI schemes were defined, assume "tel" is supported.
485            if (mSupportedUriSchemes.isEmpty()) {
486                addSupportedUriScheme(SCHEME_TEL);
487            }
488
489            return new PhoneAccount(
490                    mAccountHandle,
491                    mAddress,
492                    mSubscriptionAddress,
493                    mCapabilities,
494                    mIcon,
495                    mHighlightColor,
496                    mLabel,
497                    mShortDescription,
498                    mSupportedUriSchemes,
499                    mExtras,
500                    mSupportedAudioRoutes,
501                    mIsEnabled,
502                    mGroupId);
503        }
504    }
505
506    private PhoneAccount(
507            PhoneAccountHandle account,
508            Uri address,
509            Uri subscriptionAddress,
510            int capabilities,
511            Icon icon,
512            int highlightColor,
513            CharSequence label,
514            CharSequence shortDescription,
515            List<String> supportedUriSchemes,
516            Bundle extras,
517            int supportedAudioRoutes,
518            boolean isEnabled,
519            String groupId) {
520        mAccountHandle = account;
521        mAddress = address;
522        mSubscriptionAddress = subscriptionAddress;
523        mCapabilities = capabilities;
524        mIcon = icon;
525        mHighlightColor = highlightColor;
526        mLabel = label;
527        mShortDescription = shortDescription;
528        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
529        mExtras = extras;
530        mSupportedAudioRoutes = supportedAudioRoutes;
531        mIsEnabled = isEnabled;
532        mGroupId = groupId;
533    }
534
535    public static Builder builder(
536            PhoneAccountHandle accountHandle,
537            CharSequence label) {
538        return new Builder(accountHandle, label);
539    }
540
541    /**
542     * Returns a builder initialized with the current {@link PhoneAccount} instance.
543     *
544     * @return The builder.
545     */
546    public Builder toBuilder() { return new Builder(this); }
547
548    /**
549     * The unique identifier of this {@code PhoneAccount}.
550     *
551     * @return A {@code PhoneAccountHandle}.
552     */
553    public PhoneAccountHandle getAccountHandle() {
554        return mAccountHandle;
555    }
556
557    /**
558     * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
559     * represents the destination from which outgoing calls using this {@code PhoneAccount}
560     * will appear to come, if applicable, and the destination to which incoming calls using this
561     * {@code PhoneAccount} may be addressed.
562     *
563     * @return A address expressed as a {@code Uri}, for example, a phone number.
564     */
565    public Uri getAddress() {
566        return mAddress;
567    }
568
569    /**
570     * The raw callback number used for this {@code PhoneAccount}, as distinct from
571     * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
572     * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
573     * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
574     * has been used to alter the callback number.
575     * <p>
576     *
577     * @return The subscription number, suitable for display to the user.
578     */
579    public Uri getSubscriptionAddress() {
580        return mSubscriptionAddress;
581    }
582
583    /**
584     * The capabilities of this {@code PhoneAccount}.
585     *
586     * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
587     */
588    public int getCapabilities() {
589        return mCapabilities;
590    }
591
592    /**
593     * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
594     * bit mask.
595     *
596     * @param capability The capabilities to check.
597     * @return {@code true} if the phone account has the capability.
598     */
599    public boolean hasCapabilities(int capability) {
600        return (mCapabilities & capability) == capability;
601    }
602
603    /**
604     * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask.
605     *
606     * @param route The routes to check.
607     * @return {@code true} if the phone account has the routes.
608     * @hide
609     */
610    public boolean hasAudioRoutes(int routes) {
611        return (mSupportedAudioRoutes & routes) == routes;
612    }
613
614    /**
615     * A short label describing a {@code PhoneAccount}.
616     *
617     * @return A label for this {@code PhoneAccount}.
618     */
619    public CharSequence getLabel() {
620        return mLabel;
621    }
622
623    /**
624     * A short paragraph describing this {@code PhoneAccount}.
625     *
626     * @return A description for this {@code PhoneAccount}.
627     */
628    public CharSequence getShortDescription() {
629        return mShortDescription;
630    }
631
632    /**
633     * The URI schemes supported by this {@code PhoneAccount}.
634     *
635     * @return The URI schemes.
636     */
637    public List<String> getSupportedUriSchemes() {
638        return mSupportedUriSchemes;
639    }
640
641    /**
642     * The extras associated with this {@code PhoneAccount}.
643     * <p>
644     * A {@link ConnectionService} may provide implementation specific information about the
645     * {@link PhoneAccount} via the extras.
646     *
647     * @return The extras.
648     */
649    public Bundle getExtras() {
650        return mExtras;
651    }
652
653    /**
654     * The audio routes supported by this {@code PhoneAccount}.
655     *
656     * @hide
657     */
658    public int getSupportedAudioRoutes() {
659        return mSupportedAudioRoutes;
660    }
661
662    /**
663     * The icon to represent this {@code PhoneAccount}.
664     *
665     * @return The icon.
666     */
667    public Icon getIcon() {
668        return mIcon;
669    }
670
671    /**
672     * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
673     * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
674     *
675     * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
676     */
677    public boolean isEnabled() {
678        return mIsEnabled;
679    }
680
681    /**
682     * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an
683     * empty {@link String} if the {@link PhoneAccount} is not in a group. If this
684     * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered
685     * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced,
686     * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}.
687     * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced.
688     *
689     * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group.
690     * @hide
691     */
692    public String getGroupId() {
693        return mGroupId;
694    }
695
696    /**
697     * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
698     * scheme.
699     *
700     * @param uriScheme The URI scheme to check.
701     * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
702     * specified URI scheme.
703     */
704    public boolean supportsUriScheme(String uriScheme) {
705        if (mSupportedUriSchemes == null || uriScheme == null) {
706            return false;
707        }
708
709        for (String scheme : mSupportedUriSchemes) {
710            if (scheme != null && scheme.equals(uriScheme)) {
711                return true;
712            }
713        }
714        return false;
715    }
716
717    /**
718     * A highlight color to use in displaying information about this {@code PhoneAccount}.
719     *
720     * @return A hexadecimal color value.
721     */
722    public int getHighlightColor() {
723        return mHighlightColor;
724    }
725
726    /**
727     * Sets the enabled state of the phone account.
728     * @hide
729     */
730    public void setIsEnabled(boolean isEnabled) {
731        mIsEnabled = isEnabled;
732    }
733
734    /**
735     * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise.
736     * @hide
737     */
738    public boolean isSelfManaged() {
739        return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED;
740    }
741
742    //
743    // Parcelable implementation
744    //
745
746    @Override
747    public int describeContents() {
748        return 0;
749    }
750
751    @Override
752    public void writeToParcel(Parcel out, int flags) {
753        if (mAccountHandle == null) {
754            out.writeInt(0);
755        } else {
756            out.writeInt(1);
757            mAccountHandle.writeToParcel(out, flags);
758        }
759        if (mAddress == null) {
760            out.writeInt(0);
761        } else {
762            out.writeInt(1);
763            mAddress.writeToParcel(out, flags);
764        }
765        if (mSubscriptionAddress == null) {
766            out.writeInt(0);
767        } else {
768            out.writeInt(1);
769            mSubscriptionAddress.writeToParcel(out, flags);
770        }
771        out.writeInt(mCapabilities);
772        out.writeInt(mHighlightColor);
773        out.writeCharSequence(mLabel);
774        out.writeCharSequence(mShortDescription);
775        out.writeStringList(mSupportedUriSchemes);
776
777        if (mIcon == null) {
778            out.writeInt(0);
779        } else {
780            out.writeInt(1);
781            mIcon.writeToParcel(out, flags);
782        }
783        out.writeByte((byte) (mIsEnabled ? 1 : 0));
784        out.writeBundle(mExtras);
785        out.writeString(mGroupId);
786        out.writeInt(mSupportedAudioRoutes);
787    }
788
789    public static final Creator<PhoneAccount> CREATOR
790            = new Creator<PhoneAccount>() {
791        @Override
792        public PhoneAccount createFromParcel(Parcel in) {
793            return new PhoneAccount(in);
794        }
795
796        @Override
797        public PhoneAccount[] newArray(int size) {
798            return new PhoneAccount[size];
799        }
800    };
801
802    private PhoneAccount(Parcel in) {
803        if (in.readInt() > 0) {
804            mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
805        } else {
806            mAccountHandle = null;
807        }
808        if (in.readInt() > 0) {
809            mAddress = Uri.CREATOR.createFromParcel(in);
810        } else {
811            mAddress = null;
812        }
813        if (in.readInt() > 0) {
814            mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
815        } else {
816            mSubscriptionAddress = null;
817        }
818        mCapabilities = in.readInt();
819        mHighlightColor = in.readInt();
820        mLabel = in.readCharSequence();
821        mShortDescription = in.readCharSequence();
822        mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
823        if (in.readInt() > 0) {
824            mIcon = Icon.CREATOR.createFromParcel(in);
825        } else {
826            mIcon = null;
827        }
828        mIsEnabled = in.readByte() == 1;
829        mExtras = in.readBundle();
830        mGroupId = in.readString();
831        mSupportedAudioRoutes = in.readInt();
832    }
833
834    @Override
835    public String toString() {
836        StringBuilder sb = new StringBuilder().append("[[")
837                .append(mIsEnabled ? 'X' : ' ')
838                .append("] PhoneAccount: ")
839                .append(mAccountHandle)
840                .append(" Capabilities: ")
841                .append(capabilitiesToString())
842                .append(" Audio Routes: ")
843                .append(audioRoutesToString())
844                .append(" Schemes: ");
845        for (String scheme : mSupportedUriSchemes) {
846            sb.append(scheme)
847                    .append(" ");
848        }
849        sb.append(" Extras: ");
850        sb.append(mExtras);
851        sb.append(" GroupId: ");
852        sb.append(Log.pii(mGroupId));
853        sb.append("]");
854        return sb.toString();
855    }
856
857    /**
858     * Generates a string representation of a capabilities bitmask.
859     *
860     * @param capabilities The capabilities bitmask.
861     * @return String representation of the capabilities bitmask.
862     */
863    private String capabilitiesToString() {
864        StringBuilder sb = new StringBuilder();
865        if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
866            sb.append("SelfManaged ");
867        }
868        if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
869            sb.append("SuppVideo ");
870        }
871        if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
872            sb.append("Video ");
873        }
874        if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
875            sb.append("Presence ");
876        }
877        if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) {
878            sb.append("CallProvider ");
879        }
880        if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) {
881            sb.append("CallSubject ");
882        }
883        if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) {
884            sb.append("ConnectionMgr ");
885        }
886        if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) {
887            sb.append("EmergOnly ");
888        }
889        if (hasCapabilities(CAPABILITY_MULTI_USER)) {
890            sb.append("MultiUser ");
891        }
892        if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
893            sb.append("PlaceEmerg ");
894        }
895        if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
896            sb.append("EmergVideo ");
897        }
898        if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
899            sb.append("SimSub ");
900        }
901        return sb.toString();
902    }
903
904    private String audioRoutesToString() {
905        StringBuilder sb = new StringBuilder();
906
907        if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) {
908            sb.append("B");
909        }
910        if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) {
911            sb.append("E");
912        }
913        if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) {
914            sb.append("S");
915        }
916        if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) {
917            sb.append("W");
918        }
919
920        return sb.toString();
921    }
922}
923