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 /** 384 * Flag indicating that this {@link PhoneAccount} provides SIM-based voice calls, potentially as 385 * an over-the-top solution such as wi-fi calling. 386 * 387 * <p>Similar to {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}, this capability indicates this 388 * {@link PhoneAccount} has the ability to make voice calls (but not necessarily at this time). 389 * Whether this {@link PhoneAccount} can make a voice call is ultimately controlled by {@link 390 * #CAPABILITY_VOICE_CALLING_AVAILABLE}, which indicates whether this {@link PhoneAccount} is 391 * currently capable of making a voice call. Consider a case where, for example, a {@link 392 * PhoneAccount} supports making voice calls (e.g. {@link 393 * #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}), but a current lack of network connectivity 394 * prevents voice calls from being made (e.g. {@link #CAPABILITY_VOICE_CALLING_AVAILABLE}). 395 * 396 * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link 397 * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the 398 * associated requirements. 399 * 400 * @see #CAPABILITY_VOICE_CALLING_AVAILABLE 401 * @see #getCapabilities 402 */ 403 public static final int CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS = 0x10000; 404 405 /** 406 * Flag indicating that this {@link PhoneAccount} is <em>currently</em> able to place SIM-based 407 * voice calls, similar to {@link #CAPABILITY_VIDEO_CALLING}. 408 * 409 * <p>See also {@link #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}, which indicates whether 410 * the {@code PhoneAccount} supports placing SIM-based voice calls or not. 411 * 412 * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link 413 * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the 414 * associated requirements. 415 * 416 * @see #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS 417 * @see #getCapabilities 418 */ 419 public static final int CAPABILITY_VOICE_CALLING_AVAILABLE = 0x20000; 420 421 422 /** 423 * Flag indicating that this {@link PhoneAccount} supports the use TelecomManager APIs that 424 * utilize {@link android.os.OutcomeReceiver}s or {@link java.util.function.Consumer}s. 425 * Be aware, if this capability is set, {@link #CAPABILITY_SELF_MANAGED} will be amended by 426 * Telecom when this {@link PhoneAccount} is registered via 427 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}. 428 * 429 * <p> 430 * {@link android.os.OutcomeReceiver}s and {@link java.util.function.Consumer}s represent 431 * transactional operations because the operation can succeed or fail. An app wishing to use 432 * transactional operations should define behavior for a successful and failed TelecomManager 433 * API call. 434 * 435 * @see #CAPABILITY_SELF_MANAGED 436 * @see #getCapabilities 437 */ 438 public static final int CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS = 0x40000; 439 440 /** 441 * Flag indicating that this voip app {@link PhoneAccount} supports the call streaming session 442 * to stream call audio to another remote device via streaming app. 443 * 444 * @see #getCapabilities 445 */ 446 public static final int CAPABILITY_SUPPORTS_CALL_STREAMING = 0x80000; 447 448 /* NEXT CAPABILITY: [0x100000, 0x200000, 0x400000] */ 449 450 /** 451 * URI scheme for telephone number URIs. 452 */ 453 public static final String SCHEME_TEL = "tel"; 454 455 /** 456 * URI scheme for voicemail URIs. 457 */ 458 public static final String SCHEME_VOICEMAIL = "voicemail"; 459 460 /** 461 * URI scheme for SIP URIs. 462 */ 463 public static final String SCHEME_SIP = "sip"; 464 465 /** 466 * Indicating no icon tint is set. 467 * @hide 468 */ 469 public static final int NO_ICON_TINT = 0; 470 471 /** 472 * Indicating no hightlight color is set. 473 */ 474 public static final int NO_HIGHLIGHT_COLOR = 0; 475 476 /** 477 * Indicating no resource ID is set. 478 */ 479 public static final int NO_RESOURCE_ID = -1; 480 481 private final PhoneAccountHandle mAccountHandle; 482 private final Uri mAddress; 483 private final Uri mSubscriptionAddress; 484 private final int mCapabilities; 485 private final int mHighlightColor; 486 private final CharSequence mLabel; 487 private final CharSequence mShortDescription; 488 private final List<String> mSupportedUriSchemes; 489 private final int mSupportedAudioRoutes; 490 private final Icon mIcon; 491 private final Bundle mExtras; 492 private boolean mIsEnabled; 493 private String mGroupId; 494 495 @Override equals(Object o)496 public boolean equals(Object o) { 497 if (this == o) return true; 498 if (o == null || getClass() != o.getClass()) return false; 499 PhoneAccount that = (PhoneAccount) o; 500 return mCapabilities == that.mCapabilities && 501 mHighlightColor == that.mHighlightColor && 502 mSupportedAudioRoutes == that.mSupportedAudioRoutes && 503 mIsEnabled == that.mIsEnabled && 504 Objects.equals(mAccountHandle, that.mAccountHandle) && 505 Objects.equals(mAddress, that.mAddress) && 506 Objects.equals(mSubscriptionAddress, that.mSubscriptionAddress) && 507 Objects.equals(mLabel, that.mLabel) && 508 Objects.equals(mShortDescription, that.mShortDescription) && 509 Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) && 510 areBundlesEqual(mExtras, that.mExtras) && 511 Objects.equals(mGroupId, that.mGroupId); 512 } 513 514 @Override hashCode()515 public int hashCode() { 516 return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities, 517 mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes, 518 mSupportedAudioRoutes, 519 mExtras, mIsEnabled, mGroupId); 520 } 521 522 /** 523 * Helper class for creating a {@link PhoneAccount}. 524 */ 525 public static class Builder { 526 527 private PhoneAccountHandle mAccountHandle; 528 private Uri mAddress; 529 private Uri mSubscriptionAddress; 530 private int mCapabilities; 531 private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; 532 private int mHighlightColor = NO_HIGHLIGHT_COLOR; 533 private CharSequence mLabel; 534 private CharSequence mShortDescription; 535 private List<String> mSupportedUriSchemes = new ArrayList<String>(); 536 private Icon mIcon; 537 private Bundle mExtras; 538 private boolean mIsEnabled = false; 539 private String mGroupId = ""; 540 541 /** 542 * Creates a builder with the specified {@link PhoneAccountHandle} and label. 543 * <p> 544 * Note: each CharSequence or String field is limited to 256 characters. This check is 545 * enforced when registering the PhoneAccount via 546 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 547 * {@link IllegalArgumentException} to be thrown if the character field limit is over 256. 548 */ Builder(PhoneAccountHandle accountHandle, CharSequence label)549 public Builder(PhoneAccountHandle accountHandle, CharSequence label) { 550 this.mAccountHandle = accountHandle; 551 this.mLabel = label; 552 } 553 554 /** 555 * Creates an instance of the {@link PhoneAccount.Builder} from an existing 556 * {@link PhoneAccount}. 557 * 558 * @param phoneAccount The {@link PhoneAccount} used to initialize the builder. 559 */ Builder(PhoneAccount phoneAccount)560 public Builder(PhoneAccount phoneAccount) { 561 mAccountHandle = phoneAccount.getAccountHandle(); 562 mAddress = phoneAccount.getAddress(); 563 mSubscriptionAddress = phoneAccount.getSubscriptionAddress(); 564 mCapabilities = phoneAccount.getCapabilities(); 565 mHighlightColor = phoneAccount.getHighlightColor(); 566 mLabel = phoneAccount.getLabel(); 567 mShortDescription = phoneAccount.getShortDescription(); 568 mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes()); 569 mIcon = phoneAccount.getIcon(); 570 mIsEnabled = phoneAccount.isEnabled(); 571 mExtras = phoneAccount.getExtras(); 572 mGroupId = phoneAccount.getGroupId(); 573 mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes(); 574 } 575 576 /** 577 * Sets the label. See {@link PhoneAccount#getLabel()}. 578 * <p> 579 * Note: Each CharSequence or String field is limited to 256 characters. This check is 580 * enforced when registering the PhoneAccount via 581 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 582 * {@link IllegalArgumentException} to be thrown if the character field limit is over 256. 583 * 584 * @param label The label of the phone account. 585 * @return The builder. 586 * @hide 587 */ setLabel(CharSequence label)588 public Builder setLabel(CharSequence label) { 589 this.mLabel = label; 590 return this; 591 } 592 593 /** 594 * Sets the address. See {@link PhoneAccount#getAddress}. 595 * <p> 596 * Note: The entire URI value is limited to 256 characters. This check is 597 * enforced when registering the PhoneAccount via 598 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 599 * {@link IllegalArgumentException} to be thrown if URI is over 256. 600 * 601 * @param value The address of the phone account. 602 * @return The builder. 603 */ setAddress(Uri value)604 public Builder setAddress(Uri value) { 605 this.mAddress = value; 606 return this; 607 } 608 609 /** 610 * Sets the subscription address. See {@link PhoneAccount#getSubscriptionAddress}. 611 * 612 * @param value The subscription address. 613 * @return The builder. 614 */ setSubscriptionAddress(Uri value)615 public Builder setSubscriptionAddress(Uri value) { 616 this.mSubscriptionAddress = value; 617 return this; 618 } 619 620 /** 621 * Sets the capabilities. See {@link PhoneAccount#getCapabilities}. 622 * 623 * @param value The capabilities to set. 624 * @return The builder. 625 */ setCapabilities(int value)626 public Builder setCapabilities(int value) { 627 this.mCapabilities = value; 628 return this; 629 } 630 631 /** 632 * Sets the icon. See {@link PhoneAccount#getIcon}. 633 * <p> 634 * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory. 635 * This check is enforced when registering the PhoneAccount via 636 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} 637 * 638 * @param icon The icon to set. 639 */ setIcon(Icon icon)640 public Builder setIcon(Icon icon) { 641 mIcon = icon; 642 return this; 643 } 644 645 /** 646 * Sets the highlight color. See {@link PhoneAccount#getHighlightColor}. 647 * 648 * @param value The highlight color. 649 * @return The builder. 650 */ setHighlightColor(int value)651 public Builder setHighlightColor(int value) { 652 this.mHighlightColor = value; 653 return this; 654 } 655 656 /** 657 * Sets the short description. See {@link PhoneAccount#getShortDescription}. 658 * <p> 659 * Note: Each CharSequence or String field is limited to 256 characters. This check is 660 * enforced when registering the PhoneAccount via 661 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 662 * {@link IllegalArgumentException} to be thrown if the character field limit is over 256. 663 * 664 * @param value The short description. 665 * @return The builder. 666 */ setShortDescription(CharSequence value)667 public Builder setShortDescription(CharSequence value) { 668 this.mShortDescription = value; 669 return this; 670 } 671 672 /** 673 * Specifies an additional URI scheme supported by the {@link PhoneAccount}. 674 * 675 * <p> 676 * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will 677 * cause an {@link IllegalArgumentException} to be thrown when the account is registered. 678 * 679 * @param uriScheme The URI scheme. 680 * @return The builder. 681 */ addSupportedUriScheme(String uriScheme)682 public Builder addSupportedUriScheme(String uriScheme) { 683 if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) { 684 this.mSupportedUriSchemes.add(uriScheme); 685 } 686 return this; 687 } 688 689 /** 690 * Specifies the URI schemes supported by the {@link PhoneAccount}. 691 * 692 * <p> 693 * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is 694 * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any 695 * scheme will cause an {@link IllegalArgumentException} to be thrown when the account 696 * is registered. 697 * 698 * @param uriSchemes The URI schemes. 699 * @return The builder. 700 */ setSupportedUriSchemes(List<String> uriSchemes)701 public Builder setSupportedUriSchemes(List<String> uriSchemes) { 702 mSupportedUriSchemes.clear(); 703 704 if (uriSchemes != null && !uriSchemes.isEmpty()) { 705 for (String uriScheme : uriSchemes) { 706 addSupportedUriScheme(uriScheme); 707 } 708 } 709 return this; 710 } 711 712 /** 713 * Specifies the extras associated with the {@link PhoneAccount}. 714 * <p> 715 * {@code PhoneAccount}s only support extra values of type: {@link String}, {@link Integer}, 716 * and {@link Boolean}. Extras which are not of these types are ignored. 717 * <p> 718 * Note: Each Bundle (Key, Value) String field is limited to 256 characters. Additionally, 719 * the bundle is limited to 100 (Key, Value) pairs total. This check is 720 * enforced when registering the PhoneAccount via 721 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 722 * {@link IllegalArgumentException} to be thrown if the character field limit is over 256 723 * or more than 100 (Key, Value) pairs are in the Bundle. 724 * 725 * @param extras 726 * @return 727 */ setExtras(Bundle extras)728 public Builder setExtras(Bundle extras) { 729 mExtras = extras; 730 return this; 731 } 732 733 /** 734 * Sets the enabled state of the phone account. 735 * 736 * @param isEnabled The enabled state. 737 * @return The builder. 738 * @hide 739 */ setIsEnabled(boolean isEnabled)740 public Builder setIsEnabled(boolean isEnabled) { 741 mIsEnabled = isEnabled; 742 return this; 743 } 744 745 /** 746 * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is 747 * registered to Telecom, it will replace another {@link PhoneAccount} that is already 748 * registered in Telecom and take on the current user defaults and enabled status. There can 749 * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a 750 * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only 751 * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced. 752 * <p> 753 * Note: This is an API specific to the Telephony stack; the group Id will be ignored for 754 * callers not holding the correct permission. 755 * <p> 756 * Additionally, each CharSequence or String field is limited to 256 characters. 757 * This check is enforced when registering the PhoneAccount via 758 * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an 759 * {@link IllegalArgumentException} to be thrown if the character field limit is over 256. 760 * 761 * @param groupId The group Id of the {@link PhoneAccount} that will replace any other 762 * registered {@link PhoneAccount} in Telecom with the same Group Id. 763 * @return The builder 764 * @hide 765 */ 766 @SystemApi 767 @RequiresPermission(MODIFY_PHONE_STATE) setGroupId(@onNull String groupId)768 public @NonNull Builder setGroupId(@NonNull String groupId) { 769 if (groupId != null) { 770 mGroupId = groupId; 771 } else { 772 mGroupId = ""; 773 } 774 return this; 775 } 776 777 /** 778 * Sets the audio routes supported by this {@link PhoneAccount}. 779 * 780 * @param routes bit mask of available routes. 781 * @return The builder. 782 * @hide 783 */ setSupportedAudioRoutes(int routes)784 public Builder setSupportedAudioRoutes(int routes) { 785 mSupportedAudioRoutes = routes; 786 return this; 787 } 788 789 /** 790 * Creates an instance of a {@link PhoneAccount} based on the current builder settings. 791 * 792 * @return The {@link PhoneAccount}. 793 */ build()794 public PhoneAccount build() { 795 // If no supported URI schemes were defined, assume "tel" is supported. 796 if (mSupportedUriSchemes.isEmpty()) { 797 addSupportedUriScheme(SCHEME_TEL); 798 } 799 800 return new PhoneAccount( 801 mAccountHandle, 802 mAddress, 803 mSubscriptionAddress, 804 mCapabilities, 805 mIcon, 806 mHighlightColor, 807 mLabel, 808 mShortDescription, 809 mSupportedUriSchemes, 810 mExtras, 811 mSupportedAudioRoutes, 812 mIsEnabled, 813 mGroupId); 814 } 815 } 816 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)817 private PhoneAccount( 818 PhoneAccountHandle account, 819 Uri address, 820 Uri subscriptionAddress, 821 int capabilities, 822 Icon icon, 823 int highlightColor, 824 CharSequence label, 825 CharSequence shortDescription, 826 List<String> supportedUriSchemes, 827 Bundle extras, 828 int supportedAudioRoutes, 829 boolean isEnabled, 830 String groupId) { 831 mAccountHandle = account; 832 mAddress = address; 833 mSubscriptionAddress = subscriptionAddress; 834 mCapabilities = capabilities; 835 mIcon = icon; 836 mHighlightColor = highlightColor; 837 mLabel = label; 838 mShortDescription = shortDescription; 839 mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes); 840 mExtras = extras; 841 mSupportedAudioRoutes = supportedAudioRoutes; 842 mIsEnabled = isEnabled; 843 mGroupId = groupId; 844 } 845 builder( PhoneAccountHandle accountHandle, CharSequence label)846 public static Builder builder( 847 PhoneAccountHandle accountHandle, 848 CharSequence label) { 849 return new Builder(accountHandle, label); 850 } 851 852 /** 853 * Returns a builder initialized with the current {@link PhoneAccount} instance. 854 * 855 * @return The builder. 856 */ toBuilder()857 public Builder toBuilder() { return new Builder(this); } 858 859 /** 860 * The unique identifier of this {@code PhoneAccount}. 861 * 862 * @return A {@code PhoneAccountHandle}. 863 */ getAccountHandle()864 public PhoneAccountHandle getAccountHandle() { 865 return mAccountHandle; 866 } 867 868 /** 869 * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This 870 * represents the destination from which outgoing calls using this {@code PhoneAccount} 871 * will appear to come, if applicable, and the destination to which incoming calls using this 872 * {@code PhoneAccount} may be addressed. 873 * 874 * @return A address expressed as a {@code Uri}, for example, a phone number. 875 */ getAddress()876 public Uri getAddress() { 877 return mAddress; 878 } 879 880 /** 881 * The raw callback number used for this {@code PhoneAccount}, as distinct from 882 * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered 883 * as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration 884 * where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)} 885 * has been used to alter the callback number. 886 * <p> 887 * 888 * @return The subscription number, suitable for display to the user. 889 */ getSubscriptionAddress()890 public Uri getSubscriptionAddress() { 891 return mSubscriptionAddress; 892 } 893 894 /** 895 * The capabilities of this {@code PhoneAccount}. 896 * 897 * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities. 898 */ getCapabilities()899 public int getCapabilities() { 900 return mCapabilities; 901 } 902 903 /** 904 * Determines if this {@code PhoneAccount} has a capabilities specified by the passed in 905 * bit mask. 906 * 907 * @param capability The capabilities to check. 908 * @return {@code true} if the phone account has the capability. 909 */ hasCapabilities(int capability)910 public boolean hasCapabilities(int capability) { 911 return (mCapabilities & capability) == capability; 912 } 913 914 /** 915 * Determines if this {@code PhoneAccount} has routes specified by the passed in bit mask. 916 * 917 * @param route The routes to check. 918 * @return {@code true} if the phone account has the routes. 919 * @hide 920 */ hasAudioRoutes(int routes)921 public boolean hasAudioRoutes(int routes) { 922 return (mSupportedAudioRoutes & routes) == routes; 923 } 924 925 /** 926 * A short label describing a {@code PhoneAccount}. 927 * 928 * @return A label for this {@code PhoneAccount}. 929 */ getLabel()930 public CharSequence getLabel() { 931 return mLabel; 932 } 933 934 /** 935 * A short paragraph describing this {@code PhoneAccount}. 936 * 937 * @return A description for this {@code PhoneAccount}. 938 */ getShortDescription()939 public CharSequence getShortDescription() { 940 return mShortDescription; 941 } 942 943 /** 944 * The URI schemes supported by this {@code PhoneAccount}. 945 * 946 * @return The URI schemes. 947 */ getSupportedUriSchemes()948 public List<String> getSupportedUriSchemes() { 949 return mSupportedUriSchemes; 950 } 951 952 /** 953 * The extras associated with this {@code PhoneAccount}. 954 * <p> 955 * A {@link ConnectionService} may provide implementation specific information about the 956 * {@link PhoneAccount} via the extras. 957 * 958 * @return The extras. 959 */ getExtras()960 public Bundle getExtras() { 961 return mExtras; 962 } 963 964 /** 965 * The audio routes supported by this {@code PhoneAccount}. 966 * 967 * @hide 968 */ getSupportedAudioRoutes()969 public int getSupportedAudioRoutes() { 970 return mSupportedAudioRoutes; 971 } 972 973 /** 974 * The icon to represent this {@code PhoneAccount}. 975 * 976 * @return The icon. 977 */ getIcon()978 public Icon getIcon() { 979 return mIcon; 980 } 981 982 /** 983 * Indicates whether the user has enabled this {@code PhoneAccount} or not. This value is only 984 * populated for {@code PhoneAccount}s returned by {@link TelecomManager#getPhoneAccount}. 985 * 986 * @return {@code true} if the account is enabled by the user, {@code false} otherwise. 987 */ isEnabled()988 public boolean isEnabled() { 989 return mIsEnabled; 990 } 991 992 /** 993 * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an 994 * empty {@link String} if the {@link PhoneAccount} is not in a group. If this 995 * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered 996 * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced, 997 * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}. 998 * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced. 999 * 1000 * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group. 1001 * @hide 1002 */ getGroupId()1003 public String getGroupId() { 1004 return mGroupId; 1005 } 1006 1007 /** 1008 * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI 1009 * scheme. 1010 * 1011 * @param uriScheme The URI scheme to check. 1012 * @return {@code true} if the {@code PhoneAccount} supports calls to/from addresses with the 1013 * specified URI scheme. 1014 */ supportsUriScheme(String uriScheme)1015 public boolean supportsUriScheme(String uriScheme) { 1016 if (mSupportedUriSchemes == null || uriScheme == null) { 1017 return false; 1018 } 1019 1020 for (String scheme : mSupportedUriSchemes) { 1021 if (scheme != null && scheme.equals(uriScheme)) { 1022 return true; 1023 } 1024 } 1025 return false; 1026 } 1027 1028 /** 1029 * A highlight color to use in displaying information about this {@code PhoneAccount}. 1030 * 1031 * @return A hexadecimal color value. 1032 */ getHighlightColor()1033 public int getHighlightColor() { 1034 return mHighlightColor; 1035 } 1036 1037 /** 1038 * Sets the enabled state of the phone account. 1039 * @hide 1040 */ setIsEnabled(boolean isEnabled)1041 public void setIsEnabled(boolean isEnabled) { 1042 mIsEnabled = isEnabled; 1043 } 1044 1045 /** 1046 * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise. 1047 * @hide 1048 */ isSelfManaged()1049 public boolean isSelfManaged() { 1050 return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED; 1051 } 1052 1053 // 1054 // Parcelable implementation 1055 // 1056 1057 @Override describeContents()1058 public int describeContents() { 1059 return 0; 1060 } 1061 1062 @Override writeToParcel(Parcel out, int flags)1063 public void writeToParcel(Parcel out, int flags) { 1064 if (mAccountHandle == null) { 1065 out.writeInt(0); 1066 } else { 1067 out.writeInt(1); 1068 mAccountHandle.writeToParcel(out, flags); 1069 } 1070 if (mAddress == null) { 1071 out.writeInt(0); 1072 } else { 1073 out.writeInt(1); 1074 mAddress.writeToParcel(out, flags); 1075 } 1076 if (mSubscriptionAddress == null) { 1077 out.writeInt(0); 1078 } else { 1079 out.writeInt(1); 1080 mSubscriptionAddress.writeToParcel(out, flags); 1081 } 1082 out.writeInt(mCapabilities); 1083 out.writeInt(mHighlightColor); 1084 out.writeCharSequence(mLabel); 1085 out.writeCharSequence(mShortDescription); 1086 out.writeStringList(mSupportedUriSchemes); 1087 1088 if (mIcon == null) { 1089 out.writeInt(0); 1090 } else { 1091 out.writeInt(1); 1092 mIcon.writeToParcel(out, flags); 1093 } 1094 out.writeByte((byte) (mIsEnabled ? 1 : 0)); 1095 out.writeBundle(mExtras); 1096 out.writeString(mGroupId); 1097 out.writeInt(mSupportedAudioRoutes); 1098 } 1099 1100 public static final @android.annotation.NonNull Creator<PhoneAccount> CREATOR 1101 = new Creator<PhoneAccount>() { 1102 @Override 1103 public PhoneAccount createFromParcel(Parcel in) { 1104 return new PhoneAccount(in); 1105 } 1106 1107 @Override 1108 public PhoneAccount[] newArray(int size) { 1109 return new PhoneAccount[size]; 1110 } 1111 }; 1112 PhoneAccount(Parcel in)1113 private PhoneAccount(Parcel in) { 1114 if (in.readInt() > 0) { 1115 mAccountHandle = PhoneAccountHandle.CREATOR.createFromParcel(in); 1116 } else { 1117 mAccountHandle = null; 1118 } 1119 if (in.readInt() > 0) { 1120 mAddress = Uri.CREATOR.createFromParcel(in); 1121 } else { 1122 mAddress = null; 1123 } 1124 if (in.readInt() > 0) { 1125 mSubscriptionAddress = Uri.CREATOR.createFromParcel(in); 1126 } else { 1127 mSubscriptionAddress = null; 1128 } 1129 mCapabilities = in.readInt(); 1130 mHighlightColor = in.readInt(); 1131 mLabel = in.readCharSequence(); 1132 mShortDescription = in.readCharSequence(); 1133 mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList()); 1134 if (in.readInt() > 0) { 1135 mIcon = Icon.CREATOR.createFromParcel(in); 1136 } else { 1137 mIcon = null; 1138 } 1139 mIsEnabled = in.readByte() == 1; 1140 mExtras = in.readBundle(); 1141 mGroupId = in.readString(); 1142 mSupportedAudioRoutes = in.readInt(); 1143 } 1144 1145 @Override toString()1146 public String toString() { 1147 StringBuilder sb = new StringBuilder().append("[[") 1148 .append(mIsEnabled ? 'X' : ' ') 1149 .append("] PhoneAccount: ") 1150 .append(mAccountHandle) 1151 .append(" Capabilities: ") 1152 .append(capabilitiesToString()) 1153 .append(" Audio Routes: ") 1154 .append(audioRoutesToString()) 1155 .append(" Schemes: "); 1156 for (String scheme : mSupportedUriSchemes) { 1157 sb.append(scheme) 1158 .append(" "); 1159 } 1160 sb.append(" Extras: "); 1161 sb.append(mExtras); 1162 sb.append(" GroupId: "); 1163 sb.append(Log.pii(mGroupId)); 1164 sb.append("]"); 1165 return sb.toString(); 1166 } 1167 1168 /** 1169 * Generates a string representation of a capabilities bitmask. 1170 * 1171 * @return String representation of the capabilities bitmask. 1172 * @hide 1173 */ capabilitiesToString()1174 public String capabilitiesToString() { 1175 StringBuilder sb = new StringBuilder(); 1176 if (hasCapabilities(CAPABILITY_SELF_MANAGED)) { 1177 sb.append("SelfManaged "); 1178 } 1179 if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) { 1180 sb.append("SuppVideo "); 1181 } 1182 if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) { 1183 sb.append("Video "); 1184 } 1185 if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) { 1186 sb.append("Presence "); 1187 } 1188 if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) { 1189 sb.append("CallProvider "); 1190 } 1191 if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) { 1192 sb.append("CallSubject "); 1193 } 1194 if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) { 1195 sb.append("ConnectionMgr "); 1196 } 1197 if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) { 1198 sb.append("EmergOnly "); 1199 } 1200 if (hasCapabilities(CAPABILITY_MULTI_USER)) { 1201 sb.append("MultiUser "); 1202 } 1203 if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) { 1204 sb.append("PlaceEmerg "); 1205 } 1206 if (hasCapabilities(CAPABILITY_EMERGENCY_PREFERRED)) { 1207 sb.append("EmerPrefer "); 1208 } 1209 if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) { 1210 sb.append("EmergVideo "); 1211 } 1212 if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) { 1213 sb.append("SimSub "); 1214 } 1215 if (hasCapabilities(CAPABILITY_RTT)) { 1216 sb.append("Rtt "); 1217 } 1218 if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) { 1219 sb.append("AdhocConf "); 1220 } 1221 if (hasCapabilities(CAPABILITY_CALL_COMPOSER)) { 1222 sb.append("CallComposer "); 1223 } 1224 if (hasCapabilities(CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS)) { 1225 sb.append("SuppVoice "); 1226 } 1227 if (hasCapabilities(CAPABILITY_VOICE_CALLING_AVAILABLE)) { 1228 sb.append("Voice "); 1229 } 1230 if (hasCapabilities(CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS)) { 1231 sb.append("TransactOps "); 1232 } 1233 if (hasCapabilities(CAPABILITY_SUPPORTS_CALL_STREAMING)) { 1234 sb.append("Stream "); 1235 } 1236 return sb.toString(); 1237 } 1238 audioRoutesToString()1239 private String audioRoutesToString() { 1240 StringBuilder sb = new StringBuilder(); 1241 1242 if (hasAudioRoutes(CallAudioState.ROUTE_BLUETOOTH)) { 1243 sb.append("B"); 1244 } 1245 if (hasAudioRoutes(CallAudioState.ROUTE_EARPIECE)) { 1246 sb.append("E"); 1247 } 1248 if (hasAudioRoutes(CallAudioState.ROUTE_SPEAKER)) { 1249 sb.append("S"); 1250 } 1251 if (hasAudioRoutes(CallAudioState.ROUTE_WIRED_HEADSET)) { 1252 sb.append("W"); 1253 } 1254 1255 return sb.toString(); 1256 } 1257 1258 /** 1259 * Determines if two {@link Bundle}s are equal. 1260 * @param extras First {@link Bundle} to check. 1261 * @param newExtras {@link Bundle} to compare against. 1262 * @return {@code true} if the {@link Bundle}s are equal, {@code false} otherwise. 1263 */ areBundlesEqual(Bundle extras, Bundle newExtras)1264 private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) { 1265 if (extras == null || newExtras == null) { 1266 return extras == newExtras; 1267 } 1268 1269 if (extras.size() != newExtras.size()) { 1270 return false; 1271 } 1272 1273 for(String key : extras.keySet()) { 1274 if (key != null) { 1275 final Object value = extras.get(key); 1276 final Object newValue = newExtras.get(key); 1277 if (!Objects.equals(value, newValue)) { 1278 return false; 1279 } 1280 } 1281 } 1282 return true; 1283 } 1284 } 1285