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