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