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