1 package org.robolectric.shadows; 2 3 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 5 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 6 import static android.os.Build.VERSION_CODES.LOLLIPOP; 7 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 8 import static android.os.Build.VERSION_CODES.M; 9 import static android.os.Build.VERSION_CODES.N; 10 import static android.os.Build.VERSION_CODES.O; 11 import static android.os.Build.VERSION_CODES.P; 12 import static android.os.Build.VERSION_CODES.Q; 13 import static android.os.Build.VERSION_CODES.R; 14 import static android.os.Build.VERSION_CODES.S; 15 import static android.os.Build.VERSION_CODES.TIRAMISU; 16 import static android.telephony.PhoneStateListener.LISTEN_CALL_STATE; 17 import static android.telephony.PhoneStateListener.LISTEN_CELL_INFO; 18 import static android.telephony.PhoneStateListener.LISTEN_CELL_LOCATION; 19 import static android.telephony.PhoneStateListener.LISTEN_NONE; 20 import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; 21 import static android.telephony.TelephonyManager.CALL_STATE_IDLE; 22 import static android.telephony.TelephonyManager.CALL_STATE_RINGING; 23 24 import android.Manifest.permission; 25 import android.annotation.CallSuper; 26 import android.app.ActivityThread; 27 import android.app.PendingIntent; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.net.Uri; 31 import android.os.Build; 32 import android.os.Build.VERSION; 33 import android.os.PersistableBundle; 34 import android.os.SystemProperties; 35 import android.telecom.PhoneAccountHandle; 36 import android.telephony.Annotation.NetworkType; 37 import android.telephony.Annotation.OverrideNetworkType; 38 import android.telephony.CellInfo; 39 import android.telephony.CellLocation; 40 import android.telephony.PhoneStateListener; 41 import android.telephony.ServiceState; 42 import android.telephony.SignalStrength; 43 import android.telephony.SubscriptionManager; 44 import android.telephony.TelephonyCallback; 45 import android.telephony.TelephonyCallback.CallStateListener; 46 import android.telephony.TelephonyCallback.CellInfoListener; 47 import android.telephony.TelephonyCallback.CellLocationListener; 48 import android.telephony.TelephonyCallback.DisplayInfoListener; 49 import android.telephony.TelephonyCallback.ServiceStateListener; 50 import android.telephony.TelephonyCallback.SignalStrengthsListener; 51 import android.telephony.TelephonyDisplayInfo; 52 import android.telephony.TelephonyManager; 53 import android.telephony.TelephonyManager.CellInfoCallback; 54 import android.telephony.VisualVoicemailSmsFilterSettings; 55 import android.telephony.emergency.EmergencyNumber; 56 import android.text.TextUtils; 57 import android.util.SparseArray; 58 import android.util.SparseBooleanArray; 59 import android.util.SparseIntArray; 60 import com.google.common.base.Ascii; 61 import com.google.common.base.Preconditions; 62 import com.google.common.base.Predicate; 63 import com.google.common.collect.ImmutableList; 64 import com.google.common.collect.ImmutableMap; 65 import com.google.common.collect.Iterables; 66 import java.util.ArrayList; 67 import java.util.Collections; 68 import java.util.HashMap; 69 import java.util.HashSet; 70 import java.util.List; 71 import java.util.Locale; 72 import java.util.Map; 73 import java.util.Set; 74 import java.util.concurrent.Executor; 75 import org.robolectric.RuntimeEnvironment; 76 import org.robolectric.annotation.HiddenApi; 77 import org.robolectric.annotation.Implementation; 78 import org.robolectric.annotation.Implements; 79 import org.robolectric.annotation.RealObject; 80 import org.robolectric.annotation.Resetter; 81 import org.robolectric.shadow.api.Shadow; 82 import org.robolectric.util.ReflectionHelpers; 83 84 @Implements(value = TelephonyManager.class, looseSignatures = true) 85 public class ShadowTelephonyManager { 86 87 @RealObject protected TelephonyManager realTelephonyManager; 88 89 private final Map<PhoneStateListener, Integer> phoneStateRegistrations = new HashMap<>(); 90 private final /*List<TelephonyCallback>*/ List<Object> telephonyCallbackRegistrations = 91 new ArrayList<>(); 92 private final Map<Integer, String> slotIndexToDeviceId = new HashMap<>(); 93 private final Map<Integer, String> slotIndexToImei = new HashMap<>(); 94 private final Map<Integer, String> slotIndexToMeid = new HashMap<>(); 95 private final Map<PhoneAccountHandle, Boolean> voicemailVibrationEnabledMap = new HashMap<>(); 96 private final Map<PhoneAccountHandle, Uri> voicemailRingtoneUriMap = new HashMap<>(); 97 private final Map<PhoneAccountHandle, TelephonyManager> phoneAccountToTelephonyManagers = 98 new HashMap<>(); 99 private final Map<PhoneAccountHandle, Integer> phoneAccountHandleSubscriptionId = new HashMap<>(); 100 101 private PhoneStateListener lastListener; 102 private /*TelephonyCallback*/ Object lastTelephonyCallback; 103 private int lastEventFlags; 104 105 private String deviceId; 106 private String deviceSoftwareVersion; 107 private String imei; 108 private String meid; 109 private String groupIdLevel1; 110 private String networkOperatorName = ""; 111 private String networkCountryIso; 112 private String networkOperator = ""; 113 private String networkSpecifier = ""; 114 private Locale simLocale; 115 private String simOperator = ""; 116 private String simOperatorName; 117 private String simSerialNumber; 118 private boolean readPhoneStatePermission = true; 119 private int phoneType = TelephonyManager.PHONE_TYPE_GSM; 120 private String line1Number; 121 private int networkType; 122 private int dataNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 123 private int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 124 private List<CellInfo> allCellInfo = Collections.emptyList(); 125 private List<CellInfo> callbackCellInfos = null; 126 private CellLocation cellLocation = null; 127 private int callState = CALL_STATE_IDLE; 128 private int dataState = TelephonyManager.DATA_DISCONNECTED; 129 private int dataActivity = TelephonyManager.DATA_ACTIVITY_NONE; 130 private String incomingPhoneNumber = null; 131 private boolean isSmsCapable = true; 132 private boolean voiceCapable = true; 133 private String voiceMailNumber; 134 private String voiceMailAlphaTag; 135 private int phoneCount = 1; 136 private int activeModemCount = 1; 137 private Map<Integer, TelephonyManager> subscriptionIdsToTelephonyManagers = new HashMap<>(); 138 private PersistableBundle carrierConfig; 139 private ServiceState serviceState; 140 private boolean isNetworkRoaming; 141 private final SparseIntArray simStates = new SparseIntArray(); 142 private final SparseIntArray currentPhoneTypes = new SparseIntArray(); 143 private final SparseArray<List<String>> carrierPackageNames = new SparseArray<>(); 144 private final Map<Integer, String> simCountryIsoMap = new HashMap<>(); 145 private int simCarrierId; 146 private int carrierIdFromSimMccMnc; 147 private String subscriberId; 148 private /*UiccSlotInfo[]*/ Object uiccSlotInfos; 149 private /*UiccCardInfo[]*/ Object uiccCardsInfo = new ArrayList<>(); 150 private String visualVoicemailPackageName = null; 151 private SignalStrength signalStrength; 152 private boolean dataEnabled = false; 153 private final Set<Integer> dataDisabledReasons = new HashSet<>(); 154 private boolean isRttSupported; 155 private boolean isTtyModeSupported; 156 private final SparseBooleanArray subIdToHasCarrierPrivileges = new SparseBooleanArray(); 157 private final List<String> sentDialerSpecialCodes = new ArrayList<>(); 158 private boolean hearingAidCompatibilitySupported = false; 159 private int requestCellInfoUpdateErrorCode = 0; 160 private Throwable requestCellInfoUpdateDetail = null; 161 private Object telephonyDisplayInfo; 162 private boolean isDataConnectionAllowed; 163 private static int callComposerStatus = 0; 164 private VisualVoicemailSmsParams lastVisualVoicemailSmsParams; 165 private VisualVoicemailSmsFilterSettings visualVoicemailSmsFilterSettings; 166 private boolean emergencyCallbackMode; 167 private static Map<Integer, List<EmergencyNumber>> emergencyNumbersList; 168 169 /** 170 * Should be {@link TelephonyManager.BootstrapAuthenticationCallback} but this object was 171 * introduced in Android S, so we are using Object to avoid breaking other SDKs 172 * 173 * <p>XXX Look into using the real types if we're now compiling against S 174 */ 175 private Object callback; 176 177 private /*PhoneCapability*/ Object phoneCapability; 178 179 { resetSimStates()180 resetSimStates(); resetSimCountryIsos()181 resetSimCountryIsos(); 182 } 183 184 @Resetter reset()185 public static void reset() { 186 callComposerStatus = 0; 187 emergencyNumbersList = null; 188 } 189 190 @Implementation(minSdk = S) setCallComposerStatus(int callComposerStatus)191 protected void setCallComposerStatus(int callComposerStatus) { 192 ShadowTelephonyManager.callComposerStatus = callComposerStatus; 193 } 194 195 @Implementation(minSdk = S) 196 @HiddenApi getCallComposerStatus()197 protected int getCallComposerStatus() { 198 return callComposerStatus; 199 } 200 getBootstrapAuthenticationCallback()201 public Object getBootstrapAuthenticationCallback() { 202 return callback; 203 } 204 205 @Implementation(minSdk = S) 206 @HiddenApi bootstrapAuthenticationRequest( Object appType, Object nafId, Object securityProtocol, Object forceBootStrapping, Object e, Object callback)207 public void bootstrapAuthenticationRequest( 208 Object appType, 209 Object nafId, 210 Object securityProtocol, 211 Object forceBootStrapping, 212 Object e, 213 Object callback) { 214 this.callback = callback; 215 } 216 setPhoneCapability( Object phoneCapability)217 public void setPhoneCapability(/*PhoneCapability*/ Object phoneCapability) { 218 this.phoneCapability = phoneCapability; 219 } 220 221 @Implementation(minSdk = S) 222 @HiddenApi getPhoneCapability()223 public /*PhoneCapability*/ Object getPhoneCapability() { 224 return phoneCapability; 225 } 226 227 @Implementation listen(PhoneStateListener listener, int flags)228 protected void listen(PhoneStateListener listener, int flags) { 229 lastListener = listener; 230 lastEventFlags = flags; 231 232 if (flags == LISTEN_NONE) { 233 phoneStateRegistrations.remove(listener); 234 } else { 235 initListener(listener, flags); 236 phoneStateRegistrations.put(listener, flags); 237 } 238 } 239 240 /** 241 * Returns the most recent listener passed to #listen(). 242 * 243 * @return Phone state listener. 244 * @deprecated Avoid using. 245 */ 246 @Deprecated getListener()247 public PhoneStateListener getListener() { 248 return lastListener; 249 } 250 251 /** 252 * Returns the most recent flags passed to #listen(). 253 * 254 * @return Event flags. 255 * @deprecated Avoid using. 256 */ 257 @Deprecated getEventFlags()258 public int getEventFlags() { 259 return lastEventFlags; 260 } 261 262 @Implementation(minSdk = S) registerTelephonyCallback( Object executor, Object callback)263 public void registerTelephonyCallback( 264 /*Executor*/ Object executor, /*TelephonyCallback*/ Object callback) { 265 Preconditions.checkArgument(executor instanceof Executor); 266 Preconditions.checkArgument(callback instanceof TelephonyCallback); 267 lastTelephonyCallback = callback; 268 initTelephonyCallback(callback); 269 telephonyCallbackRegistrations.add(callback); 270 } 271 272 @Implementation(minSdk = TIRAMISU) registerTelephonyCallback( Object includeLocationData, Object executor, Object callback)273 protected void registerTelephonyCallback( 274 /*int*/ Object includeLocationData, /*Executor*/ 275 Object executor, /*TelephonyCallback*/ 276 Object callback) { 277 Preconditions.checkArgument(includeLocationData instanceof Integer); 278 registerTelephonyCallback(executor, callback); 279 } 280 281 @Implementation(minSdk = S) unregisterTelephonyCallback( Object callback)282 public void unregisterTelephonyCallback(/*TelephonyCallback*/ Object callback) { 283 telephonyCallbackRegistrations.remove(callback); 284 } 285 286 /** Returns the most recent callback passed to #registerTelephonyCallback(). */ getLastTelephonyCallback()287 public /*TelephonyCallback*/ Object getLastTelephonyCallback() { 288 return lastTelephonyCallback; 289 } 290 291 /** Call state may be specified via {@link #setCallState(int)}. */ 292 @Implementation(minSdk = S) getCallStateForSubscription()293 protected int getCallStateForSubscription() { 294 checkReadPhoneStatePermission(); 295 return callState; 296 } 297 298 /** Call state may be specified via {@link #setCallState(int)}. */ 299 @Implementation getCallState()300 protected int getCallState() { 301 checkReadPhoneStatePermission(); 302 return callState; 303 } 304 305 /** Sets the current call state to the desired state and updates any listeners. */ setCallState(int callState)306 public void setCallState(int callState) { 307 setCallState(callState, null); 308 } 309 310 /** 311 * Sets the current call state with the option to specify an incoming phone number for the 312 * CALL_STATE_RINGING state. The incoming phone number will be ignored for all other cases. 313 */ setCallState(int callState, String incomingPhoneNumber)314 public void setCallState(int callState, String incomingPhoneNumber) { 315 if (callState != CALL_STATE_RINGING) { 316 incomingPhoneNumber = null; 317 } 318 319 this.callState = callState; 320 this.incomingPhoneNumber = incomingPhoneNumber; 321 322 for (PhoneStateListener listener : getListenersForFlags(LISTEN_CALL_STATE)) { 323 listener.onCallStateChanged(callState, incomingPhoneNumber); 324 } 325 if (VERSION.SDK_INT >= S) { 326 for (CallStateListener listener : getCallbackForListener(CallStateListener.class)) { 327 listener.onCallStateChanged(callState); 328 } 329 } 330 } 331 332 /** 333 * Data state may be specified via {@link #setDataState(int)}. If no override is set, this 334 * defaults to {@link TelephonyManager#DATA_DISCONNECTED}. 335 */ 336 @Implementation getDataState()337 protected int getDataState() { 338 return dataState; 339 } 340 341 /** Sets the data state returned by {@link #getDataState()}. */ setDataState(int dataState)342 public void setDataState(int dataState) { 343 this.dataState = dataState; 344 } 345 346 /** 347 * Data activity may be specified via {@link #setDataActivity(int)}. If no override is set, this 348 * defaults to {@link TelephonyManager#DATA_ACTIVITY_NONE}. 349 */ 350 @Implementation getDataActivity()351 protected int getDataActivity() { 352 return dataActivity; 353 } 354 355 /** 356 * Sets the value to be returned by calls to {@link #getDataActivity()}. This <b>should</b> 357 * correspond to one of the {@code DATA_ACTIVITY_*} constants defined on {@link TelephonyManager}, 358 * but this is not enforced. 359 */ setDataActivity(int dataActivity)360 public void setDataActivity(int dataActivity) { 361 this.dataActivity = dataActivity; 362 } 363 364 @Implementation getDeviceId()365 protected String getDeviceId() { 366 checkReadPhoneStatePermission(); 367 return deviceId; 368 } 369 setDeviceId(String newDeviceId)370 public void setDeviceId(String newDeviceId) { 371 deviceId = newDeviceId; 372 } 373 374 @Implementation getDeviceSoftwareVersion()375 protected String getDeviceSoftwareVersion() { 376 checkReadPhoneStatePermission(); 377 return deviceSoftwareVersion; 378 } 379 setDeviceSoftwareVersion(String newDeviceSoftwareVersion)380 public void setDeviceSoftwareVersion(String newDeviceSoftwareVersion) { 381 deviceSoftwareVersion = newDeviceSoftwareVersion; 382 } 383 384 @Implementation(minSdk = LOLLIPOP_MR1) setNetworkOperatorName(String networkOperatorName)385 public void setNetworkOperatorName(String networkOperatorName) { 386 this.networkOperatorName = networkOperatorName; 387 } 388 389 @Implementation(minSdk = LOLLIPOP) getImei()390 protected String getImei() { 391 checkReadPhoneStatePermission(); 392 return imei; 393 } 394 395 @Implementation(minSdk = O) getImei(int slotIndex)396 protected String getImei(int slotIndex) { 397 checkReadPhoneStatePermission(); 398 return slotIndexToImei.get(slotIndex); 399 } 400 401 /** Set the IMEI returned by getImei(). */ setImei(String imei)402 public void setImei(String imei) { 403 this.imei = imei; 404 } 405 406 /** Set the IMEI returned by {@link #getImei(int)}. */ setImei(int slotIndex, String imei)407 public void setImei(int slotIndex, String imei) { 408 slotIndexToImei.put(slotIndex, imei); 409 } 410 411 @Implementation(minSdk = O) getMeid()412 protected String getMeid() { 413 checkReadPhoneStatePermission(); 414 return meid; 415 } 416 417 @Implementation(minSdk = O) getMeid(int slotIndex)418 protected String getMeid(int slotIndex) { 419 checkReadPhoneStatePermission(); 420 return slotIndexToMeid.get(slotIndex); 421 } 422 423 /** Set the MEID returned by getMeid(). */ setMeid(String meid)424 public void setMeid(String meid) { 425 this.meid = meid; 426 } 427 428 /** Set the MEID returned by {@link #getMeid(int)}. */ setMeid(int slotIndex, String meid)429 public void setMeid(int slotIndex, String meid) { 430 slotIndexToMeid.put(slotIndex, meid); 431 } 432 433 @Implementation getNetworkOperatorName()434 protected String getNetworkOperatorName() { 435 return networkOperatorName; 436 } 437 438 @Implementation(minSdk = LOLLIPOP_MR1, maxSdk = P) setNetworkCountryIso(String networkCountryIso)439 public void setNetworkCountryIso(String networkCountryIso) { 440 this.networkCountryIso = networkCountryIso; 441 } 442 443 /** 444 * Returns the SIM country lowercase. This matches the API this shadows: 445 * https://developer.android.com/reference/android/telephony/TelephonyManager#getNetworkCountryIso(). 446 */ 447 @Implementation getNetworkCountryIso()448 protected String getNetworkCountryIso() { 449 return networkCountryIso == null ? null : Ascii.toLowerCase(networkCountryIso); 450 } 451 452 /** Sets the sim locale returned by {@link #getSimLocale()}. */ setSimLocale(Locale simLocale)453 public void setSimLocale(Locale simLocale) { 454 this.simLocale = simLocale; 455 } 456 457 /** Returns sim locale set by {@link #setSimLocale}. */ 458 @Implementation(minSdk = Q) getSimLocale()459 protected Locale getSimLocale() { 460 return simLocale; 461 } 462 setNetworkOperator(String networkOperator)463 public void setNetworkOperator(String networkOperator) { 464 this.networkOperator = networkOperator; 465 } 466 467 @Implementation getNetworkOperator()468 protected String getNetworkOperator() { 469 return networkOperator; 470 } 471 setNetworkSpecifier(String networkSpecifier)472 public void setNetworkSpecifier(String networkSpecifier) { 473 this.networkSpecifier = networkSpecifier; 474 } 475 476 @Implementation(minSdk = O) getNetworkSpecifier()477 protected String getNetworkSpecifier() { 478 return networkSpecifier; 479 } 480 481 @Implementation getSimOperator()482 protected String getSimOperator() { 483 return simOperator; 484 } 485 setSimOperator(String simOperator)486 public void setSimOperator(String simOperator) { 487 this.simOperator = simOperator; 488 } 489 490 @Implementation getSimOperatorName()491 protected String getSimOperatorName() { 492 return simOperatorName; 493 } 494 495 @Implementation(minSdk = LOLLIPOP_MR1) setSimOperatorName(String simOperatorName)496 public void setSimOperatorName(String simOperatorName) { 497 this.simOperatorName = simOperatorName; 498 } 499 500 @Implementation getSimSerialNumber()501 protected String getSimSerialNumber() { 502 checkReadPhoneStatePermission(); 503 return this.simSerialNumber; 504 } 505 506 /** sets the serial number that will be returned by {@link #getSimSerialNumber}. */ setSimSerialNumber(String simSerialNumber)507 public void setSimSerialNumber(String simSerialNumber) { 508 this.simSerialNumber = simSerialNumber; 509 } 510 511 /** 512 * Returns the SIM country lowercase. This matches the API it shadows: 513 * https://developer.android.com/reference/android/telephony/TelephonyManager#getSimCountryIso(). 514 */ 515 @Implementation getSimCountryIso()516 protected String getSimCountryIso() { 517 String simCountryIso = simCountryIsoMap.get(/* subId= */ 0); 518 return simCountryIso == null ? simCountryIso : Ascii.toLowerCase(simCountryIso); 519 } 520 521 @Implementation(minSdk = N, maxSdk = Q) 522 @HiddenApi getSimCountryIso(int subId)523 protected String getSimCountryIso(int subId) { 524 return simCountryIsoMap.get(subId); 525 } 526 527 @Implementation(minSdk = LOLLIPOP_MR1) setSimCountryIso(String simCountryIso)528 public void setSimCountryIso(String simCountryIso) { 529 setSimCountryIso(/* subId= */ 0, simCountryIso); 530 } 531 532 /** Sets the {@code simCountryIso} for the given {@code subId}. */ setSimCountryIso(int subId, String simCountryIso)533 public void setSimCountryIso(int subId, String simCountryIso) { 534 simCountryIsoMap.put(subId, simCountryIso); 535 } 536 537 /** Clears {@code subId} to simCountryIso mapping and resets to default state. */ resetSimCountryIsos()538 public void resetSimCountryIsos() { 539 simCountryIsoMap.clear(); 540 simCountryIsoMap.put(0, ""); 541 } 542 543 @Implementation getSimState()544 protected int getSimState() { 545 return getSimState(/* slotIndex= */ 0); 546 } 547 548 /** Sets the sim state of slot 0. */ setSimState(int simState)549 public void setSimState(int simState) { 550 setSimState(/* slotIndex= */ 0, simState); 551 } 552 553 /** Set the sim state for the given {@code slotIndex}. */ setSimState(int slotIndex, int state)554 public void setSimState(int slotIndex, int state) { 555 simStates.put(slotIndex, state); 556 } 557 558 @Implementation(minSdk = O) getSimState(int slotIndex)559 protected int getSimState(int slotIndex) { 560 return simStates.get(slotIndex, TelephonyManager.SIM_STATE_UNKNOWN); 561 } 562 563 /** Sets the UICC slots information returned by {@link #getUiccSlotsInfo()}. */ setUiccSlotsInfo( Object uiccSlotsInfos)564 public void setUiccSlotsInfo(/*UiccSlotInfo[]*/ Object uiccSlotsInfos) { 565 this.uiccSlotInfos = uiccSlotsInfos; 566 } 567 568 /** Returns the UICC slots information set by {@link #setUiccSlotsInfo}. */ 569 @Implementation(minSdk = P) 570 @HiddenApi getUiccSlotsInfo()571 protected /*UiccSlotInfo[]*/ Object getUiccSlotsInfo() { 572 return uiccSlotInfos; 573 } 574 575 /** Sets the UICC cards information returned by {@link #getUiccCardsInfo()}. */ setUiccCardsInfo( Object uiccCardsInfo)576 public void setUiccCardsInfo(/*UiccCardsInfo[]*/ Object uiccCardsInfo) { 577 this.uiccCardsInfo = uiccCardsInfo; 578 } 579 580 /** Returns the UICC cards information set by {@link #setUiccCardsInfo}. */ 581 @Implementation(minSdk = Q) 582 @HiddenApi getUiccCardsInfo()583 protected /*UiccSlotInfo[]*/ Object getUiccCardsInfo() { 584 return uiccCardsInfo; 585 } 586 587 /** Clears {@code slotIndex} to state mapping and resets to default state. */ resetSimStates()588 public void resetSimStates() { 589 simStates.clear(); 590 simStates.put(0, TelephonyManager.SIM_STATE_READY); 591 } 592 setReadPhoneStatePermission(boolean readPhoneStatePermission)593 public void setReadPhoneStatePermission(boolean readPhoneStatePermission) { 594 this.readPhoneStatePermission = readPhoneStatePermission; 595 } 596 checkReadPhoneStatePermission()597 private void checkReadPhoneStatePermission() { 598 if (!readPhoneStatePermission) { 599 throw new SecurityException(); 600 } 601 } 602 checkReadPrivilegedPhoneStatePermission()603 private void checkReadPrivilegedPhoneStatePermission() { 604 if (!checkPermission(permission.READ_PRIVILEGED_PHONE_STATE)) { 605 throw new SecurityException(); 606 } 607 } 608 getShadowInstrumentation()609 static ShadowInstrumentation getShadowInstrumentation() { 610 ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread(); 611 return Shadow.extract(activityThread.getInstrumentation()); 612 } 613 checkPermission(String permission)614 static boolean checkPermission(String permission) { 615 return getShadowInstrumentation() 616 .checkPermission(permission, android.os.Process.myPid(), android.os.Process.myUid()) 617 == PERMISSION_GRANTED; 618 } 619 620 @Implementation getPhoneType()621 protected int getPhoneType() { 622 return phoneType; 623 } 624 625 @Implementation(minSdk = LOLLIPOP_MR1) setPhoneType(int phoneType)626 public void setPhoneType(int phoneType) { 627 this.phoneType = phoneType; 628 } 629 630 @Implementation getLine1Number()631 protected String getLine1Number() { 632 checkReadPhoneStatePermission(); 633 return line1Number; 634 } 635 setLine1Number(String line1Number)636 public void setLine1Number(String line1Number) { 637 this.line1Number = line1Number; 638 } 639 640 @Implementation getNetworkType()641 protected int getNetworkType() { 642 checkReadPhoneStatePermission(); 643 return networkType; 644 } 645 646 /** 647 * @deprecated {@link TelephonyManager#getNetworkType()} was replaced with {@link 648 * TelephonyManager#getDataNetworkType()} in Android N, and has been deprecated in Android R. 649 * Use {@link #setDataNetworkType instead}. 650 */ 651 @Deprecated setNetworkType(int networkType)652 public void setNetworkType(int networkType) { 653 this.networkType = networkType; 654 } 655 656 /** 657 * Returns whatever value was set by the last call to {@link #setDataNetworkType}, defaulting to 658 * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if it was never called. 659 */ 660 @Implementation(minSdk = N) getDataNetworkType()661 protected int getDataNetworkType() { 662 checkReadPhoneStatePermission(); 663 return dataNetworkType; 664 } 665 666 /** 667 * Sets the value to be returned by calls to {@link #getDataNetworkType}. This <b>should</b> 668 * correspond to one of the {@code NETWORK_TYPE_*} constants defined on {@link TelephonyManager}, 669 * but this is not enforced. 670 */ 671 @Implementation(minSdk = LOLLIPOP_MR1) setDataNetworkType(int dataNetworkType)672 public void setDataNetworkType(int dataNetworkType) { 673 this.dataNetworkType = dataNetworkType; 674 } 675 676 /** 677 * Returns whatever value was set by the last call to {@link #setVoiceNetworkType}, defaulting to 678 * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if it was never called. 679 * 680 * <p>An exception will be thrown if the READ_PHONE_STATE permission has not been granted. 681 */ 682 @Implementation(minSdk = N) getVoiceNetworkType()683 protected int getVoiceNetworkType() { 684 checkReadPhoneStatePermission(); 685 return voiceNetworkType; 686 } 687 688 /** 689 * Sets the value to be returned by calls to {@link getVoiceNetworkType}. This <b>should</b> 690 * correspond to one of the {@code NETWORK_TYPE_*} constants defined on {@link TelephonyManager}, 691 * but this is not enforced. 692 */ setVoiceNetworkType(int voiceNetworkType)693 public void setVoiceNetworkType(int voiceNetworkType) { 694 this.voiceNetworkType = voiceNetworkType; 695 } 696 697 @Implementation(minSdk = JELLY_BEAN_MR1) getAllCellInfo()698 protected List<CellInfo> getAllCellInfo() { 699 return allCellInfo; 700 } 701 setAllCellInfo(List<CellInfo> allCellInfo)702 public void setAllCellInfo(List<CellInfo> allCellInfo) { 703 this.allCellInfo = allCellInfo; 704 705 if (VERSION.SDK_INT >= JELLY_BEAN_MR1) { 706 for (PhoneStateListener listener : getListenersForFlags(LISTEN_CELL_INFO)) { 707 listener.onCellInfoChanged(allCellInfo); 708 } 709 } 710 if (VERSION.SDK_INT >= S) { 711 for (CellInfoListener listener : getCallbackForListener(CellInfoListener.class)) { 712 listener.onCellInfoChanged(allCellInfo); 713 } 714 } 715 } 716 717 /** 718 * Returns the value set by {@link #setCallbackCellInfos}, defaulting to calling the real {@link 719 * TelephonyManager#NETWORK_TYPE_UNKNOWN} if it was never called. 720 */ 721 @Implementation(minSdk = Q) requestCellInfoUpdate(Object cellInfoExecutor, Object cellInfoCallback)722 protected void requestCellInfoUpdate(Object cellInfoExecutor, Object cellInfoCallback) { 723 Executor executor = (Executor) cellInfoExecutor; 724 if (callbackCellInfos == null) { 725 // ignore 726 } else if (requestCellInfoUpdateErrorCode != 0 || requestCellInfoUpdateDetail != null) { 727 // perform the "failure" callback operation via the specified executor 728 executor.execute( 729 () -> { 730 // Must cast 'callback' inside the anonymous class to avoid NoClassDefFoundError when 731 // referring to 'CellInfoCallback'. 732 CellInfoCallback callback = (CellInfoCallback) cellInfoCallback; 733 callback.onError(requestCellInfoUpdateErrorCode, requestCellInfoUpdateDetail); 734 }); 735 } else { 736 // perform the "success" callback operation via the specified executor 737 executor.execute( 738 () -> { 739 // Must cast 'callback' inside the anonymous class to avoid NoClassDefFoundError when 740 // referring to 'CellInfoCallback'. 741 CellInfoCallback callback = (CellInfoCallback) cellInfoCallback; 742 callback.onCellInfo(callbackCellInfos); 743 }); 744 } 745 } 746 747 /** 748 * Sets the value to be returned by calls to {@link requestCellInfoUpdate}. Note that it does not 749 * set the value to be returned by calls to {@link getAllCellInfo}; for that, see {@link 750 * setAllCellInfo}. 751 */ setCallbackCellInfos(List<CellInfo> callbackCellInfos)752 public void setCallbackCellInfos(List<CellInfo> callbackCellInfos) { 753 this.callbackCellInfos = callbackCellInfos; 754 } 755 756 /** 757 * Sets the values to be returned by a presumed error condition in {@link requestCellInfoUpdate}. 758 * These values will persist until cleared: to clear, set (0, null) using this method. 759 */ setRequestCellInfoUpdateErrorValues(int errorCode, Throwable detail)760 public void setRequestCellInfoUpdateErrorValues(int errorCode, Throwable detail) { 761 requestCellInfoUpdateErrorCode = errorCode; 762 requestCellInfoUpdateDetail = detail; 763 } 764 765 @Implementation getCellLocation()766 protected CellLocation getCellLocation() { 767 return this.cellLocation; 768 } 769 setCellLocation(CellLocation cellLocation)770 public void setCellLocation(CellLocation cellLocation) { 771 this.cellLocation = cellLocation; 772 773 for (PhoneStateListener listener : getListenersForFlags(LISTEN_CELL_LOCATION)) { 774 listener.onCellLocationChanged(cellLocation); 775 } 776 if (VERSION.SDK_INT >= S) { 777 for (CellLocationListener listener : getCallbackForListener(CellLocationListener.class)) { 778 listener.onCellLocationChanged(cellLocation); 779 } 780 } 781 } 782 783 @Implementation(minSdk = JELLY_BEAN_MR2) getGroupIdLevel1()784 protected String getGroupIdLevel1() { 785 checkReadPhoneStatePermission(); 786 return this.groupIdLevel1; 787 } 788 setGroupIdLevel1(String groupIdLevel1)789 public void setGroupIdLevel1(String groupIdLevel1) { 790 this.groupIdLevel1 = groupIdLevel1; 791 } 792 793 @CallSuper initListener(PhoneStateListener listener, int flags)794 protected void initListener(PhoneStateListener listener, int flags) { 795 if ((flags & LISTEN_CALL_STATE) != 0) { 796 listener.onCallStateChanged(callState, incomingPhoneNumber); 797 } 798 if ((flags & LISTEN_CELL_INFO) != 0) { 799 if (VERSION.SDK_INT >= JELLY_BEAN_MR1) { 800 listener.onCellInfoChanged(allCellInfo); 801 } 802 } 803 if ((flags & LISTEN_CELL_LOCATION) != 0) { 804 listener.onCellLocationChanged(cellLocation); 805 } 806 807 if (telephonyDisplayInfo != null 808 && ((flags & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0)) { 809 listener.onDisplayInfoChanged((TelephonyDisplayInfo) telephonyDisplayInfo); 810 } 811 812 if (serviceState != null && ((flags & PhoneStateListener.LISTEN_SERVICE_STATE) != 0)) { 813 listener.onServiceStateChanged(serviceState); 814 } 815 } 816 817 @CallSuper initTelephonyCallback(Object callback)818 protected void initTelephonyCallback(Object callback) { 819 if (VERSION.SDK_INT < S) { 820 return; 821 } 822 823 if (callback instanceof CallStateListener) { 824 ((CallStateListener) callback).onCallStateChanged(callState); 825 } 826 if (callback instanceof CellInfoListener) { 827 ((CellInfoListener) callback).onCellInfoChanged(allCellInfo); 828 } 829 if (callback instanceof CellLocationListener) { 830 ((CellLocationListener) callback).onCellLocationChanged(cellLocation); 831 } 832 if (telephonyDisplayInfo != null && callback instanceof DisplayInfoListener) { 833 ((DisplayInfoListener) callback) 834 .onDisplayInfoChanged((TelephonyDisplayInfo) telephonyDisplayInfo); 835 } 836 if (serviceState != null && callback instanceof ServiceStateListener) { 837 ((ServiceStateListener) callback).onServiceStateChanged(serviceState); 838 } 839 } 840 getListenersForFlags(int flags)841 protected Iterable<PhoneStateListener> getListenersForFlags(int flags) { 842 return Iterables.filter( 843 phoneStateRegistrations.keySet(), 844 new Predicate<PhoneStateListener>() { 845 @Override 846 public boolean apply(PhoneStateListener input) { 847 // only select PhoneStateListeners with matching flags 848 return (phoneStateRegistrations.get(input) & flags) != 0; 849 } 850 }); 851 } 852 853 /** 854 * Returns a view of {@code telephonyCallbackRegistrations} containing all elements that are of 855 * the type {@code clazz}. 856 */ 857 protected <T> Iterable<T> getCallbackForListener(Class<T> clazz) { 858 // Only selects TelephonyCallback with matching class. 859 return Iterables.filter(telephonyCallbackRegistrations, clazz); 860 } 861 862 /** 863 * @return true by default, or the value specified via {@link #setIsSmsCapable(boolean)} 864 */ 865 @Implementation 866 protected boolean isSmsCapable() { 867 return isSmsCapable; 868 } 869 870 /** Sets the value returned by {@link TelephonyManager#isSmsCapable()}. */ 871 public void setIsSmsCapable(boolean isSmsCapable) { 872 this.isSmsCapable = isSmsCapable; 873 } 874 875 /** 876 * Returns a new empty {@link PersistableBundle} by default, or the value specified via {@link 877 * #setCarrierConfig(PersistableBundle)}. 878 */ 879 @Implementation(minSdk = O) 880 protected PersistableBundle getCarrierConfig() { 881 checkReadPhoneStatePermission(); 882 return carrierConfig != null ? carrierConfig : new PersistableBundle(); 883 } 884 885 /** 886 * Sets the value returned by {@link TelephonyManager#getCarrierConfig()}. 887 * 888 * @param carrierConfig 889 */ 890 public void setCarrierConfig(PersistableBundle carrierConfig) { 891 this.carrierConfig = carrierConfig; 892 } 893 894 /** 895 * Returns {@code null} by default, or the value specified via {@link 896 * #setVoiceMailNumber(String)}. 897 */ 898 @Implementation 899 protected String getVoiceMailNumber() { 900 checkReadPhoneStatePermission(); 901 return voiceMailNumber; 902 } 903 904 /** Sets the value returned by {@link TelephonyManager#getVoiceMailNumber()}. */ 905 public void setVoiceMailNumber(String voiceMailNumber) { 906 this.voiceMailNumber = voiceMailNumber; 907 } 908 909 /** 910 * Returns {@code null} by default or the value specified via {@link 911 * #setVoiceMailAlphaTag(String)}. 912 */ 913 @Implementation 914 protected String getVoiceMailAlphaTag() { 915 checkReadPhoneStatePermission(); 916 return voiceMailAlphaTag; 917 } 918 919 /** Sets the value returned by {@link TelephonyManager#getVoiceMailAlphaTag()}. */ 920 public void setVoiceMailAlphaTag(String voiceMailAlphaTag) { 921 this.voiceMailAlphaTag = voiceMailAlphaTag; 922 } 923 924 /** Returns 1 by default or the value specified via {@link #setPhoneCount(int)}. */ 925 @Implementation(minSdk = M) 926 protected int getPhoneCount() { 927 return phoneCount; 928 } 929 930 /** Sets the value returned by {@link TelephonyManager#getPhoneCount()}. */ 931 public void setPhoneCount(int phoneCount) { 932 this.phoneCount = phoneCount; 933 } 934 935 /** Returns 1 by default or the value specified via {@link #setActiveModemCount(int)}. */ 936 @Implementation(minSdk = R) 937 protected int getActiveModemCount() { 938 return activeModemCount; 939 } 940 941 /** Sets the value returned by {@link TelephonyManager#getActiveModemCount()}. */ 942 public void setActiveModemCount(int activeModemCount) { 943 this.activeModemCount = activeModemCount; 944 } 945 946 /** 947 * Returns {@code null} by default or the value specified via {@link #setDeviceId(int, String)}. 948 */ 949 @Implementation(minSdk = M) 950 protected String getDeviceId(int slot) { 951 checkReadPhoneStatePermission(); 952 return slotIndexToDeviceId.get(slot); 953 } 954 955 /** Sets the value returned by {@link TelephonyManager#getDeviceId(int)}. */ 956 public void setDeviceId(int slot, String deviceId) { 957 slotIndexToDeviceId.put(slot, deviceId); 958 } 959 960 /** 961 * Returns {@code true} by default or the value specified via {@link #setVoiceCapable(boolean)}. 962 */ 963 @Implementation(minSdk = LOLLIPOP_MR1) 964 protected boolean isVoiceCapable() { 965 return voiceCapable; 966 } 967 968 /** Sets the value returned by {@link #isVoiceCapable()}. */ 969 public void setVoiceCapable(boolean voiceCapable) { 970 this.voiceCapable = voiceCapable; 971 } 972 973 /** 974 * Returns {@code null} by default or the value specified via {@link 975 * #setVoicemailVibrationEnabled(PhoneAccountHandle, boolean)}. 976 */ 977 @Implementation(minSdk = N) 978 protected boolean isVoicemailVibrationEnabled(PhoneAccountHandle handle) { 979 Boolean result = voicemailVibrationEnabledMap.get(handle); 980 return result != null ? result : false; 981 } 982 983 /** 984 * Sets the value returned by {@link 985 * TelephonyManager#isVoicemailVibrationEnabled(PhoneAccountHandle)}. 986 */ 987 @Implementation(minSdk = O) 988 protected void setVoicemailVibrationEnabled(PhoneAccountHandle handle, boolean isEnabled) { 989 voicemailVibrationEnabledMap.put(handle, isEnabled); 990 } 991 992 /** 993 * Returns {@code null} by default or the value specified via {@link 994 * #setVoicemailRingtoneUri(PhoneAccountHandle, Uri)}. 995 */ 996 @Implementation(minSdk = N) 997 protected Uri getVoicemailRingtoneUri(PhoneAccountHandle handle) { 998 return voicemailRingtoneUriMap.get(handle); 999 } 1000 1001 /** 1002 * Sets the value returned by {@link 1003 * TelephonyManager#getVoicemailRingtoneUri(PhoneAccountHandle)}. 1004 */ 1005 @Implementation(minSdk = O) 1006 protected void setVoicemailRingtoneUri(PhoneAccountHandle handle, Uri uri) { 1007 voicemailRingtoneUriMap.put(handle, uri); 1008 } 1009 1010 /** 1011 * Returns {@code null} by default or the value specified via {@link 1012 * #setTelephonyManagerForHandle(PhoneAccountHandle, TelephonyManager)}. 1013 */ 1014 @Implementation(minSdk = O) 1015 protected TelephonyManager createForPhoneAccountHandle(PhoneAccountHandle handle) { 1016 checkReadPhoneStatePermission(); 1017 return phoneAccountToTelephonyManagers.get(handle); 1018 } 1019 1020 /** 1021 * Sets the value returned by {@link 1022 * TelephonyManager#createForPhoneAccountHandle(PhoneAccountHandle)}. 1023 */ 1024 public void setTelephonyManagerForHandle( 1025 PhoneAccountHandle handle, TelephonyManager telephonyManager) { 1026 phoneAccountToTelephonyManagers.put(handle, telephonyManager); 1027 } 1028 1029 /** 1030 * Returns {@code null} by default or the value specified via {@link 1031 * #setTelephonyManagerForSubscriptionId(int, TelephonyManager)} 1032 */ 1033 @Implementation(minSdk = N) 1034 protected TelephonyManager createForSubscriptionId(int subId) { 1035 return subscriptionIdsToTelephonyManagers.get(subId); 1036 } 1037 1038 /** Sets the value returned by {@link TelephonyManager#createForSubscriptionId(int)}. */ 1039 public void setTelephonyManagerForSubscriptionId( 1040 int subscriptionId, TelephonyManager telephonyManager) { 1041 subscriptionIdsToTelephonyManagers.put(subscriptionId, telephonyManager); 1042 } 1043 1044 /** 1045 * Returns {@code null} by default or the value specified via {@link 1046 * #setServiceState(ServiceState)} 1047 */ 1048 @Implementation(minSdk = O) 1049 protected ServiceState getServiceState() { 1050 checkReadPhoneStatePermission(); 1051 return serviceState; 1052 } 1053 1054 /** 1055 * Returns {@code null} by default or the value specified via {@link 1056 * #setServiceState(ServiceState)} 1057 */ 1058 @Implementation(minSdk = TIRAMISU) 1059 protected ServiceState getServiceState(int includeLocationData) { 1060 return getServiceState(); 1061 } 1062 1063 /** Sets the value returned by {@link TelephonyManager#getServiceState()}. */ 1064 public void setServiceState(ServiceState serviceState) { 1065 this.serviceState = serviceState; 1066 1067 for (PhoneStateListener listener : getListenersForFlags(LISTEN_SERVICE_STATE)) { 1068 listener.onServiceStateChanged(serviceState); 1069 } 1070 if (VERSION.SDK_INT >= S) { 1071 for (ServiceStateListener listener : getCallbackForListener(ServiceStateListener.class)) { 1072 listener.onServiceStateChanged(serviceState); 1073 } 1074 } 1075 } 1076 1077 /** 1078 * Returns {@code false} by default or the value specified via {@link 1079 * #setIsNetworkRoaming(boolean)} 1080 */ 1081 @Implementation 1082 protected boolean isNetworkRoaming() { 1083 return isNetworkRoaming; 1084 } 1085 1086 /** Sets the value returned by {@link TelephonyManager#isNetworkRoaming()}. */ 1087 public void setIsNetworkRoaming(boolean isNetworkRoaming) { 1088 this.isNetworkRoaming = isNetworkRoaming; 1089 } 1090 1091 @Implementation(minSdk = M) 1092 @HiddenApi 1093 protected int getCurrentPhoneType(int subId) { 1094 return currentPhoneTypes.get(subId, TelephonyManager.PHONE_TYPE_NONE); 1095 } 1096 1097 /** Sets the phone type for the given {@code subId}. */ 1098 public void setCurrentPhoneType(int subId, int phoneType) { 1099 currentPhoneTypes.put(subId, phoneType); 1100 } 1101 1102 /** Removes all {@code subId} to {@code phoneType} mappings. */ 1103 public void clearPhoneTypes() { 1104 currentPhoneTypes.clear(); 1105 } 1106 1107 @Implementation(minSdk = M) 1108 @HiddenApi 1109 protected List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) { 1110 return carrierPackageNames.get(phoneId); 1111 } 1112 1113 @Implementation(minSdk = LOLLIPOP) 1114 @HiddenApi 1115 protected List<String> getCarrierPackageNamesForIntent(Intent intent) { 1116 return carrierPackageNames.get(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 1117 } 1118 1119 /** Sets the {@code packages} for the given {@code phoneId}. */ 1120 public void setCarrierPackageNamesForPhone(int phoneId, List<String> packages) { 1121 carrierPackageNames.put(phoneId, packages); 1122 } 1123 1124 @Implementation(minSdk = Q) 1125 protected int getCarrierIdFromSimMccMnc() { 1126 return carrierIdFromSimMccMnc; 1127 } 1128 1129 /** Sets the value to be returned by {@link #getCarrierIdFromSimMccMnc()}. */ 1130 public void setCarrierIdFromSimMccMnc(int carrierIdFromSimMccMnc) { 1131 this.carrierIdFromSimMccMnc = carrierIdFromSimMccMnc; 1132 } 1133 1134 @Implementation(minSdk = P) 1135 protected int getSimCarrierId() { 1136 return simCarrierId; 1137 } 1138 1139 /** Sets the value to be returned by {@link #getSimCarrierId()}. */ 1140 public void setSimCarrierId(int simCarrierId) { 1141 this.simCarrierId = simCarrierId; 1142 } 1143 1144 @Implementation 1145 protected String getSubscriberId() { 1146 checkReadPhoneStatePermission(); 1147 return subscriberId; 1148 } 1149 1150 /** Sets the value to be returned by {@link #getSubscriberId()}. */ 1151 public void setSubscriberId(String subscriberId) { 1152 this.subscriberId = subscriberId; 1153 } 1154 1155 @Implementation(minSdk = R) 1156 protected int getSubscriptionId(PhoneAccountHandle handle) { 1157 checkReadPhoneStatePermission(); 1158 return phoneAccountHandleSubscriptionId.get(handle); 1159 } 1160 1161 public void setPhoneAccountHandleSubscriptionId(PhoneAccountHandle handle, int subscriptionId) { 1162 phoneAccountHandleSubscriptionId.put(handle, subscriptionId); 1163 } 1164 1165 /** Returns the value set by {@link #setVisualVoicemailPackageName(String)}. */ 1166 @Implementation(minSdk = O) 1167 protected String getVisualVoicemailPackageName() { 1168 checkReadPhoneStatePermission(); 1169 return visualVoicemailPackageName; 1170 } 1171 1172 /** Sets the value to be returned by {@link #getVisualVoicemailPackageName()}. */ 1173 public void setVisualVoicemailPackageName(String visualVoicemailPackageName) { 1174 this.visualVoicemailPackageName = visualVoicemailPackageName; 1175 } 1176 1177 @Implementation(minSdk = P) 1178 protected SignalStrength getSignalStrength() { 1179 return signalStrength; 1180 } 1181 1182 /** Sets the value to be returned by {@link #getSignalStrength()} */ 1183 public void setSignalStrength(SignalStrength signalStrength) { 1184 this.signalStrength = signalStrength; 1185 for (PhoneStateListener listener : 1186 getListenersForFlags(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS)) { 1187 listener.onSignalStrengthsChanged(signalStrength); 1188 } 1189 if (VERSION.SDK_INT >= S) { 1190 for (SignalStrengthsListener listener : 1191 getCallbackForListener(SignalStrengthsListener.class)) { 1192 listener.onSignalStrengthsChanged(signalStrength); 1193 } 1194 } 1195 } 1196 1197 /** 1198 * Cribbed from {@link android.telephony.PhoneNumberUtils#isEmergencyNumberInternal}. 1199 * 1200 * <p>TODO: need better implementation 1201 */ 1202 @Implementation(minSdk = Build.VERSION_CODES.Q) 1203 protected boolean isEmergencyNumber(String number) { 1204 if (ShadowServiceManager.getService(Context.TELEPHONY_SERVICE) == null) { 1205 throw new IllegalStateException("telephony service is null."); 1206 } 1207 1208 if (number == null) { 1209 return false; 1210 } 1211 1212 Context context = ReflectionHelpers.getField(realTelephonyManager, "mContext"); 1213 Locale locale = context == null ? null : context.getResources().getConfiguration().locale; 1214 String defaultCountryIso = locale == null ? null : locale.getCountry(); 1215 1216 int slotId = -1; 1217 boolean useExactMatch = true; 1218 1219 // retrieve the list of emergency numbers 1220 // check read-write ecclist property first 1221 String ecclist = (slotId <= 0) ? "ril.ecclist" : ("ril.ecclist" + slotId); 1222 1223 String emergencyNumbers = SystemProperties.get(ecclist, ""); 1224 1225 if (TextUtils.isEmpty(emergencyNumbers)) { 1226 // then read-only ecclist property since old RIL only uses this 1227 emergencyNumbers = SystemProperties.get("ro.ril.ecclist"); 1228 } 1229 1230 if (!TextUtils.isEmpty(emergencyNumbers)) { 1231 // searches through the comma-separated list for a match, 1232 // return true if one is found. 1233 for (String emergencyNum : emergencyNumbers.split(",")) { 1234 // It is not possible to append additional digits to an emergency number to dial 1235 // the number in Brazil - it won't connect. 1236 if (useExactMatch || "BR".equalsIgnoreCase(defaultCountryIso)) { 1237 if (number.equals(emergencyNum)) { 1238 return true; 1239 } 1240 } else { 1241 if (number.startsWith(emergencyNum)) { 1242 return true; 1243 } 1244 } 1245 } 1246 // no matches found against the list! 1247 return false; 1248 } 1249 1250 emergencyNumbers = ((slotId < 0) ? "112,911,000,08,110,118,119,999" : "112,911"); 1251 for (String emergencyNum : emergencyNumbers.split(",")) { 1252 if (useExactMatch) { 1253 if (number.equals(emergencyNum)) { 1254 return true; 1255 } 1256 } else { 1257 if (number.startsWith(emergencyNum)) { 1258 return true; 1259 } 1260 } 1261 } 1262 1263 return false; 1264 } 1265 1266 /** 1267 * Emergency Callback Mode (ECBM) is typically set by the carrier, for a time window of 5 minutes 1268 * after the last outgoing emergency call. The user can exit ECBM via a system notification. 1269 * 1270 * @param emergencyCallbackMode whether the device is in ECBM or not. 1271 */ 1272 public void setEmergencyCallbackMode(boolean emergencyCallbackMode) { 1273 this.emergencyCallbackMode = emergencyCallbackMode; 1274 } 1275 1276 @Implementation(minSdk = Build.VERSION_CODES.O) 1277 protected boolean getEmergencyCallbackMode() { 1278 checkReadPrivilegedPhoneStatePermission(); 1279 return emergencyCallbackMode; 1280 } 1281 1282 @Implementation(minSdk = Build.VERSION_CODES.Q) 1283 protected boolean isPotentialEmergencyNumber(String number) { 1284 return isEmergencyNumber(number); 1285 } 1286 1287 /** 1288 * Implementation for {@link TelephonyManager#isDataEnabled}. 1289 * 1290 * @return False by default, unless set with {@link TelephonyManager#setDataEnabled}. 1291 */ 1292 @Implementation(minSdk = Build.VERSION_CODES.O) 1293 protected boolean isDataEnabled() { 1294 checkReadPhoneStatePermission(); 1295 return dataEnabled; 1296 } 1297 1298 /** 1299 * Implementation for {@link TelephonyManager#isDataEnabledForReason}. 1300 * 1301 * @return True by default, unless reason is set to false with {@link 1302 * TelephonyManager#setDataEnabledForReason}. 1303 */ 1304 @Implementation(minSdk = Build.VERSION_CODES.S) 1305 protected boolean isDataEnabledForReason(@TelephonyManager.DataEnabledReason int reason) { 1306 checkReadPhoneStatePermission(); 1307 return !dataDisabledReasons.contains(reason); 1308 } 1309 1310 /** 1311 * Implementation for {@link TelephonyManager#setDataEnabled}. Marked as public in order to allow 1312 * it to be used as a test API. 1313 */ 1314 @Implementation(minSdk = Build.VERSION_CODES.O) 1315 public void setDataEnabled(boolean enabled) { 1316 setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER, enabled); 1317 } 1318 1319 /** 1320 * Implementation for {@link TelephonyManager#setDataEnabledForReason}. Marked as public in order 1321 * to allow it to be used as a test API. 1322 */ 1323 @Implementation(minSdk = Build.VERSION_CODES.S) 1324 public void setDataEnabledForReason( 1325 @TelephonyManager.DataEnabledReason int reason, boolean enabled) { 1326 if (enabled) { 1327 dataDisabledReasons.remove(reason); 1328 } else { 1329 dataDisabledReasons.add(reason); 1330 } 1331 dataEnabled = dataDisabledReasons.isEmpty(); 1332 } 1333 1334 /** 1335 * Implementation for {@link TelephonyManager#isRttSupported}. 1336 * 1337 * @return False by default, unless set with {@link #setRttSupported(boolean)}. 1338 */ 1339 @Implementation(minSdk = Build.VERSION_CODES.Q) 1340 protected boolean isRttSupported() { 1341 return isRttSupported; 1342 } 1343 1344 /** Sets the value to be returned by {@link #isRttSupported()} */ 1345 public void setRttSupported(boolean isRttSupported) { 1346 this.isRttSupported = isRttSupported; 1347 } 1348 1349 /** 1350 * Implementation for {@link TelephonyManager#isTtyModeSupported}. 1351 * 1352 * @return False by default, unless set with {@link #setTtyModeSupported(boolean)}. 1353 */ 1354 @Implementation(minSdk = Build.VERSION_CODES.M) 1355 protected boolean isTtyModeSupported() { 1356 checkReadPhoneStatePermission(); 1357 return isTtyModeSupported; 1358 } 1359 1360 /** Sets the value to be returned by {@link #isTtyModeSupported()} */ 1361 public void setTtyModeSupported(boolean isTtyModeSupported) { 1362 this.isTtyModeSupported = isTtyModeSupported; 1363 } 1364 1365 /** 1366 * @return False by default, unless set with {@link #setHasCarrierPrivileges(int, boolean)}. 1367 */ 1368 @Implementation(minSdk = Build.VERSION_CODES.N) 1369 @HiddenApi 1370 protected boolean hasCarrierPrivileges(int subId) { 1371 return subIdToHasCarrierPrivileges.get(subId); 1372 } 1373 1374 public void setHasCarrierPrivileges(boolean hasCarrierPrivileges) { 1375 int subId = ReflectionHelpers.callInstanceMethod(realTelephonyManager, "getSubId"); 1376 setHasCarrierPrivileges(subId, hasCarrierPrivileges); 1377 } 1378 1379 /** Sets the {@code hasCarrierPrivileges} for the given {@code subId}. */ 1380 public void setHasCarrierPrivileges(int subId, boolean hasCarrierPrivileges) { 1381 subIdToHasCarrierPrivileges.put(subId, hasCarrierPrivileges); 1382 } 1383 1384 /** 1385 * Implementation for {@link TelephonyManager#sendDialerSpecialCode(String)}. 1386 * 1387 * @param inputCode special code to be sent. 1388 */ 1389 @Implementation(minSdk = O) 1390 public void sendDialerSpecialCode(String inputCode) { 1391 sentDialerSpecialCodes.add(inputCode); 1392 } 1393 1394 /** 1395 * Returns immutable list of special codes sent using {@link 1396 * TelephonyManager#sendDialerSpecialCode(String)}. Special codes contained in the list are in the 1397 * order they were sent. 1398 */ 1399 public List<String> getSentDialerSpecialCodes() { 1400 return ImmutableList.copyOf(sentDialerSpecialCodes); 1401 } 1402 1403 /** Sets the value to be returned by {@link #isHearingAidCompatibilitySupported()}. */ 1404 public void setHearingAidCompatibilitySupported(boolean isSupported) { 1405 hearingAidCompatibilitySupported = isSupported; 1406 } 1407 1408 /** 1409 * Implementation for {@link TelephonyManager#isHearingAidCompatibilitySupported()}. 1410 * 1411 * @return False by default, unless set with {@link 1412 * #setHearingAidCompatibilitySupported(boolean)}. 1413 */ 1414 @Implementation(minSdk = M) 1415 protected boolean isHearingAidCompatibilitySupported() { 1416 return hearingAidCompatibilitySupported; 1417 } 1418 1419 /** 1420 * Creates a {@link TelephonyDisplayInfo}. 1421 * 1422 * @param networkType The packet-switching cellular network type (see {@link NetworkType}) 1423 * @param overrideNetworkType The override network type (see {@link OverrideNetworkType}) 1424 */ 1425 public static Object createTelephonyDisplayInfo( 1426 @NetworkType int networkType, @OverrideNetworkType int overrideNetworkType) { 1427 return new TelephonyDisplayInfo(networkType, overrideNetworkType); 1428 } 1429 1430 /** 1431 * Sets the current {@link TelephonyDisplayInfo}, and notifies all the {@link PhoneStateListener}s 1432 * that were registered with the {@link PhoneStateListener#LISTEN_DISPLAY_INFO_CHANGED} flag. 1433 * 1434 * @param telephonyDisplayInfo The {@link TelephonyDisplayInfo} to set. May not be null. 1435 * @throws NullPointerException if telephonyDisplayInfo is null. 1436 */ 1437 public void setTelephonyDisplayInfo(Object telephonyDisplayInfo) { 1438 Preconditions.checkNotNull(telephonyDisplayInfo); 1439 this.telephonyDisplayInfo = telephonyDisplayInfo; 1440 1441 for (PhoneStateListener listener : 1442 getListenersForFlags(PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)) { 1443 listener.onDisplayInfoChanged((TelephonyDisplayInfo) telephonyDisplayInfo); 1444 } 1445 if (VERSION.SDK_INT >= S) { 1446 for (DisplayInfoListener listener : getCallbackForListener(DisplayInfoListener.class)) { 1447 listener.onDisplayInfoChanged((TelephonyDisplayInfo) telephonyDisplayInfo); 1448 } 1449 } 1450 } 1451 1452 @Implementation(minSdk = R) 1453 @HiddenApi 1454 protected boolean isDataConnectionAllowed() { 1455 checkReadPhoneStatePermission(); 1456 return isDataConnectionAllowed; 1457 } 1458 1459 public void setIsDataConnectionAllowed(boolean isDataConnectionAllowed) { 1460 this.isDataConnectionAllowed = isDataConnectionAllowed; 1461 } 1462 1463 @Implementation(minSdk = O) 1464 public void sendVisualVoicemailSms( 1465 String number, int port, String text, PendingIntent sentIntent) { 1466 lastVisualVoicemailSmsParams = new VisualVoicemailSmsParams(number, port, text, sentIntent); 1467 } 1468 1469 public VisualVoicemailSmsParams getLastSentVisualVoicemailSmsParams() { 1470 return lastVisualVoicemailSmsParams; 1471 } 1472 1473 /** 1474 * Implementation for {@link 1475 * TelephonyManager#setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings)}. 1476 * 1477 * @param settings The settings for the filter, or null to disable the filter. 1478 */ 1479 @Implementation(minSdk = O) 1480 public void setVisualVoicemailSmsFilterSettings(VisualVoicemailSmsFilterSettings settings) { 1481 visualVoicemailSmsFilterSettings = settings; 1482 } 1483 1484 /** Returns the last set {@link VisualVoicemailSmsFilterSettings}. */ 1485 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings() { 1486 return visualVoicemailSmsFilterSettings; 1487 } 1488 1489 /** Testable parameters from calls to {@link #sendVisualVoicemailSms}. */ 1490 public static class VisualVoicemailSmsParams { 1491 private final String destinationAddress; 1492 private final int port; 1493 private final String text; 1494 private final PendingIntent sentIntent; 1495 1496 public VisualVoicemailSmsParams( 1497 String destinationAddress, int port, String text, PendingIntent sentIntent) { 1498 this.destinationAddress = destinationAddress; 1499 this.port = port; 1500 this.text = text; 1501 this.sentIntent = sentIntent; 1502 } 1503 1504 public String getDestinationAddress() { 1505 return destinationAddress; 1506 } 1507 1508 public int getPort() { 1509 return port; 1510 } 1511 1512 public String getText() { 1513 return text; 1514 } 1515 1516 public PendingIntent getSentIntent() { 1517 return sentIntent; 1518 } 1519 } 1520 1521 /** 1522 * Sets the emergency numbers list returned by {@link TelephonyManager#getEmergencyNumberList}. 1523 */ 1524 public static void setEmergencyNumberList( 1525 Map<Integer, List<EmergencyNumber>> emergencyNumbersList) { 1526 ShadowTelephonyManager.emergencyNumbersList = emergencyNumbersList; 1527 } 1528 1529 /** 1530 * Implementation for {@link TelephonyManager#getEmergencyNumberList}. 1531 * 1532 * @return an immutable map by default, unless set with {@link #setEmergencyNumberList}. 1533 */ 1534 @Implementation(minSdk = R) 1535 protected Map<Integer, List<EmergencyNumber>> getEmergencyNumberList() { 1536 if (ShadowTelephonyManager.emergencyNumbersList != null) { 1537 return ShadowTelephonyManager.emergencyNumbersList; 1538 } 1539 return ImmutableMap.of(); 1540 } 1541 } 1542