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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 543 public Bundle getExtras() { 544 return mExtras; 545 } 546 547 /** 548 * The icon to represent this {@code PhoneAccount}. 549 * 550 * @return The icon. 551 */ 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 */ 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 */ 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 */ 592 public int getHighlightColor() { 593 return mHighlightColor; 594 } 595 596 /** 597 * Sets the enabled state of the phone account. 598 * @hide 599 */ 600 public void setIsEnabled(boolean isEnabled) { 601 mIsEnabled = isEnabled; 602 } 603 604 // 605 // Parcelable implementation 606 // 607 608 @Override 609 public int describeContents() { 610 return 0; 611 } 612 613 @Override 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 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 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 */ 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