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 private String mGroupId; 224 225 /** 226 * Helper class for creating a {@link PhoneAccount}. 227 */ 228 public static class Builder { 229 private PhoneAccountHandle mAccountHandle; 230 private Uri mAddress; 231 private Uri mSubscriptionAddress; 232 private int mCapabilities; 233 private int mHighlightColor = NO_HIGHLIGHT_COLOR; 234 private CharSequence mLabel; 235 private CharSequence mShortDescription; 236 private List<String> mSupportedUriSchemes = new ArrayList<String>(); 237 private Icon mIcon; 238 private Bundle mExtras; 239 private boolean mIsEnabled = false; 240 private String mGroupId = ""; 241 242 /** 243 * Creates a builder with the specified {@link PhoneAccountHandle} and label. 244 */ 245 public Builder(PhoneAccountHandle accountHandle, CharSequence label) { 246 this.mAccountHandle = accountHandle; 247 this.mLabel = label; 248 } 249 250 /** 251 * Creates an instance of the {@link PhoneAccount.Builder} from an existing 252 * {@link PhoneAccount}. 253 * 254 * @param phoneAccount The {@link PhoneAccount} used to initialize the builder. 255 */ 256 public Builder(PhoneAccount phoneAccount) { 257 mAccountHandle = phoneAccount.getAccountHandle(); 258 mAddress = phoneAccount.getAddress(); 259 mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); 260 mCapabilities = phoneAccount.getCapabilities(); 261 mHighlightColor = phoneAccount.getHighlightColor(); 262 mLabel = phoneAccount.getLabel(); 263 mShortDescription = phoneAccount.getShortDescription(); 264 mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); 265 mIcon = phoneAccount.getIcon(); 266 mIsEnabled = phoneAccount.isEnabled(); 267 mExtras = phoneAccount.getExtras(); 268 mGroupId = phoneAccount.getGroupId(); 269 } 270 271 /** 272 * Sets the address. See {@link PhoneAccount#getAddress}. 273 * 274 * @param value The address of the phone account. 275 * @return The builder. 276 */ 277 public Builder setAddress(Uri value) { 278 this.mAddress = value; 279 return this; 280 } 281 282 /** 283 * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}. 284 * 285 * @param value The subscription address. 286 * @return The builder. 287 */ 288 public Builder setSubscriptionAddress(Uri value) { 289 this.mSubscriptionAddress = value; 290 return this; 291 } 292 293 /** 294 * Sets the capabilities. See {@link PhoneAccount#getCapabilities}. 295 * 296 * @param value The capabilities to set. 297 * @return The builder. 298 */ 299 public Builder setCapabilities(int value) { 300 this.mCapabilities = value; 301 return this; 302 } 303 304 /** 305 * Sets the icon. See {@link PhoneAccount#getIcon}. 306 * 307 * @param icon The icon to set. 308 */ 309 public Builder setIcon(Icon icon) { 310 mIcon = icon; 311 return this; 312 } 313 314 /** 315 * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}. 316 * 317 * @param value The highlight color. 318 * @return The builder. 319 */ 320 public Builder setHighlightColor(int value) { 321 this.mHighlightColor = value; 322 return this; 323 } 324 325 /** 326 * Sets the short description. See {@link PhoneAccount#getShortDescription}. 327 * 328 * @param value The short description. 329 * @return The builder. 330 */ 331 public Builder setShortDescription(CharSequence value) { 332 this.mShortDescription = value; 333 return this; 334 } 335 336 /** 337 * Specifies an additional URI scheme supported by the {@link PhoneAccount}. 338 * 339 * @param uriScheme The URI scheme. 340 * @return The builder. 341 */ 342 public Builder addSupportedUriScheme(String uriScheme) { 343 if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) { 344 this.mSupportedUriSchemes.add(uriScheme); 345 } 346 return this; 347 } 348 349 /** 350 * Specifies the URI schemes supported by the {@link PhoneAccount}. 351 * 352 * @param uriSchemes The URI schemes. 353 * @return The builder. 354 */ 355 public Builder setSupportedUriSchemes(List<String> uriSchemes) { 356 mSupportedUriSchemes.clear(); 357 358 if (uriSchemes != null && !uriSchemes.isEmpty()) { 359 for (String uriScheme : uriSchemes) { 360 addSupportedUriScheme(uriScheme); 361 } 362 } 363 return this; 364 } 365 366 /** 367 * Specifies the extras associated with the {@link PhoneAccount}. 368 * <p> 369 * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer}, 370 * and {@link Boolean}. Extras which are not of these types are ignored. 371 * 372 * @param extras 373 * @return 374 */ 375 public Builder setExtras(Bundle extras) { 376 mExtras = extras; 377 return this; 378 } 379 380 /** 381 * Sets the enabled state of the phone account. 382 * 383 * @param isEnabled The enabled state. 384 * @return The builder. 385 * @hide 386 */ 387 public Builder setIsEnabled(boolean isEnabled) { 388 mIsEnabled = isEnabled; 389 return this; 390 } 391 392 /** 393 * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is 394 * registered to Telecom, it will replace another {@link PhoneAccount} that is already 395 * registered in Telecom and take on the current user defaults and enabled status. There can 396 * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a 397 * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only 398 * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced. 399 * @param groupId The group Id of the {@link PhoneAccount} that will replace any other 400 * registered {@link PhoneAccount} in Telecom with the same Group Id. 401 * @return The builder 402 * @hide 403 */ 404 public Builder setGroupId(String groupId) { 405 if (groupId != null) { 406 mGroupId = groupId; 407 } else { 408 mGroupId = ""; 409 } 410 return this; 411 } 412 413 /** 414 * Creates an instance of a {@link PhoneAccount} based on the current builder settings. 415 * 416 * @return The {@link PhoneAccount}. 417 */ 418 public PhoneAccount build() { 419 // If no supported URI schemes were defined, assume "tel" is supported. 420 if (mSupportedUriSchemes.isEmpty()) { 421 addSupportedUriScheme(SCHEME_TEL); 422 } 423 424 return new PhoneAccount( 425 mAccountHandle, 426 mAddress, 427 mSubscriptionAddress, 428 mCapabilities, 429 mIcon, 430 mHighlightColor, 431 mLabel, 432 mShortDescription, 433 mSupportedUriSchemes, 434 mExtras, 435 mIsEnabled, 436 mGroupId); 437 } 438 } 439 440 private PhoneAccount( 441 PhoneAccountHandle account, 442 Uri address, 443 Uri subscriptionAddress, 444 int capabilities, 445 Icon icon, 446 int highlightColor, 447 CharSequence label, 448 CharSequence shortDescription, 449 List<String> supportedUriSchemes, 450 Bundle extras, 451 boolean isEnabled, 452 String groupId) { 453 mAccountHandle = account; 454 mAddress = address; 455 mSubscriptionAddress = subscriptionAddress; 456 mCapabilities = capabilities; 457 mIcon = icon; 458 mHighlightColor = highlightColor; 459 mLabel = label; 460 mShortDescription = shortDescription; 461 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 462 mExtras = extras; 463 mIsEnabled = isEnabled; 464 mGroupId = groupId; 465 } 466 467 public static Builder builder( 468 PhoneAccountHandle accountHandle, 469 CharSequence label) { 470 return new Builder(accountHandle, label); 471 } 472 473 /** 474 * Returns a builder initialized with the current {@link PhoneAccount} instance. 475 * 476 * @return The builder. 477 */ 478 public Builder toBuilder() { return new Builder(this); } 479 480 /** 481 * The unique identifier of this {@code PhoneAccount}. 482 * 483 * @return A {@code PhoneAccountHandle}. 484 */ 485 public PhoneAccountHandle getAccountHandle() { 486 return mAccountHandle; 487 } 488 489 /** 490 * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This 491 * represents the destination from which outgoing calls using this {@code PhoneAccount} 492 * will appear to come, if applicable, and the destination to which incoming calls using this 493 * {@code PhoneAccount} may be addressed. 494 * 495 * @return A address expressed as a {@code Uri}, for example, a phone number. 496 */ 497 public Uri getAddress() { 498 return mAddress; 499 } 500 501 /** 502 * The raw callback number used for this {@code PhoneAccount}, as distinct from 503 * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered 504 * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration 505 * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} 506 * has been used to alter the callback number. 507 * <p> 508 * 509 * @return The subscription number, suitable for display to the user. 510 */ 511 public Uri getSubscriptionAddress() { 512 return mSubscriptionAddress; 513 } 514 515 /** 516 * The capabilities of this {@code PhoneAccount}. 517 * 518 * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities. 519 */ 520 public int getCapabilities() { 521 return mCapabilities; 522 } 523 524 /** 525 * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in 526 * bit mask. 527 * 528 * @param capability The capabilities to check. 529 * @return {@code true} if the phone account has the capability. 530 */ 531 public boolean hasCapabilities(int capability) { 532 return (mCapabilities & capability) == capability; 533 } 534 535 /** 536 * A short label describing a {@code PhoneAccount}. 537 * 538 * @return A label for this {@code PhoneAccount}. 539 */ 540 public CharSequence getLabel() { 541 return mLabel; 542 } 543 544 /** 545 * A short paragraph describing this {@code PhoneAccount}. 546 * 547 * @return A description for this {@code PhoneAccount}. 548 */ 549 public CharSequence getShortDescription() { 550 return mShortDescription; 551 } 552 553 /** 554 * The URI schemes supported by this {@code PhoneAccount}. 555 * 556 * @return The URI schemes. 557 */ 558 public List<String> getSupportedUriSchemes() { 559 return mSupportedUriSchemes; 560 } 561 562 /** 563 * The extras associated with this {@code PhoneAccount}. 564 * <p> 565 * A {@link ConnectionService} may provide implementation specific information about the 566 * {@link PhoneAccount} via the extras. 567 * 568 * @return The extras. 569 */ 570 public Bundle getExtras() { 571 return mExtras; 572 } 573 574 /** 575 * The icon to represent this {@code PhoneAccount}. 576 * 577 * @return The icon. 578 */ 579 public Icon getIcon() { 580 return mIcon; 581 } 582 583 /** 584 * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only 585 * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}. 586 * 587 * @return {@code true} if the account is enabled by the user, {@code false} otherwise. 588 */ 589 public boolean isEnabled() { 590 return mIsEnabled; 591 } 592 593 /** 594 * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an 595 * empty {@link String} if the {@link PhoneAccount} is not in a group. If this 596 * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered 597 * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced, 598 * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}. 599 * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced. 600 * 601 * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group. 602 * @hide 603 */ 604 public String getGroupId() { 605 return mGroupId; 606 } 607 608 /** 609 * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI 610 * scheme. 611 * 612 * @param uriScheme The URI scheme to check. 613 * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the 614 * specified URI scheme. 615 */ 616 public boolean supportsUriScheme(String uriScheme) { 617 if (mSupportedUriSchemes == null || uriScheme == null) { 618 return false; 619 } 620 621 for (String scheme : mSupportedUriSchemes) { 622 if (scheme != null && scheme.equals(uriScheme)) { 623 return true; 624 } 625 } 626 return false; 627 } 628 629 /** 630 * A highlight color to use in displaying information about this {@code PhoneAccount}. 631 * 632 * @return A hexadecimal color value. 633 */ 634 public int getHighlightColor() { 635 return mHighlightColor; 636 } 637 638 /** 639 * Sets the enabled state of the phone account. 640 * @hide 641 */ 642 public void setIsEnabled(boolean isEnabled) { 643 mIsEnabled = isEnabled; 644 } 645 646 // 647 // Parcelable implementation 648 // 649 650 @Override 651 public int describeContents() { 652 return 0; 653 } 654 655 @Override 656 public void writeToParcel(Parcel out, int flags) { 657 if (mAccountHandle == null) { 658 out.writeInt(0); 659 } else { 660 out.writeInt(1); 661 mAccountHandle.writeToParcel(out, flags); 662 } 663 if (mAddress == null) { 664 out.writeInt(0); 665 } else { 666 out.writeInt(1); 667 mAddress.writeToParcel(out, flags); 668 } 669 if (mSubscriptionAddress == null) { 670 out.writeInt(0); 671 } else { 672 out.writeInt(1); 673 mSubscriptionAddress.writeToParcel(out, flags); 674 } 675 out.writeInt(mCapabilities); 676 out.writeInt(mHighlightColor); 677 out.writeCharSequence(mLabel); 678 out.writeCharSequence(mShortDescription); 679 out.writeStringList(mSupportedUriSchemes); 680 681 if (mIcon == null) { 682 out.writeInt(0); 683 } else { 684 out.writeInt(1); 685 mIcon.writeToParcel(out, flags); 686 } 687 out.writeByte((byte) (mIsEnabled ? 1 : 0)); 688 out.writeBundle(mExtras); 689 out.writeString(mGroupId); 690 } 691 692 public static final Creator<PhoneAccount> CREATOR 693 = new Creator<PhoneAccount>() { 694 @Override 695 public PhoneAccount createFromParcel(Parcel in) { 696 return new PhoneAccount(in); 697 } 698 699 @Override 700 public PhoneAccount[] newArray(int size) { 701 return new PhoneAccount[size]; 702 } 703 }; 704 705 private PhoneAccount(Parcel in) { 706 if (in.readInt() > 0) { 707 mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in); 708 } else { 709 mAccountHandle = null; 710 } 711 if (in.readInt() > 0) { 712 mAddress = Uri.CREATOR.createFromParcel(in); 713 } else { 714 mAddress = null; 715 } 716 if (in.readInt() > 0) { 717 mSubscriptionAddress = Uri.CREATOR.createFromParcel(in); 718 } else { 719 mSubscriptionAddress = null; 720 } 721 mCapabilities = in.readInt(); 722 mHighlightColor = in.readInt(); 723 mLabel = in.readCharSequence(); 724 mShortDescription = in.readCharSequence(); 725 mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList()); 726 if (in.readInt() > 0) { 727 mIcon = Icon.CREATOR.createFromParcel(in); 728 } else { 729 mIcon = null; 730 } 731 mIsEnabled = in.readByte() == 1; 732 mExtras = in.readBundle(); 733 mGroupId = in.readString(); 734 } 735 736 @Override 737 public String toString() { 738 StringBuilder sb = new StringBuilder().append("[[") 739 .append(mIsEnabled ? 'X' : ' ') 740 .append("] PhoneAccount: ") 741 .append(mAccountHandle) 742 .append(" Capabilities: ") 743 .append(capabilitiesToString(mCapabilities)) 744 .append(" Schemes: "); 745 for (String scheme : mSupportedUriSchemes) { 746 sb.append(scheme) 747 .append(" "); 748 } 749 sb.append(" Extras: "); 750 sb.append(mExtras); 751 sb.append(" GroupId: "); 752 sb.append(Log.pii(mGroupId)); 753 sb.append("]"); 754 return sb.toString(); 755 } 756 757 /** 758 * Generates a string representation of a capabilities bitmask. 759 * 760 * @param capabilities The capabilities bitmask. 761 * @return String representation of the capabilities bitmask. 762 */ 763 private String capabilitiesToString(int capabilities) { 764 StringBuilder sb = new StringBuilder(); 765 if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) { 766 sb.append("Video "); 767 } 768 if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) { 769 sb.append("Presence "); 770 } 771 if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) { 772 sb.append("CallProvider "); 773 } 774 if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) { 775 sb.append("CallSubject "); 776 } 777 if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) { 778 sb.append("ConnectionMgr "); 779 } 780 if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) { 781 sb.append("EmergOnly "); 782 } 783 if (hasCapabilities(CAPABILITY_MULTI_USER)) { 784 sb.append("MultiUser "); 785 } 786 if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) { 787 sb.append("PlaceEmerg "); 788 } 789 if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) { 790 sb.append("EmergVideo "); 791 } 792 if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) { 793 sb.append("SimSub "); 794 } 795 return sb.toString(); 796 } 797 } 798