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