We show the entry point on any device which supports eUICC as long as either the eUICC
+ * was ever provisioned (that is, at least one profile was ever downloaded onto it), or if
+ * the user has enabled development mode.
+ */
+ public static boolean showEuiccSettings(Context context) {
+ EuiccManager euiccManager =
+ (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
+ if (!euiccManager.isEnabled()) {
+ return false;
+ }
+
+ final ContentResolver cr = context.getContentResolver();
+
+ TelephonyManager tm =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ String currentCountry = tm.getNetworkCountryIso().toLowerCase();
+ String supportedCountries =
+ Settings.Global.getString(cr, Settings.Global.EUICC_SUPPORTED_COUNTRIES);
+ boolean inEsimSupportedCountries = false;
+ if (TextUtils.isEmpty(currentCountry)) {
+ inEsimSupportedCountries = true;
+ } else if (!TextUtils.isEmpty(supportedCountries)) {
+ List This method can be called multiple times in one network scan, until
+ * {@link #onComplete()} or {@link #onError(int)} is called.
+ *
+ * @param results
+ */
+ void onResults(List There is no more result returned from {@link TelephonyManager} if an error occurred.
+ *
+ * {@link #onComplete()} will not be called if an error occurred.
+ *
+ * @see {@link NetworkScan.ScanErrorCode}
+ */
+ void onError(int errorCode);
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
+ public @interface NetworkQueryType {}
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
+ * scan results won't be returned to the caller until the network scan is completed.
+ *
+ * This is typically used when the modem doesn't support the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ */
+ public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
+
+ /**
+ * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
+ * results will be returned to the caller periodically in a small time window until the network
+ * scan is completed. The complete results should be returned in the last called of
+ * {@link NetworkScanCallback#onResults(List)}.
+ *
+ * This is recommended to be used if modem supports the new network scan api
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+ */
+ public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
+
+ /** The constants below are used in the async network scan. */
+ private static final boolean INCREMENTAL_RESULTS = true;
+ private static final int SEARCH_PERIODICITY_SEC = 5;
+ private static final int MAX_SEARCH_TIME_SEC = 300;
+ private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
+
+ private static final NetworkScanRequest NETWORK_SCAN_REQUEST =
+ new NetworkScanRequest(
+ NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
+ new RadioAccessSpecifier[]{
+ // GSM
+ new RadioAccessSpecifier(
+ AccessNetworkType.GERAN,
+ null /* bands */,
+ null /* channels */),
+ // LTE
+ new RadioAccessSpecifier(
+ AccessNetworkType.EUTRAN,
+ null /* bands */,
+ null /* channels */),
+ // WCDMA
+ new RadioAccessSpecifier(
+ AccessNetworkType.UTRAN,
+ null /* bands */,
+ null /* channels */)
+ },
+ SEARCH_PERIODICITY_SEC,
+ MAX_SEARCH_TIME_SEC,
+ INCREMENTAL_RESULTS,
+ INCREMENTAL_RESULTS_PERIODICITY_SEC,
+ null /* List of PLMN ids (MCC-MNC) */);
+
+ private final NetworkScanCallback mNetworkScanCallback;
+ private final TelephonyManager mTelephonyManager;
+ private final TelephonyScanManager.NetworkScanCallback mInternalNetworkScanCallback;
+ private final Executor mExecutor;
+
+ private NetworkScan mNetworkScanRequester;
+
+ /** Callbacks for sync network scan */
+ private ListenableFuture> mNetworkScanFuture;
+
+ public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
+ mTelephonyManager = tm;
+ mNetworkScanCallback = callback;
+ mInternalNetworkScanCallback = new NetworkScanCallbackImpl();
+ mExecutor = executor;
+ }
+
+ /**
+ * Performs a network scan for the given type {@code type}.
+ * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
+ * {@link TelephonyManager#requestNetworkScan(
+ * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+ *
+ * @param type used to tell which network scan API should be used.
+ */
+ public void startNetworkScan(@NetworkQueryType int type) {
+ if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
+ mNetworkScanFuture = SettableFuture.create();
+ Futures.addCallback(mNetworkScanFuture, new FutureCallback
>() {
+ @Override
+ public void onSuccess(List
> mCallback;
+ private final TelephonyManager mTelephonyManager;
+
+ NetworkScanSyncTask(
+ TelephonyManager telephonyManager, SettableFuture
> callback) {
+ mTelephonyManager = telephonyManager;
+ mCallback = callback;
+ }
+
+ @Override
+ public void run() {
+ if (DBG) Log.d(TAG, "sync scan start");
+ CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
+ if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
+ List