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