• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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