• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.telecom;
18 
19 import android.annotation.SystemApi;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.pm.PackageManager;
23 import android.content.res.Resources.NotFoundException;
24 import android.graphics.Bitmap;
25 import android.graphics.Color;
26 import android.graphics.drawable.BitmapDrawable;
27 import android.graphics.drawable.ColorDrawable;
28 import android.graphics.drawable.Drawable;
29 import android.graphics.drawable.Icon;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.os.Parcel;
33 import android.os.Parcelable;
34 import android.text.TextUtils;
35 
36 import java.lang.String;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.MissingResourceException;
41 
42 /**
43  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
44  * want those calls to be integrated into the dialer and in-call UI should build an instance of
45  * this class and register it with the system using {@link TelecomManager}.
46  * <p>
47  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
48  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
49  * should supply a valid {@link PhoneAccountHandle} that references the connection service
50  * implementation Telecom will use to interact with the app.
51  */
52 public final class PhoneAccount implements Parcelable {
53 
54     /**
55      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
56      * maximum permitted length of a call subject specified via the
57      * {@link TelecomManager#EXTRA_CALL_SUBJECT} extra on an
58      * {@link android.content.Intent#ACTION_CALL} intent.  Ultimately a {@link ConnectionService} is
59      * responsible for enforcing the maximum call subject length when sending the message, however
60      * this extra is provided so that the user interface can proactively limit the length of the
61      * call subject as the user types it.
62      */
63     public static final String EXTRA_CALL_SUBJECT_MAX_LENGTH =
64             "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH";
65 
66     /**
67      * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the
68      * character encoding to be used when determining the length of messages.
69      * The user interface can use this when determining the number of characters the user may type
70      * in a call subject.  If empty-string, the call subject message size limit will be enforced on
71      * a 1:1 basis.  That is, each character will count towards the messages size limit as a single
72      * character.  If a character encoding is specified, the message size limit will be based on the
73      * number of bytes in the message per the specified encoding.  See
74      * {@link #EXTRA_CALL_SUBJECT_MAX_LENGTH} for more information on the call subject maximum
75      * length.
76      */
77     public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING =
78             "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING";
79 
80     /**
81      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
82      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
83      * will be allowed to manage phone calls including using its own proprietary phone-call
84      * implementation (like VoIP calling) to make calls instead of the telephony stack.
85      * <p>
86      * When a user opts to place a call using the SIM-based telephony stack, the
87      * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first
88      * if the user has explicitly selected it to be used as the default connection manager.
89      * <p>
90      * See {@link #getCapabilities}
91      */
92     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
93 
94     /**
95      * Flag indicating that this {@code PhoneAccount} can make phone calls in place of
96      * traditional SIM-based telephony calls. This account will be treated as a distinct method
97      * for placing calls alongside the traditional SIM-based telephony stack. This flag is
98      * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage
99      * or place calls from the built-in telephony stack.
100      * <p>
101      * See {@link #getCapabilities}
102      * <p>
103      */
104     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
105 
106     /**
107      * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM
108      * subscription.
109      * <p>
110      * Only the Android framework can register a {@code PhoneAccount} having this capability.
111      * <p>
112      * See {@link #getCapabilities}
113      */
114     public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
115 
116     /**
117      * Flag indicating that this {@code PhoneAccount} is capable of placing video calls.
118      * <p>
119      * See {@link #getCapabilities}
120      */
121     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
122 
123     /**
124      * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls.
125      * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls.
126      * <p>
127      * See {@link #getCapabilities}
128      */
129     public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10;
130 
131     /**
132      * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This
133      * should only be used by system apps (and will be ignored for all other apps trying to use it).
134      * <p>
135      * See {@link #getCapabilities}
136      * @hide
137      */
138     @SystemApi
139     public static final int CAPABILITY_MULTI_USER = 0x20;
140 
141     /**
142      * Flag indicating that this {@code PhoneAccount} supports a subject for Calls.  This means a
143      * caller is able to specify a short subject line for an outgoing call.  A capable receiving
144      * device displays the call subject on the incoming call screen.
145      * <p>
146      * See {@link #getCapabilities}
147      */
148     public static final int CAPABILITY_CALL_SUBJECT = 0x40;
149 
150     /**
151      * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
152      * <p>
153      * See {@link #getCapabilities}
154      * @hide
155      */
156     public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
157 
158     /**
159      * Flag indicating that for this {@code PhoneAccount}, the ability to make a video call to a
160      * number relies on presence.  Should only be set if the {@code PhoneAccount} also has
161      * {@link #CAPABILITY_VIDEO_CALLING}.
162      * <p>
163      * When set, the {@link ConnectionService} is responsible for toggling the
164      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the
165      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether
166      * a contact's phone number supports video calling.
167      * <p>
168      * See {@link #getCapabilities}
169      */
170     public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100;
171 
172     /**
173      * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed.
174      * <p>
175      * When set, Telecom will allow emergency video calls to be placed.  When not set, Telecom will
176      * convert all outgoing video calls to emergency numbers to audio-only.
177      * @hide
178      */
179     public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
180 
181     /**
182      * URI scheme for telephone number URIs.
183      */
184     public static final String SCHEME_TEL = "tel";
185 
186     /**
187      * URI scheme for voicemail URIs.
188      */
189     public static final String SCHEME_VOICEMAIL = "voicemail";
190 
191     /**
192      * URI scheme for SIP URIs.
193      */
194     public static final String SCHEME_SIP = "sip";
195 
196     /**
197      * Indicating no icon tint is set.
198      * @hide
199      */
200     public static final int NO_ICON_TINT = 0;
201 
202     /**
203      * Indicating no hightlight color is set.
204      */
205     public static final int NO_HIGHLIGHT_COLOR = 0;
206 
207     /**
208      * Indicating no resource ID is set.
209      */
210     public static final int NO_RESOURCE_ID = -1;
211 
212     private final PhoneAccountHandle mAccountHandle;
213     private final Uri mAddress;
214     private final Uri mSubscriptionAddress;
215     private final int mCapabilities;
216     private final int mHighlightColor;
217     private final CharSequence mLabel;
218     private final CharSequence mShortDescription;
219     private final List<String> mSupportedUriSchemes;
220     private final Icon mIcon;
221     private final Bundle mExtras;
222     private boolean mIsEnabled;
223 
224     /**
225      * Helper class for creating a {@link PhoneAccount}.
226      */
227     public static class Builder {
228         private PhoneAccountHandle mAccountHandle;
229         private Uri mAddress;
230         private Uri mSubscriptionAddress;
231         private int mCapabilities;
232         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
233         private CharSequence mLabel;
234         private CharSequence mShortDescription;
235         private List<String> mSupportedUriSchemes = new ArrayList<String>();
236         private Icon mIcon;
237         private Bundle mExtras;
238         private boolean mIsEnabled = false;
239 
240         /**
241          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
242          */
Builder(PhoneAccountHandle accountHandle, CharSequence label)243         public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
244             this.mAccountHandle = accountHandle;
245             this.mLabel = label;
246         }
247 
248         /**
249          * Creates an instance of the {@link PhoneAccount.Builder} from an existing
250          * {@link PhoneAccount}.
251          *
252          * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
253          */
Builder(PhoneAccount phoneAccount)254         public Builder(PhoneAccount phoneAccount) {
255             mAccountHandle = phoneAccount.getAccountHandle();
256             mAddress = phoneAccount.getAddress();
257             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
258             mCapabilities = phoneAccount.getCapabilities();
259             mHighlightColor = phoneAccount.getHighlightColor();
260             mLabel = phoneAccount.getLabel();
261             mShortDescription = phoneAccount.getShortDescription();
262             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
263             mIcon = phoneAccount.getIcon();
264             mIsEnabled = phoneAccount.isEnabled();
265             mExtras = phoneAccount.getExtras();
266         }
267 
268         /**
269          * Sets the address. See {@link PhoneAccount#getAddress}.
270          *
271          * @param value The address of the phone account.
272          * @return The builder.
273          */
setAddress(Uri value)274         public Builder setAddress(Uri value) {
275             this.mAddress = value;
276             return this;
277         }
278 
279         /**
280          * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}.
281          *
282          * @param value The subscription address.
283          * @return The builder.
284          */
setSubscriptionAddress(Uri value)285         public Builder setSubscriptionAddress(Uri value) {
286             this.mSubscriptionAddress = value;
287             return this;
288         }
289 
290         /**
291          * Sets the capabilities. See {@link PhoneAccount#getCapabilities}.
292          *
293          * @param value The capabilities to set.
294          * @return The builder.
295          */
setCapabilities(int value)296         public Builder setCapabilities(int value) {
297             this.mCapabilities = value;
298             return this;
299         }
300 
301         /**
302          * Sets the icon. See {@link PhoneAccount#getIcon}.
303          *
304          * @param icon The icon to set.
305          */
setIcon(Icon icon)306         public Builder setIcon(Icon icon) {
307             mIcon = icon;
308             return this;
309         }
310 
311         /**
312          * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}.
313          *
314          * @param value The highlight color.
315          * @return The builder.
316          */
setHighlightColor(int value)317         public Builder setHighlightColor(int value) {
318             this.mHighlightColor = value;
319             return this;
320         }
321 
322         /**
323          * Sets the short description. See {@link PhoneAccount#getShortDescription}.
324          *
325          * @param value The short description.
326          * @return The builder.
327          */
setShortDescription(CharSequence value)328         public Builder setShortDescription(CharSequence value) {
329             this.mShortDescription = value;
330             return this;
331         }
332 
333         /**
334          * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
335          *
336          * @param uriScheme The URI scheme.
337          * @return The builder.
338          */
addSupportedUriScheme(String uriScheme)339         public Builder addSupportedUriScheme(String uriScheme) {
340             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
341                 this.mSupportedUriSchemes.add(uriScheme);
342             }
343             return this;
344         }
345 
346         /**
347          * Specifies the URI schemes supported by the {@link PhoneAccount}.
348          *
349          * @param uriSchemes The URI schemes.
350          * @return The builder.
351          */
setSupportedUriSchemes(List<String> uriSchemes)352         public Builder setSupportedUriSchemes(List<String> uriSchemes) {
353             mSupportedUriSchemes.clear();
354 
355             if (uriSchemes != null && !uriSchemes.isEmpty()) {
356                 for (String uriScheme : uriSchemes) {
357                     addSupportedUriScheme(uriScheme);
358                 }
359             }
360             return this;
361         }
362 
363         /**
364          * Specifies the extras associated with the {@link PhoneAccount}.
365          * <p>
366          * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer},
367          * and {@link Boolean}.  Extras which are not of these types are ignored.
368          *
369          * @param extras
370          * @return
371          */
setExtras(Bundle extras)372         public Builder setExtras(Bundle extras) {
373             mExtras = extras;
374             return this;
375         }
376 
377         /**
378          * Sets the enabled state of the phone account.
379          *
380          * @param isEnabled The enabled state.
381          * @return The builder.
382          * @hide
383          */
setIsEnabled(boolean isEnabled)384         public Builder setIsEnabled(boolean isEnabled) {
385             mIsEnabled = isEnabled;
386             return this;
387         }
388 
389         /**
390          * Creates an instance of a {@link PhoneAccount} based on the current builder settings.
391          *
392          * @return The {@link PhoneAccount}.
393          */
build()394         public PhoneAccount build() {
395             // If no supported URI schemes were defined, assume "tel" is supported.
396             if (mSupportedUriSchemes.isEmpty()) {
397                 addSupportedUriScheme(SCHEME_TEL);
398             }
399 
400             return new PhoneAccount(
401                     mAccountHandle,
402                     mAddress,
403                     mSubscriptionAddress,
404                     mCapabilities,
405                     mIcon,
406                     mHighlightColor,
407                     mLabel,
408                     mShortDescription,
409                     mSupportedUriSchemes,
410                     mExtras,
411                     mIsEnabled);
412         }
413     }
414 
PhoneAccount( PhoneAccountHandle account, Uri address, Uri subscriptionAddress, int capabilities, Icon icon, int highlightColor, CharSequence label, CharSequence shortDescription, List<String> supportedUriSchemes, Bundle extras, boolean isEnabled)415     private PhoneAccount(
416             PhoneAccountHandle account,
417             Uri address,
418             Uri subscriptionAddress,
419             int capabilities,
420             Icon icon,
421             int highlightColor,
422             CharSequence label,
423             CharSequence shortDescription,
424             List<String> supportedUriSchemes,
425             Bundle extras,
426             boolean isEnabled) {
427         mAccountHandle = account;
428         mAddress = address;
429         mSubscriptionAddress = subscriptionAddress;
430         mCapabilities = capabilities;
431         mIcon = icon;
432         mHighlightColor = highlightColor;
433         mLabel = label;
434         mShortDescription = shortDescription;
435         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
436         mExtras = extras;
437         mIsEnabled = isEnabled;
438     }
439 
builder( PhoneAccountHandle accountHandle, CharSequence label)440     public static Builder builder(
441             PhoneAccountHandle accountHandle,
442             CharSequence label) {
443         return new Builder(accountHandle, label);
444     }
445 
446     /**
447      * Returns a builder initialized with the current {@link PhoneAccount} instance.
448      *
449      * @return The builder.
450      */
toBuilder()451     public Builder toBuilder() { return new Builder(this); }
452 
453     /**
454      * The unique identifier of this {@code PhoneAccount}.
455      *
456      * @return A {@code PhoneAccountHandle}.
457      */
getAccountHandle()458     public PhoneAccountHandle getAccountHandle() {
459         return mAccountHandle;
460     }
461 
462     /**
463      * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
464      * represents the destination from which outgoing calls using this {@code PhoneAccount}
465      * will appear to come, if applicable, and the destination to which incoming calls using this
466      * {@code PhoneAccount} may be addressed.
467      *
468      * @return A address expressed as a {@code Uri}, for example, a phone number.
469      */
getAddress()470     public Uri getAddress() {
471         return mAddress;
472     }
473 
474     /**
475      * The raw callback number used for this {@code PhoneAccount}, as distinct from
476      * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
477      * as {@code null}.  It is used by the system for SIM-based {@code PhoneAccount} registration
478      * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
479      * has been used to alter the callback number.
480      * <p>
481      *
482      * @return The subscription number, suitable for display to the user.
483      */
getSubscriptionAddress()484     public Uri getSubscriptionAddress() {
485         return mSubscriptionAddress;
486     }
487 
488     /**
489      * The capabilities of this {@code PhoneAccount}.
490      *
491      * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
492      */
getCapabilities()493     public int getCapabilities() {
494         return mCapabilities;
495     }
496 
497     /**
498      * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in
499      * bit mask.
500      *
501      * @param capability The capabilities to check.
502      * @return {@code true} if the phone account has the capability.
503      */
hasCapabilities(int capability)504     public boolean hasCapabilities(int capability) {
505         return (mCapabilities & capability) == capability;
506     }
507 
508     /**
509      * A short label describing a {@code PhoneAccount}.
510      *
511      * @return A label for this {@code PhoneAccount}.
512      */
getLabel()513     public CharSequence getLabel() {
514         return mLabel;
515     }
516 
517     /**
518      * A short paragraph describing this {@code PhoneAccount}.
519      *
520      * @return A description for this {@code PhoneAccount}.
521      */
getShortDescription()522     public CharSequence getShortDescription() {
523         return mShortDescription;
524     }
525 
526     /**
527      * The URI schemes supported by this {@code PhoneAccount}.
528      *
529      * @return The URI schemes.
530      */
getSupportedUriSchemes()531     public List<String> getSupportedUriSchemes() {
532         return mSupportedUriSchemes;
533     }
534 
535     /**
536      * The extras associated with this {@code PhoneAccount}.
537      * <p>
538      * A {@link ConnectionService} may provide implementation specific information about the
539      * {@link PhoneAccount} via the extras.
540      *
541      * @return The extras.
542      */
getExtras()543     public Bundle getExtras() {
544         return mExtras;
545     }
546 
547     /**
548      * The icon to represent this {@code PhoneAccount}.
549      *
550      * @return The icon.
551      */
getIcon()552     public Icon getIcon() {
553         return mIcon;
554     }
555 
556     /**
557      * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only
558      * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}.
559      *
560      * @return {@code true} if the account is enabled by the user, {@code false} otherwise.
561      */
isEnabled()562     public boolean isEnabled() {
563         return mIsEnabled;
564     }
565 
566     /**
567      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
568      * scheme.
569      *
570      * @param uriScheme The URI scheme to check.
571      * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the
572      * specified URI scheme.
573      */
supportsUriScheme(String uriScheme)574     public boolean supportsUriScheme(String uriScheme) {
575         if (mSupportedUriSchemes == null || uriScheme == null) {
576             return false;
577         }
578 
579         for (String scheme : mSupportedUriSchemes) {
580             if (scheme != null && scheme.equals(uriScheme)) {
581                 return true;
582             }
583         }
584         return false;
585     }
586 
587     /**
588      * A highlight color to use in displaying information about this {@code PhoneAccount}.
589      *
590      * @return A hexadecimal color value.
591      */
getHighlightColor()592     public int getHighlightColor() {
593         return mHighlightColor;
594     }
595 
596     /**
597      * Sets the enabled state of the phone account.
598      * @hide
599      */
setIsEnabled(boolean isEnabled)600     public void setIsEnabled(boolean isEnabled) {
601         mIsEnabled = isEnabled;
602     }
603 
604     //
605     // Parcelable implementation
606     //
607 
608     @Override
describeContents()609     public int describeContents() {
610         return 0;
611     }
612 
613     @Override
writeToParcel(Parcel out, int flags)614     public void writeToParcel(Parcel out, int flags) {
615         if (mAccountHandle == null) {
616             out.writeInt(0);
617         } else {
618             out.writeInt(1);
619             mAccountHandle.writeToParcel(out, flags);
620         }
621         if (mAddress == null) {
622             out.writeInt(0);
623         } else {
624             out.writeInt(1);
625             mAddress.writeToParcel(out, flags);
626         }
627         if (mSubscriptionAddress == null) {
628             out.writeInt(0);
629         } else {
630             out.writeInt(1);
631             mSubscriptionAddress.writeToParcel(out, flags);
632         }
633         out.writeInt(mCapabilities);
634         out.writeInt(mHighlightColor);
635         out.writeCharSequence(mLabel);
636         out.writeCharSequence(mShortDescription);
637         out.writeStringList(mSupportedUriSchemes);
638 
639         if (mIcon == null) {
640             out.writeInt(0);
641         } else {
642             out.writeInt(1);
643             mIcon.writeToParcel(out, flags);
644         }
645         out.writeByte((byte) (mIsEnabled ? 1 : 0));
646         out.writeBundle(mExtras);
647     }
648 
649     public static final Creator<PhoneAccount> CREATOR
650             = new Creator<PhoneAccount>() {
651         @Override
652         public PhoneAccount createFromParcel(Parcel in) {
653             return new PhoneAccount(in);
654         }
655 
656         @Override
657         public PhoneAccount[] newArray(int size) {
658             return new PhoneAccount[size];
659         }
660     };
661 
PhoneAccount(Parcel in)662     private PhoneAccount(Parcel in) {
663         if (in.readInt() > 0) {
664             mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in);
665         } else {
666             mAccountHandle = null;
667         }
668         if (in.readInt() > 0) {
669             mAddress = Uri.CREATOR.createFromParcel(in);
670         } else {
671             mAddress = null;
672         }
673         if (in.readInt() > 0) {
674             mSubscriptionAddress = Uri.CREATOR.createFromParcel(in);
675         } else {
676             mSubscriptionAddress = null;
677         }
678         mCapabilities = in.readInt();
679         mHighlightColor = in.readInt();
680         mLabel = in.readCharSequence();
681         mShortDescription = in.readCharSequence();
682         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
683         if (in.readInt() > 0) {
684             mIcon = Icon.CREATOR.createFromParcel(in);
685         } else {
686             mIcon = null;
687         }
688         mIsEnabled = in.readByte() == 1;
689         mExtras = in.readBundle();
690     }
691 
692     @Override
toString()693     public String toString() {
694         StringBuilder sb = new StringBuilder().append("[[")
695                 .append(mIsEnabled ? 'X' : ' ')
696                 .append("] PhoneAccount: ")
697                 .append(mAccountHandle)
698                 .append(" Capabilities: ")
699                 .append(capabilitiesToString(mCapabilities))
700                 .append(" Schemes: ");
701         for (String scheme : mSupportedUriSchemes) {
702             sb.append(scheme)
703                     .append(" ");
704         }
705         sb.append(" Extras: ");
706         sb.append(mExtras);
707         sb.append("]");
708         return sb.toString();
709     }
710 
711     /**
712      * Generates a string representation of a capabilities bitmask.
713      *
714      * @param capabilities The capabilities bitmask.
715      * @return String representation of the capabilities bitmask.
716      */
capabilitiesToString(int capabilities)717     private String capabilitiesToString(int capabilities) {
718         StringBuilder sb = new StringBuilder();
719         if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
720             sb.append("Video ");
721         }
722         if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
723             sb.append("Presence ");
724         }
725         if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) {
726             sb.append("CallProvider ");
727         }
728         if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) {
729             sb.append("CallSubject ");
730         }
731         if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) {
732             sb.append("ConnectionMgr ");
733         }
734         if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) {
735             sb.append("EmergOnly ");
736         }
737         if (hasCapabilities(CAPABILITY_MULTI_USER)) {
738             sb.append("MultiUser ");
739         }
740         if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
741             sb.append("PlaceEmerg ");
742         }
743         if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
744             sb.append("EmergVideo ");
745         }
746         if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
747             sb.append("SimSub ");
748         }
749         return sb.toString();
750     }
751 }
752