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