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