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 static android.Manifest.permission.MODIFY_PHONE_STATE; 20 21 import android.annotation.NonNull; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemApi; 24 import android.content.Intent; 25 import android.graphics.drawable.Icon; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.os.Parcel; 29 import android.os.Parcelable; 30 import android.telephony.CarrierConfigManager; 31 import android.telephony.TelephonyManager; 32 import android.text.TextUtils; 33 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.List; 37 import java.util.Objects; 38 39 /** 40 * Represents a distinct method to place or receive a phone call. Apps which can place calls and 41 * want those calls to be integrated into the dialer and in-call UI should build an instance of 42 * this class and register it with the system using {@link TelecomManager}. 43 * <p> 44 * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with 45 * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app 46 * should supply a valid {@link PhoneAccountHandle} that references the connection service 47 * implementation Telecom will use to interact with the app. 48 */ 49 public final class PhoneAccount implements Parcelable { 50 51 /** 52 * Integer extra which determines the order in which {@link PhoneAccount}s are sorted 53 * 54 * This is an extras key set via {@link Builder#setExtras} which determines the order in which 55 * {@link PhoneAccount}s from the same {@link ConnectionService} are sorted. The accounts 56 * are sorted in ascending order by this key, and this ordering is used to 57 * determine priority when a call can be placed via multiple accounts. 58 * 59 * When multiple {@link PhoneAccount}s are supplied with the same sort order key, no ordering is 60 * guaranteed between those {@link PhoneAccount}s. Additionally, no ordering is guaranteed 61 * between {@link PhoneAccount}s that do not supply this extra, and all such accounts 62 * will be sorted after the accounts that do supply this extra. 63 * 64 * An example of a sort order key is slot index (see {@link TelephonyManager#getSlotIndex()}), 65 * which is the one used by the cell Telephony stack. 66 * @hide 67 */ 68 @SystemApi 69 public static final String EXTRA_SORT_ORDER = 70 "android.telecom.extra.SORT_ORDER"; 71 72 /** 73 * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the 74 * maximum permitted length of a call subject specified via the 75 * {@link TelecomManager#EXTRA_CALL_SUBJECT} extra on an 76 * {@link android.content.Intent#ACTION_CALL} intent. Ultimately a {@link ConnectionService} is 77 * responsible for enforcing the maximum call subject length when sending the message, however 78 * this extra is provided so that the user interface can proactively limit the length of the 79 * call subject as the user types it. 80 */ 81 public static final String EXTRA_CALL_SUBJECT_MAX_LENGTH = 82 "android.telecom.extra.CALL_SUBJECT_MAX_LENGTH"; 83 84 /** 85 * {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which determines the 86 * character encoding to be used when determining the length of messages. 87 * The user interface can use this when determining the number of characters the user may type 88 * in a call subject. If empty-string, the call subject message size limit will be enforced on 89 * a 1:1 basis. That is, each character will count towards the messages size limit as a single 90 * character. If a character encoding is specified, the message size limit will be based on the 91 * number of bytes in the message per the specified encoding. See 92 * {@link #EXTRA_CALL_SUBJECT_MAX_LENGTH} for more information on the call subject maximum 93 * length. 94 */ 95 public static final String EXTRA_CALL_SUBJECT_CHARACTER_ENCODING = 96 "android.telecom.extra.CALL_SUBJECT_CHARACTER_ENCODING"; 97 98 /** 99 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 100 * indicates that all calls from this {@link PhoneAccount} should be treated as VoIP calls 101 * rather than cellular calls by the Telecom audio handling logic. 102 */ 103 public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE = 104 "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE"; 105 106 /** 107 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 108 * indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a 109 * connection (see {@code android.telecom.Call#handoverTo()}) to this {@link PhoneAccount} from 110 * a {@link PhoneAccount} specifying {@link #EXTRA_SUPPORTS_HANDOVER_FROM}. 111 * <p> 112 * A handover request is initiated by the user from the default dialer app to indicate a desire 113 * to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another. 114 */ 115 public static final String EXTRA_SUPPORTS_HANDOVER_TO = 116 "android.telecom.extra.SUPPORTS_HANDOVER_TO"; 117 118 /** 119 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 120 * indicates whether this {@link PhoneAccount} supports using a fallback if video calling is 121 * not available. This extra is for device level support, {@link 122 * android.telephony.CarrierConfigManager#KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL} should also 123 * be checked to ensure it is not disabled by individual carrier. 124 * 125 * @hide 126 */ 127 public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK = 128 "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK"; 129 130 /** 131 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 132 * indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a 133 * connection from this {@link PhoneAccount} to another {@link PhoneAccount}. 134 * (see {@code android.telecom.Call#handoverTo()}) which specifies 135 * {@link #EXTRA_SUPPORTS_HANDOVER_TO}. 136 * <p> 137 * A handover request is initiated by the user from the default dialer app to indicate a desire 138 * to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another. 139 */ 140 public static final String EXTRA_SUPPORTS_HANDOVER_FROM = 141 "android.telecom.extra.SUPPORTS_HANDOVER_FROM"; 142 143 144 /** 145 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 146 * indicates whether a Self-Managed {@link PhoneAccount} should log its calls to the call log. 147 * Self-Managed {@link PhoneAccount}s are responsible for their own notifications, so the system 148 * will not create a notification when a missed call is logged. 149 * <p> 150 * By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log. 151 * Setting this extra to {@code true} provides a means for them to log their calls. 152 * <p> 153 * Note: Only calls where the {@link Call.Details#getHandle()} {@link Uri#getScheme()} is 154 * {@link #SCHEME_SIP} or {@link #SCHEME_TEL} will be logged at the current time. 155 */ 156 public static final String EXTRA_LOG_SELF_MANAGED_CALLS = 157 "android.telecom.extra.LOG_SELF_MANAGED_CALLS"; 158 159 /** 160 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 161 * indicates whether calls for a {@link PhoneAccount} should generate a "call recording tone" 162 * when the user is recording audio on the device. 163 * <p> 164 * The call recording tone is played over the telephony audio stream so that the remote party 165 * has an audible indication that it is possible their call is being recorded using a call 166 * recording app on the device. 167 * <p> 168 * This extra only has an effect for calls placed via Telephony (e.g. 169 * {@link #CAPABILITY_SIM_SUBSCRIPTION}). 170 * <p> 171 * The call recording tone is a 1400 hz tone which repeats every 15 seconds while recording is 172 * in progress. 173 * @hide 174 */ 175 @SystemApi 176 public static final String EXTRA_PLAY_CALL_RECORDING_TONE = 177 "android.telecom.extra.PLAY_CALL_RECORDING_TONE"; 178 179 /** 180 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()} which 181 * indicates whether calls for a {@link PhoneAccount} should skip call filtering. 182 * <p> 183 * If not specified, this will default to false; all calls will undergo call filtering unless 184 * specifically exempted (e.g. {@link Connection#PROPERTY_EMERGENCY_CALLBACK_MODE}.) However, 185 * this may be used to skip call filtering when it has already been performed on another device. 186 * @hide 187 */ 188 public static final String EXTRA_SKIP_CALL_FILTERING = 189 "android.telecom.extra.SKIP_CALL_FILTERING"; 190 191 /** 192 * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which 193 * indicates whether a Self-managed {@link PhoneAccount} want to expose its calls to all 194 * {@link InCallService} which declares the metadata 195 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS}. 196 */ 197 public static final String EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE = 198 "android.telecom.extra.ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE"; 199 200 /** 201 * Flag indicating that this {@code PhoneAccount} can act as a connection manager for 202 * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount} 203 * will be allowed to manage phone calls including using its own proprietary phone-call 204 * implementation (like VoIP calling) to make calls instead of the telephony stack. 205 * <p> 206 * When a user opts to place a call using the SIM-based telephony stack, the 207 * {@link ConnectionService} associated with this {@code PhoneAccount} will be attempted first 208 * if the user has explicitly selected it to be used as the default connection manager. 209 * <p> 210 * See {@link #getCapabilities} 211 */ 212 public static final int CAPABILITY_CONNECTION_MANAGER = 0x1; 213 214 /** 215 * Flag indicating that this {@code PhoneAccount} can make phone calls in place of 216 * traditional SIM-based telephony calls. This account will be treated as a distinct method 217 * for placing calls alongside the traditional SIM-based telephony stack. This flag is 218 * distinct from {@link #CAPABILITY_CONNECTION_MANAGER} in that it is not allowed to manage 219 * or place calls from the built-in telephony stack. 220 * <p> 221 * See {@link #getCapabilities} 222 * <p> 223 */ 224 public static final int CAPABILITY_CALL_PROVIDER = 0x2; 225 226 /** 227 * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM 228 * subscription. 229 * <p> 230 * Only the Android framework can register a {@code PhoneAccount} having this capability. 231 * <p> 232 * See {@link #getCapabilities} 233 */ 234 public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4; 235 236 /** 237 * Flag indicating that this {@code PhoneAccount} is currently able to place video calls. 238 * <p> 239 * See also {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING} which indicates whether the 240 * {@code PhoneAccount} supports placing video calls. 241 * <p> 242 * See {@link #getCapabilities} 243 */ 244 public static final int CAPABILITY_VIDEO_CALLING = 0x8; 245 246 /** 247 * Flag indicating that this {@code PhoneAccount} is capable of placing emergency calls. 248 * By default all PSTN {@code PhoneAccount}s are capable of placing emergency calls. 249 * <p> 250 * See {@link #getCapabilities} 251 */ 252 public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 0x10; 253 254 /** 255 * Flag indicating that this {@code PhoneAccount} is capable of being used by all users. This 256 * should only be used by system apps (and will be ignored for all other apps trying to use it). 257 * <p> 258 * See {@link #getCapabilities} 259 * @hide 260 */ 261 @SystemApi 262 public static final int CAPABILITY_MULTI_USER = 0x20; 263 264 /** 265 * Flag indicating that this {@code PhoneAccount} supports a subject for Calls. This means a 266 * caller is able to specify a short subject line for an outgoing call. A capable receiving 267 * device displays the call subject on the incoming call screen. 268 * <p> 269 * See {@link #getCapabilities} 270 */ 271 public static final int CAPABILITY_CALL_SUBJECT = 0x40; 272 273 /** 274 * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls. 275 * <p> 276 * See {@link #getCapabilities} 277 * @hide 278 */ 279 @SystemApi 280 public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80; 281 282 /** 283 * Flag indicating that for this {@code PhoneAccount}, the ability to make a video call to a 284 * number relies on presence. Should only be set if the {@code PhoneAccount} also has 285 * {@link #CAPABILITY_VIDEO_CALLING}. 286 * <p> 287 * Note: As of Android 12, using the 288 * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit on the 289 * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} column to indicate whether 290 * a contact's phone number supports video calling has been deprecated and should only be used 291 * on devices where {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set. On newer 292 * devices, applications must use {@link android.telephony.ims.RcsUceAdapter} instead to 293 * determine whether or not a contact's phone number supports carrier video calling. 294 * <p> 295 * See {@link #getCapabilities} 296 */ 297 public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100; 298 299 /** 300 * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed. 301 * <p> 302 * When set, Telecom will allow emergency video calls to be placed. When not set, Telecom will 303 * convert all outgoing video calls to emergency numbers to audio-only. 304 * @hide 305 */ 306 @SystemApi 307 public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200; 308 309 /** 310 * Flag indicating that this {@link PhoneAccount} supports video calling. 311 * This is not an indication that the {@link PhoneAccount} is currently able to make a video 312 * call, but rather that it has the ability to make video calls (but not necessarily at this 313 * time). 314 * <p> 315 * Whether a {@link PhoneAccount} can make a video call is ultimately controlled by 316 * {@link #CAPABILITY_VIDEO_CALLING}, which indicates whether the {@link PhoneAccount} is 317 * currently capable of making a video call. Consider a case where, for example, a 318 * {@link PhoneAccount} supports making video calls (e.g. 319 * {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}), but a current lack of network connectivity 320 * prevents video calls from being made (e.g. {@link #CAPABILITY_VIDEO_CALLING}). 321 * <p> 322 * See {@link #getCapabilities} 323 */ 324 public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400; 325 326 /** 327 * Flag indicating that this {@link PhoneAccount} is responsible for managing its own 328 * {@link Connection}s. This type of {@link PhoneAccount} is ideal for use with standalone 329 * calling apps which do not wish to use the default phone app for {@link Connection} UX, 330 * but which want to leverage the call and audio routing capabilities of the Telecom framework. 331 * <p> 332 * When set, {@link Connection}s created by the self-managed {@link ConnectionService} will not 333 * be surfaced to implementations of the {@link InCallService} API. Thus it is the 334 * responsibility of a self-managed {@link ConnectionService} to provide a user interface for 335 * its {@link Connection}s. 336 * <p> 337 * Self-managed {@link Connection}s will, however, be displayed on connected Bluetooth devices. 338 */ 339 public static final int CAPABILITY_SELF_MANAGED = 0x800; 340 341 /** 342 * Flag indicating that this {@link PhoneAccount} is capable of making a call with an 343 * RTT (Real-time text) session. 344 * When set, Telecom will attempt to open an RTT session on outgoing calls that specify 345 * that they should be placed with an RTT session , and the in-call app will be displayed 346 * with text entry fields for RTT. Likewise, the in-call app can request that an RTT 347 * session be opened during a call if this bit is set. 348 */ 349 public static final int CAPABILITY_RTT = 0x1000; 350 351 /** 352 * Flag indicating that this {@link PhoneAccount} is the preferred SIM subscription for 353 * emergency calls. A {@link PhoneAccount} that sets this capability must also 354 * set the {@link #CAPABILITY_SIM_SUBSCRIPTION} and {@link #CAPABILITY_PLACE_EMERGENCY_CALLS} 355 * capabilities. There must only be one emergency preferred {@link PhoneAccount} on the device. 356 * <p> 357 * When set, Telecom will prefer this {@link PhoneAccount} over others for emergency calling, 358 * even if the emergency call was placed with a specific {@link PhoneAccount} set using the 359 * extra{@link TelecomManager#EXTRA_PHONE_ACCOUNT_HANDLE} in 360 * {@link Intent#ACTION_CALL_EMERGENCY} or {@link TelecomManager#placeCall(Uri, Bundle)}. 361 * 362 * @hide 363 */ 364 @SystemApi 365 public static final int CAPABILITY_EMERGENCY_PREFERRED = 0x2000; 366 367 /** 368 * An adhoc conference call is established by providing a list of addresses to 369 * {@code TelecomManager#startConference(List<Uri>, int videoState)} where the 370 * {@link ConnectionService} is responsible for connecting all indicated participants 371 * to a conference simultaneously. 372 * This is in contrast to conferences formed by merging calls together (e.g. using 373 * {@link android.telecom.Call#mergeConference()}). 374 */ 375 public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 0x4000; 376 377 /** 378 * Flag indicating whether this {@link PhoneAccount} is capable of supporting the call composer 379 * functionality for enriched calls. 380 */ 381 public static final int CAPABILITY_CALL_COMPOSER = 0x8000; 382 383 /* NEXT CAPABILITY: 0x10000 */ 384 385 /** 386 * URI scheme for telephone number URIs. 387 */ 388 public static final String SCHEME_TEL = "tel"; 389 390 /** 391 * URI scheme for voicemail URIs. 392 */ 393 public static final String SCHEME_VOICEMAIL = "voicemail"; 394 395 /** 396 * URI scheme for SIP URIs. 397 */ 398 public static final String SCHEME_SIP = "sip"; 399 400 /** 401 * Indicating no icon tint is set. 402 * @hide 403 */ 404 public static final int NO_ICON_TINT = 0; 405 406 /** 407 * Indicating no hightlight color is set. 408 */ 409 public static final int NO_HIGHLIGHT_COLOR = 0; 410 411 /** 412 * Indicating no resource ID is set. 413 */ 414 public static final int NO_RESOURCE_ID = -1; 415 416 private final PhoneAccountHandle mAccountHandle; 417 private final Uri mAddress; 418 private final Uri mSubscriptionAddress; 419 private final int mCapabilities; 420 private final int mHighlightColor; 421 private final CharSequence mLabel; 422 private final CharSequence mShortDescription; 423 private final List<String> mSupportedUriSchemes; 424 private final int mSupportedAudioRoutes; 425 private final Icon mIcon; 426 private final Bundle mExtras; 427 private boolean mIsEnabled; 428 private String mGroupId; 429 430 @Override equals(Object o)431 public boolean equals(Object o) { 432 if (this == o) return true; 433 if (o == null || getClass() != o.getClass()) return false; 434 PhoneAccount that = (PhoneAccount) o; 435 return mCapabilities == that.mCapabilities && 436 mHighlightColor == that.mHighlightColor && 437 mSupportedAudioRoutes == that.mSupportedAudioRoutes && 438 mIsEnabled == that.mIsEnabled && 439 Objects.equals(mAccountHandle, that.mAccountHandle) && 440 Objects.equals(mAddress, that.mAddress) && 441 Objects.equals(mSubscriptionAddress, that.mSubscriptionAddress) && 442 Objects.equals(mLabel, that.mLabel) && 443 Objects.equals(mShortDescription, that.mShortDescription) && 444 Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) && 445 areBundlesEqual(mExtras, that.mExtras) && 446 Objects.equals(mGroupId, that.mGroupId); 447 } 448 449 @Override hashCode()450 public int hashCode() { 451 return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities, 452 mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes, 453 mSupportedAudioRoutes, 454 mExtras, mIsEnabled, mGroupId); 455 } 456 457 /** 458 * Helper class for creating a {@link PhoneAccount}. 459 */ 460 public static class Builder { 461 462 private PhoneAccountHandle mAccountHandle; 463 private Uri mAddress; 464 private Uri mSubscriptionAddress; 465 private int mCapabilities; 466 private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; 467 private int mHighlightColor = NO_HIGHLIGHT_COLOR; 468 private CharSequence mLabel; 469 private CharSequence mShortDescription; 470 private List<String> mSupportedUriSchemes = new ArrayList<String>(); 471 private Icon mIcon; 472 private Bundle mExtras; 473 private boolean mIsEnabled = false; 474 private String mGroupId = ""; 475 476 /** 477 * Creates a builder with the specified {@link PhoneAccountHandle} and label. 478 */ Builder(PhoneAccountHandle accountHandle, CharSequence label)479 public Builder(PhoneAccountHandle accountHandle, CharSequence label) { 480 this.mAccountHandle = accountHandle; 481 this.mLabel = label; 482 } 483 484 /** 485 * Creates an instance of the {@link PhoneAccount.Builder} from an existing 486 * {@link PhoneAccount}. 487 * 488 * @param phoneAccount The {@link PhoneAccount} used to initialize the builder. 489 */ Builder(PhoneAccount phoneAccount)490 public Builder(PhoneAccount phoneAccount) { 491 mAccountHandle = phoneAccount.getAccountHandle(); 492 mAddress = phoneAccount.getAddress(); 493 mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); 494 mCapabilities = phoneAccount.getCapabilities(); 495 mHighlightColor = phoneAccount.getHighlightColor(); 496 mLabel = phoneAccount.getLabel(); 497 mShortDescription = phoneAccount.getShortDescription(); 498 mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); 499 mIcon = phoneAccount.getIcon(); 500 mIsEnabled = phoneAccount.isEnabled(); 501 mExtras = phoneAccount.getExtras(); 502 mGroupId = phoneAccount.getGroupId(); 503 mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes(); 504 } 505 506 /** 507 * Sets the label. See {@link PhoneAccount#getLabel()}. 508 * 509 * @param label The label of the phone account. 510 * @return The builder. 511 * @hide 512 */ setLabel(CharSequence label)513 public Builder setLabel(CharSequence label) { 514 this.mLabel = label; 515 return this; 516 } 517 518 /** 519 * Sets the address. See {@link PhoneAccount#getAddress}. 520 * 521 * @param value The address of the phone account. 522 * @return The builder. 523 */ setAddress(Uri value)524 public Builder setAddress(Uri value) { 525 this.mAddress = value; 526 return this; 527 } 528 529 /** 530 * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}. 531 * 532 * @param value The subscription address. 533 * @return The builder. 534 */ setSubscriptionAddress(Uri value)535 public Builder setSubscriptionAddress(Uri value) { 536 this.mSubscriptionAddress = value; 537 return this; 538 } 539 540 /** 541 * Sets the capabilities. See {@link PhoneAccount#getCapabilities}. 542 * 543 * @param value The capabilities to set. 544 * @return The builder. 545 */ setCapabilities(int value)546 public Builder setCapabilities(int value) { 547 this.mCapabilities = value; 548 return this; 549 } 550 551 /** 552 * Sets the icon. See {@link PhoneAccount#getIcon}. 553 * 554 * @param icon The icon to set. 555 */ setIcon(Icon icon)556 public Builder setIcon(Icon icon) { 557 mIcon = icon; 558 return this; 559 } 560 561 /** 562 * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}. 563 * 564 * @param value The highlight color. 565 * @return The builder. 566 */ setHighlightColor(int value)567 public Builder setHighlightColor(int value) { 568 this.mHighlightColor = value; 569 return this; 570 } 571 572 /** 573 * Sets the short description. See {@link PhoneAccount#getShortDescription}. 574 * 575 * @param value The short description. 576 * @return The builder. 577 */ setShortDescription(CharSequence value)578 public Builder setShortDescription(CharSequence value) { 579 this.mShortDescription = value; 580 return this; 581 } 582 583 /** 584 * Specifies an additional URI scheme supported by the {@link PhoneAccount}. 585 * 586 * @param uriScheme The URI scheme. 587 * @return The builder. 588 */ addSupportedUriScheme(String uriScheme)589 public Builder addSupportedUriScheme(String uriScheme) { 590 if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) { 591 this.mSupportedUriSchemes.add(uriScheme); 592 } 593 return this; 594 } 595 596 /** 597 * Specifies the URI schemes supported by the {@link PhoneAccount}. 598 * 599 * @param uriSchemes The URI schemes. 600 * @return The builder. 601 */ setSupportedUriSchemes(List<String> uriSchemes)602 public Builder setSupportedUriSchemes(List<String> uriSchemes) { 603 mSupportedUriSchemes.clear(); 604 605 if (uriSchemes != null && !uriSchemes.isEmpty()) { 606 for (String uriScheme : uriSchemes) { 607 addSupportedUriScheme(uriScheme); 608 } 609 } 610 return this; 611 } 612 613 /** 614 * Specifies the extras associated with the {@link PhoneAccount}. 615 * <p> 616 * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer}, 617 * and {@link Boolean}. Extras which are not of these types are ignored. 618 * 619 * @param extras 620 * @return 621 */ setExtras(Bundle extras)622 public Builder setExtras(Bundle extras) { 623 mExtras = extras; 624 return this; 625 } 626 627 /** 628 * Sets the enabled state of the phone account. 629 * 630 * @param isEnabled The enabled state. 631 * @return The builder. 632 * @hide 633 */ setIsEnabled(boolean isEnabled)634 public Builder setIsEnabled(boolean isEnabled) { 635 mIsEnabled = isEnabled; 636 return this; 637 } 638 639 /** 640 * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is 641 * registered to Telecom, it will replace another {@link PhoneAccount} that is already 642 * registered in Telecom and take on the current user defaults and enabled status. There can 643 * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a 644 * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only 645 * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced. 646 * <p> 647 * Note: This is an API specific to the Telephony stack; the group Id will be ignored for 648 * callers not holding the correct permission. 649 * 650 * @param groupId The group Id of the {@link PhoneAccount} that will replace any other 651 * registered {@link PhoneAccount} in Telecom with the same Group Id. 652 * @return The builder 653 * @hide 654 */ 655 @SystemApi 656 @RequiresPermission(MODIFY_PHONE_STATE) setGroupId(@onNull String groupId)657 public @NonNull Builder setGroupId(@NonNull String groupId) { 658 if (groupId != null) { 659 mGroupId = groupId; 660 } else { 661 mGroupId = ""; 662 } 663 return this; 664 } 665 666 /** 667 * Sets the audio routes supported by this {@link PhoneAccount}. 668 * 669 * @param routes bit mask of available routes. 670 * @return The builder. 671 * @hide 672 */ setSupportedAudioRoutes(int routes)673 public Builder setSupportedAudioRoutes(int routes) { 674 mSupportedAudioRoutes = routes; 675 return this; 676 } 677 678 /** 679 * Creates an instance of a {@link PhoneAccount} based on the current builder settings. 680 * 681 * @return The {@link PhoneAccount}. 682 */ build()683 public PhoneAccount build() { 684 // If no supported URI schemes were defined, assume "tel" is supported. 685 if (mSupportedUriSchemes.isEmpty()) { 686 addSupportedUriScheme(SCHEME_TEL); 687 } 688 689 return new PhoneAccount( 690 mAccountHandle, 691 mAddress, 692 mSubscriptionAddress, 693 mCapabilities, 694 mIcon, 695 mHighlightColor, 696 mLabel, 697 mShortDescription, 698 mSupportedUriSchemes, 699 mExtras, 700 mSupportedAudioRoutes, 701 mIsEnabled, 702 mGroupId); 703 } 704 } 705 PhoneAccount( PhoneAccountHandle account, Uri address, Uri subscriptionAddress, int capabilities, Icon icon, int highlightColor, CharSequence label, CharSequence shortDescription, List<String> supportedUriSchemes, Bundle extras, int supportedAudioRoutes, boolean isEnabled, String groupId)706 private PhoneAccount( 707 PhoneAccountHandle account, 708 Uri address, 709 Uri subscriptionAddress, 710 int capabilities, 711 Icon icon, 712 int highlightColor, 713 CharSequence label, 714 CharSequence shortDescription, 715 List<String> supportedUriSchemes, 716 Bundle extras, 717 int supportedAudioRoutes, 718 boolean isEnabled, 719 String groupId) { 720 mAccountHandle = account; 721 mAddress = address; 722 mSubscriptionAddress = subscriptionAddress; 723 mCapabilities = capabilities; 724 mIcon = icon; 725 mHighlightColor = highlightColor; 726 mLabel = label; 727 mShortDescription = shortDescription; 728 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 729 mExtras = extras; 730 mSupportedAudioRoutes = supportedAudioRoutes; 731 mIsEnabled = isEnabled; 732 mGroupId = groupId; 733 } 734 builder( PhoneAccountHandle accountHandle, CharSequence label)735 public static Builder builder( 736 PhoneAccountHandle accountHandle, 737 CharSequence label) { 738 return new Builder(accountHandle, label); 739 } 740 741 /** 742 * Returns a builder initialized with the current {@link PhoneAccount} instance. 743 * 744 * @return The builder. 745 */ toBuilder()746 public Builder toBuilder() { return new Builder(this); } 747 748 /** 749 * The unique identifier of this {@code PhoneAccount}. 750 * 751 * @return A {@code PhoneAccountHandle}. 752 */ getAccountHandle()753 public PhoneAccountHandle getAccountHandle() { 754 return mAccountHandle; 755 } 756 757 /** 758 * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This 759 * represents the destination from which outgoing calls using this {@code PhoneAccount} 760 * will appear to come, if applicable, and the destination to which incoming calls using this 761 * {@code PhoneAccount} may be addressed. 762 * 763 * @return A address expressed as a {@code Uri}, for example, a phone number. 764 */ getAddress()765 public Uri getAddress() { 766 return mAddress; 767 } 768 769 /** 770 * The raw callback number used for this {@code PhoneAccount}, as distinct from 771 * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered 772 * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration 773 * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} 774 * has been used to alter the callback number. 775 * <p> 776 * 777 * @return The subscription number, suitable for display to the user. 778 */ getSubscriptionAddress()779 public Uri getSubscriptionAddress() { 780 return mSubscriptionAddress; 781 } 782 783 /** 784 * The capabilities of this {@code PhoneAccount}. 785 * 786 * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities. 787 */ getCapabilities()788 public int getCapabilities() { 789 return mCapabilities; 790 } 791 792 /** 793 * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in 794 * bit mask. 795 * 796 * @param capability The capabilities to check. 797 * @return {@code true} if the phone account has the capability. 798 */ hasCapabilities(int capability)799 public boolean hasCapabilities(int capability) { 800 return (mCapabilities & capability) == capability; 801 } 802 803 /** 804 * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask. 805 * 806 * @param route The routes to check. 807 * @return {@code true} if the phone account has the routes. 808 * @hide 809 */ hasAudioRoutes(int routes)810 public boolean hasAudioRoutes(int routes) { 811 return (mSupportedAudioRoutes & routes) == routes; 812 } 813 814 /** 815 * A short label describing a {@code PhoneAccount}. 816 * 817 * @return A label for this {@code PhoneAccount}. 818 */ getLabel()819 public CharSequence getLabel() { 820 return mLabel; 821 } 822 823 /** 824 * A short paragraph describing this {@code PhoneAccount}. 825 * 826 * @return A description for this {@code PhoneAccount}. 827 */ getShortDescription()828 public CharSequence getShortDescription() { 829 return mShortDescription; 830 } 831 832 /** 833 * The URI schemes supported by this {@code PhoneAccount}. 834 * 835 * @return The URI schemes. 836 */ getSupportedUriSchemes()837 public List<String> getSupportedUriSchemes() { 838 return mSupportedUriSchemes; 839 } 840 841 /** 842 * The extras associated with this {@code PhoneAccount}. 843 * <p> 844 * A {@link ConnectionService} may provide implementation specific information about the 845 * {@link PhoneAccount} via the extras. 846 * 847 * @return The extras. 848 */ getExtras()849 public Bundle getExtras() { 850 return mExtras; 851 } 852 853 /** 854 * The audio routes supported by this {@code PhoneAccount}. 855 * 856 * @hide 857 */ getSupportedAudioRoutes()858 public int getSupportedAudioRoutes() { 859 return mSupportedAudioRoutes; 860 } 861 862 /** 863 * The icon to represent this {@code PhoneAccount}. 864 * 865 * @return The icon. 866 */ getIcon()867 public Icon getIcon() { 868 return mIcon; 869 } 870 871 /** 872 * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only 873 * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}. 874 * 875 * @return {@code true} if the account is enabled by the user, {@code false} otherwise. 876 */ isEnabled()877 public boolean isEnabled() { 878 return mIsEnabled; 879 } 880 881 /** 882 * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an 883 * empty {@link String} if the {@link PhoneAccount} is not in a group. If this 884 * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered 885 * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced, 886 * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}. 887 * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced. 888 * 889 * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group. 890 * @hide 891 */ getGroupId()892 public String getGroupId() { 893 return mGroupId; 894 } 895 896 /** 897 * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI 898 * scheme. 899 * 900 * @param uriScheme The URI scheme to check. 901 * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the 902 * specified URI scheme. 903 */ supportsUriScheme(String uriScheme)904 public boolean supportsUriScheme(String uriScheme) { 905 if (mSupportedUriSchemes == null || uriScheme == null) { 906 return false; 907 } 908 909 for (String scheme : mSupportedUriSchemes) { 910 if (scheme != null && scheme.equals(uriScheme)) { 911 return true; 912 } 913 } 914 return false; 915 } 916 917 /** 918 * A highlight color to use in displaying information about this {@code PhoneAccount}. 919 * 920 * @return A hexadecimal color value. 921 */ getHighlightColor()922 public int getHighlightColor() { 923 return mHighlightColor; 924 } 925 926 /** 927 * Sets the enabled state of the phone account. 928 * @hide 929 */ setIsEnabled(boolean isEnabled)930 public void setIsEnabled(boolean isEnabled) { 931 mIsEnabled = isEnabled; 932 } 933 934 /** 935 * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise. 936 * @hide 937 */ isSelfManaged()938 public boolean isSelfManaged() { 939 return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED; 940 } 941 942 // 943 // Parcelable implementation 944 // 945 946 @Override describeContents()947 public int describeContents() { 948 return 0; 949 } 950 951 @Override writeToParcel(Parcel out, int flags)952 public void writeToParcel(Parcel out, int flags) { 953 if (mAccountHandle == null) { 954 out.writeInt(0); 955 } else { 956 out.writeInt(1); 957 mAccountHandle.writeToParcel(out, flags); 958 } 959 if (mAddress == null) { 960 out.writeInt(0); 961 } else { 962 out.writeInt(1); 963 mAddress.writeToParcel(out, flags); 964 } 965 if (mSubscriptionAddress == null) { 966 out.writeInt(0); 967 } else { 968 out.writeInt(1); 969 mSubscriptionAddress.writeToParcel(out, flags); 970 } 971 out.writeInt(mCapabilities); 972 out.writeInt(mHighlightColor); 973 out.writeCharSequence(mLabel); 974 out.writeCharSequence(mShortDescription); 975 out.writeStringList(mSupportedUriSchemes); 976 977 if (mIcon == null) { 978 out.writeInt(0); 979 } else { 980 out.writeInt(1); 981 mIcon.writeToParcel(out, flags); 982 } 983 out.writeByte((byte) (mIsEnabled ? 1 : 0)); 984 out.writeBundle(mExtras); 985 out.writeString(mGroupId); 986 out.writeInt(mSupportedAudioRoutes); 987 } 988 989 public static final @android.annotation.NonNull Creator<PhoneAccount> CREATOR 990 = new Creator<PhoneAccount>() { 991 @Override 992 public PhoneAccount createFromParcel(Parcel in) { 993 return new PhoneAccount(in); 994 } 995 996 @Override 997 public PhoneAccount[] newArray(int size) { 998 return new PhoneAccount[size]; 999 } 1000 }; 1001 PhoneAccount(Parcel in)1002 private PhoneAccount(Parcel in) { 1003 if (in.readInt() > 0) { 1004 mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in); 1005 } else { 1006 mAccountHandle = null; 1007 } 1008 if (in.readInt() > 0) { 1009 mAddress = Uri.CREATOR.createFromParcel(in); 1010 } else { 1011 mAddress = null; 1012 } 1013 if (in.readInt() > 0) { 1014 mSubscriptionAddress = Uri.CREATOR.createFromParcel(in); 1015 } else { 1016 mSubscriptionAddress = null; 1017 } 1018 mCapabilities = in.readInt(); 1019 mHighlightColor = in.readInt(); 1020 mLabel = in.readCharSequence(); 1021 mShortDescription = in.readCharSequence(); 1022 mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList()); 1023 if (in.readInt() > 0) { 1024 mIcon = Icon.CREATOR.createFromParcel(in); 1025 } else { 1026 mIcon = null; 1027 } 1028 mIsEnabled = in.readByte() == 1; 1029 mExtras = in.readBundle(); 1030 mGroupId = in.readString(); 1031 mSupportedAudioRoutes = in.readInt(); 1032 } 1033 1034 @Override toString()1035 public String toString() { 1036 StringBuilder sb = new StringBuilder().append("[[") 1037 .append(mIsEnabled ? 'X' : ' ') 1038 .append("] PhoneAccount: ") 1039 .append(mAccountHandle) 1040 .append(" Capabilities: ") 1041 .append(capabilitiesToString()) 1042 .append(" Audio Routes: ") 1043 .append(audioRoutesToString()) 1044 .append(" Schemes: "); 1045 for (String scheme : mSupportedUriSchemes) { 1046 sb.append(scheme) 1047 .append(" "); 1048 } 1049 sb.append(" Extras: "); 1050 sb.append(mExtras); 1051 sb.append(" GroupId: "); 1052 sb.append(Log.pii(mGroupId)); 1053 sb.append("]"); 1054 return sb.toString(); 1055 } 1056 1057 /** 1058 * Generates a string representation of a capabilities bitmask. 1059 * 1060 * @return String representation of the capabilities bitmask. 1061 * @hide 1062 */ capabilitiesToString()1063 public String capabilitiesToString() { 1064 StringBuilder sb = new StringBuilder(); 1065 if (hasCapabilities(CAPABILITY_SELF_MANAGED)) { 1066 sb.append("SelfManaged "); 1067 } 1068 if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) { 1069 sb.append("SuppVideo "); 1070 } 1071 if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) { 1072 sb.append("Video "); 1073 } 1074 if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) { 1075 sb.append("Presence "); 1076 } 1077 if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) { 1078 sb.append("CallProvider "); 1079 } 1080 if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) { 1081 sb.append("CallSubject "); 1082 } 1083 if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) { 1084 sb.append("ConnectionMgr "); 1085 } 1086 if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) { 1087 sb.append("EmergOnly "); 1088 } 1089 if (hasCapabilities(CAPABILITY_MULTI_USER)) { 1090 sb.append("MultiUser "); 1091 } 1092 if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) { 1093 sb.append("PlaceEmerg "); 1094 } 1095 if (hasCapabilities(CAPABILITY_EMERGENCY_PREFERRED)) { 1096 sb.append("EmerPrefer "); 1097 } 1098 if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) { 1099 sb.append("EmergVideo "); 1100 } 1101 if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) { 1102 sb.append("SimSub "); 1103 } 1104 if (hasCapabilities(CAPABILITY_RTT)) { 1105 sb.append("Rtt"); 1106 } 1107 if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) { 1108 sb.append("AdhocConf"); 1109 } 1110 if (hasCapabilities(CAPABILITY_CALL_COMPOSER)) { 1111 sb.append("CallComposer "); 1112 } 1113 return sb.toString(); 1114 } 1115 audioRoutesToString()1116 private String audioRoutesToString() { 1117 StringBuilder sb = new StringBuilder(); 1118 1119 if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) { 1120 sb.append("B"); 1121 } 1122 if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) { 1123 sb.append("E"); 1124 } 1125 if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) { 1126 sb.append("S"); 1127 } 1128 if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) { 1129 sb.append("W"); 1130 } 1131 1132 return sb.toString(); 1133 } 1134 1135 /** 1136 * Determines if two {@link Bundle}s are equal. 1137 * @param extras First {@link Bundle} to check. 1138 * @param newExtras {@link Bundle} to compare against. 1139 * @return {@code true} if the {@link Bundle}s are equal, {@code false} otherwise. 1140 */ areBundlesEqual(Bundle extras, Bundle newExtras)1141 private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) { 1142 if (extras == null || newExtras == null) { 1143 return extras == newExtras; 1144 } 1145 1146 if (extras.size() != newExtras.size()) { 1147 return false; 1148 } 1149 1150 for(String key : extras.keySet()) { 1151 if (key != null) { 1152 final Object value = extras.get(key); 1153 final Object newValue = newExtras.get(key); 1154 if (!Objects.equals(value, newValue)) { 1155 return false; 1156 } 1157 } 1158 } 1159 return true; 1160 } 1161 } 1162