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