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