• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.phone.settings;
18 
19 import static android.net.ConnectivityManager.NetworkCallback;
20 import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY;
21 import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE;
22 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
23 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT;
24 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
25 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO;
26 import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
27 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_3G;
28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
29 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
30 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
31 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR;
32 
33 import static java.util.concurrent.TimeUnit.MILLISECONDS;
34 
35 import android.annotation.NonNull;
36 import android.content.ActivityNotFoundException;
37 import android.content.ComponentName;
38 import android.content.DialogInterface;
39 import android.content.Intent;
40 import android.content.pm.ComponentInfo;
41 import android.content.pm.PackageManager;
42 import android.content.pm.ResolveInfo;
43 import android.content.res.Resources;
44 import android.graphics.Typeface;
45 import android.net.ConnectivityManager;
46 import android.net.Network;
47 import android.net.NetworkCapabilities;
48 import android.net.NetworkRequest;
49 import android.net.TrafficStats;
50 import android.net.Uri;
51 import android.os.AsyncResult;
52 import android.os.Build;
53 import android.os.Bundle;
54 import android.os.Handler;
55 import android.os.HandlerExecutor;
56 import android.os.HandlerThread;
57 import android.os.Message;
58 import android.os.PersistableBundle;
59 import android.os.SystemProperties;
60 import android.os.UserHandle;
61 import android.os.UserManager;
62 import android.telephony.AccessNetworkConstants;
63 import android.telephony.CarrierConfigManager;
64 import android.telephony.CellIdentityCdma;
65 import android.telephony.CellIdentityGsm;
66 import android.telephony.CellIdentityLte;
67 import android.telephony.CellIdentityNr;
68 import android.telephony.CellIdentityWcdma;
69 import android.telephony.CellInfo;
70 import android.telephony.CellInfoCdma;
71 import android.telephony.CellInfoGsm;
72 import android.telephony.CellInfoLte;
73 import android.telephony.CellInfoNr;
74 import android.telephony.CellInfoWcdma;
75 import android.telephony.CellSignalStrength;
76 import android.telephony.CellSignalStrengthCdma;
77 import android.telephony.CellSignalStrengthGsm;
78 import android.telephony.CellSignalStrengthLte;
79 import android.telephony.CellSignalStrengthNr;
80 import android.telephony.CellSignalStrengthWcdma;
81 import android.telephony.DataSpecificRegistrationInfo;
82 import android.telephony.NetworkRegistrationInfo;
83 import android.telephony.PhysicalChannelConfig;
84 import android.telephony.RadioAccessFamily;
85 import android.telephony.RadioAccessSpecifier;
86 import android.telephony.ServiceState;
87 import android.telephony.SignalStrength;
88 import android.telephony.SubscriptionManager;
89 import android.telephony.TelephonyCallback;
90 import android.telephony.TelephonyDisplayInfo;
91 import android.telephony.TelephonyManager;
92 import android.telephony.data.NetworkSlicingConfig;
93 import android.telephony.euicc.EuiccManager;
94 import android.telephony.ims.ImsException;
95 import android.telephony.ims.ImsManager;
96 import android.telephony.ims.ImsMmTelManager;
97 import android.telephony.ims.ImsRcsManager;
98 import android.telephony.ims.ProvisioningManager;
99 import android.telephony.ims.feature.MmTelFeature;
100 import android.telephony.satellite.SatelliteManager;
101 import android.text.TextUtils;
102 import android.util.Log;
103 import android.view.Menu;
104 import android.view.MenuItem;
105 import android.view.View;
106 import android.view.View.OnClickListener;
107 import android.widget.AdapterView;
108 import android.widget.ArrayAdapter;
109 import android.widget.Button;
110 import android.widget.CompoundButton;
111 import android.widget.CompoundButton.OnCheckedChangeListener;
112 import android.widget.EditText;
113 import android.widget.RadioGroup;
114 import android.widget.Spinner;
115 import android.widget.Switch;
116 import android.widget.TextView;
117 
118 import androidx.appcompat.app.AlertDialog;
119 import androidx.appcompat.app.AlertDialog.Builder;
120 import androidx.appcompat.app.AppCompatActivity;
121 
122 import com.android.internal.telephony.Phone;
123 import com.android.internal.telephony.PhoneFactory;
124 import com.android.internal.telephony.RILConstants;
125 import com.android.internal.telephony.euicc.EuiccConnector;
126 import com.android.internal.telephony.satellite.SatelliteServiceUtils;
127 import com.android.phone.R;
128 
129 import java.io.IOException;
130 import java.net.HttpURLConnection;
131 import java.net.URL;
132 import java.util.ArrayList;
133 import java.util.Arrays;
134 import java.util.Collections;
135 import java.util.List;
136 import java.util.Locale;
137 import java.util.Map;
138 import java.util.Set;
139 import java.util.concurrent.CompletableFuture;
140 import java.util.concurrent.CountDownLatch;
141 import java.util.concurrent.ExecutionException;
142 import java.util.concurrent.LinkedBlockingDeque;
143 import java.util.concurrent.ThreadPoolExecutor;
144 import java.util.concurrent.TimeUnit;
145 import java.util.concurrent.TimeoutException;
146 import java.util.concurrent.atomic.AtomicBoolean;
147 
148 /**
149  * Radio Information Class
150  *
151  * Allows user to read and alter some of the radio related information.
152  *
153  */
154 public class RadioInfo extends AppCompatActivity {
155     private static final String TAG = "RadioInfo";
156 
157     private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
158 
159     private static final String[] PREFERRED_NETWORK_LABELS = {
160             "GSM/WCDMA preferred",
161             "GSM only",
162             "WCDMA only",
163             "GSM/WCDMA auto (PRL)",
164             "CDMA/EvDo auto (PRL)",
165             "CDMA only",
166             "EvDo only",
167             "CDMA/EvDo/GSM/WCDMA (PRL)",
168             "CDMA + LTE/EvDo (PRL)",
169             "GSM/WCDMA/LTE (PRL)",
170             "LTE/CDMA/EvDo/GSM/WCDMA (PRL)",
171             "LTE only",
172             "LTE/WCDMA",
173             "TDSCDMA only",
174             "TDSCDMA/WCDMA",
175             "LTE/TDSCDMA",
176             "TDSCDMA/GSM",
177             "LTE/TDSCDMA/GSM",
178             "TDSCDMA/GSM/WCDMA",
179             "LTE/TDSCDMA/WCDMA",
180             "LTE/TDSCDMA/GSM/WCDMA",
181             "TDSCDMA/CDMA/EvDo/GSM/WCDMA ",
182             "LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA",
183             "NR only",
184             "NR/LTE",
185             "NR/LTE/CDMA/EvDo",
186             "NR/LTE/GSM/WCDMA",
187             "NR/LTE/CDMA/EvDo/GSM/WCDMA",
188             "NR/LTE/WCDMA",
189             "NR/LTE/TDSCDMA",
190             "NR/LTE/TDSCDMA/GSM",
191             "NR/LTE/TDSCDMA/WCDMA",
192             "NR/LTE/TDSCDMA/GSM/WCDMA",
193             "NR/LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA",
194             "Unknown"
195     };
196 
197     private static final Integer[] SIGNAL_STRENGTH_LEVEL = new Integer[] {
198             -1 /*clear mock*/,
199             CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
200             CellSignalStrength.SIGNAL_STRENGTH_POOR,
201             CellSignalStrength.SIGNAL_STRENGTH_MODERATE,
202             CellSignalStrength.SIGNAL_STRENGTH_GOOD,
203             CellSignalStrength.SIGNAL_STRENGTH_GREAT
204     };
205     private static final Integer[] MOCK_DATA_NETWORK_TYPE = new Integer[] {
206             -1 /*clear mock*/,
207             ServiceState.RIL_RADIO_TECHNOLOGY_GPRS,
208             ServiceState.RIL_RADIO_TECHNOLOGY_EDGE,
209             ServiceState.RIL_RADIO_TECHNOLOGY_UMTS,
210             ServiceState.RIL_RADIO_TECHNOLOGY_IS95A,
211             ServiceState.RIL_RADIO_TECHNOLOGY_IS95B,
212             ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT,
213             ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0,
214             ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A,
215             ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA,
216             ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA,
217             ServiceState.RIL_RADIO_TECHNOLOGY_HSPA,
218             ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B,
219             ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD,
220             ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
221             ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP,
222             ServiceState.RIL_RADIO_TECHNOLOGY_GSM,
223             ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA,
224             ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
225             ServiceState.RIL_RADIO_TECHNOLOGY_NR
226     };
227     private static String[] sPhoneIndexLabels = new String[0];
228 
229     private static final int sCellInfoListRateDisabled = Integer.MAX_VALUE;
230     private static final int sCellInfoListRateMax = 0;
231 
232     private static final String OEM_RADIO_INFO_INTENT =
233             "com.android.phone.settings.OEM_RADIO_INFO";
234 
235     private static final String DSDS_MODE_PROPERTY = "ro.boot.hardware.dsds";
236 
237     /**
238      * A value indicates the device is always on dsds mode.
239      * @see {@link #DSDS_MODE_PROPERTY}
240      */
241     private static final int ALWAYS_ON_DSDS_MODE = 1;
242 
243     //Values in must match CELL_INFO_REFRESH_RATES
244     private static final String[] CELL_INFO_REFRESH_RATE_LABELS = {
245             "Disabled",
246             "Immediate",
247             "Min 5s",
248             "Min 10s",
249             "Min 60s"
250     };
251 
252     //Values in seconds, must match CELL_INFO_REFRESH_RATE_LABELS
253     private static final int [] CELL_INFO_REFRESH_RATES = {
254         sCellInfoListRateDisabled,
255         sCellInfoListRateMax,
256         5000,
257         10000,
258         60000
259     };
260 
log(String s)261     private static void log(String s) {
262         Log.d(TAG, s);
263     }
264 
loge(String s)265     private static void loge(String s) {
266         Log.e(TAG, s);
267     }
268 
269     private static final int EVENT_QUERY_SMSC_DONE = 1005;
270     private static final int EVENT_UPDATE_SMSC_DONE = 1006;
271     private static final int EVENT_UPDATE_NR_STATS = 1008;
272 
273     private static final int MENU_ITEM_VIEW_ADN            = 1;
274     private static final int MENU_ITEM_VIEW_FDN            = 2;
275     private static final int MENU_ITEM_VIEW_SDN            = 3;
276     private static final int MENU_ITEM_GET_IMS_STATUS      = 4;
277     private static final int MENU_ITEM_TOGGLE_DATA         = 5;
278 
279     private static final String CARRIER_PROVISIONING_ACTION =
280             "com.android.phone.settings.CARRIER_PROVISIONING";
281     private static final String TRIGGER_CARRIER_PROVISIONING_ACTION =
282             "com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING";
283 
284     private static final String ACTION_REMOVABLE_ESIM_AS_DEFAULT =
285             "android.telephony.euicc.action.REMOVABLE_ESIM_AS_DEFAULT";
286 
287     private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
288     private TextView mLine1Number;
289     private TextView mSubscriptionId;
290     private TextView mDds;
291     private TextView mSubscriberId;
292     private TextView mCallState;
293     private TextView mOperatorName;
294     private TextView mRoamingState;
295     private TextView mGsmState;
296     private TextView mGprsState;
297     private TextView mVoiceNetwork;
298     private TextView mDataNetwork;
299     private TextView mVoiceRawReg;
300     private TextView mDataRawReg;
301     private TextView mWlanDataRawReg;
302     private TextView mOverrideNetwork;
303     private TextView mDBm;
304     private TextView mMwi;
305     private TextView mCfi;
306     private TextView mCellInfo;
307     private TextView mSent;
308     private TextView mReceived;
309     private TextView mPingHostnameV4;
310     private TextView mPingHostnameV6;
311     private TextView mHttpClientTest;
312     private TextView mPhyChanConfig;
313     private TextView mDownlinkKbps;
314     private TextView mUplinkKbps;
315     private TextView mEndcAvailable;
316     private TextView mDcnrRestricted;
317     private TextView mNrAvailable;
318     private TextView mNrState;
319     private TextView mNrFrequency;
320     private TextView mNetworkSlicingConfig;
321     private TextView mEuiccInfo;
322     private EditText mSmsc;
323     private Switch mRadioPowerOnSwitch;
324     private Switch mSimulateOutOfServiceSwitch;
325     private Switch mEnforceSatelliteChannel;
326     private Switch mMockSatellite;
327     private Switch mMockSatelliteDataSwitch;
328     private RadioGroup mMockSatelliteData;
329     private Button mPingTestButton;
330     private Button mUpdateSmscButton;
331     private Button mRefreshSmscButton;
332     private Button mOemInfoButton;
333     private Button mCarrierProvisioningButton;
334     private Button mTriggerCarrierProvisioningButton;
335     private Button mEsosButton;
336     private Button mSatelliteEnableNonEmergencyModeButton;
337     private Button mEsosDemoButton;
338     private Button mSatelliteConfigViewerButton;
339     private Switch mImsVolteProvisionedSwitch;
340     private Switch mImsVtProvisionedSwitch;
341     private Switch mImsWfcProvisionedSwitch;
342     private Switch mEabProvisionedSwitch;
343     private Switch mCbrsDataSwitch;
344     private Switch mDsdsSwitch;
345     private Switch mRemovableEsimSwitch;
346     private Spinner mPreferredNetworkType;
347     private Spinner mMockSignalStrength;
348     private Spinner mMockDataNetworkType;
349 
350     private Spinner mSelectPhoneIndex;
351     private Spinner mCellInfoRefreshRateSpinner;
352 
353     private static final long RUNNABLE_TIMEOUT_MS = 5 * 60 * 1000L;
354 
355     private ThreadPoolExecutor mQueuedWork;
356 
357     private ConnectivityManager mConnectivityManager;
358     private TelephonyManager mTelephonyManager;
359     private ImsManager mImsManager = null;
360     private Phone mPhone = null;
361     private ProvisioningManager mProvisioningManager = null;
362     private EuiccManager mEuiccManager;
363 
364     private String mPingHostnameResultV4;
365     private String mPingHostnameResultV6;
366     private String mHttpClientTestResult;
367     private boolean mMwiValue = false;
368     private boolean mCfiValue = false;
369 
370     private boolean mSystemUser = true;
371 
372     private final PersistableBundle[] mCarrierSatelliteOriginalBundle = new PersistableBundle[2];
373     private final PersistableBundle[] mSatelliteDataOriginalBundle = new PersistableBundle[2];
374     private final PersistableBundle[] mOriginalSystemChannels = new PersistableBundle[2];
375     private List<CellInfo> mCellInfoResult = null;
376     private final boolean[] mSimulateOos = new boolean[2];
377     private int[] mSelectedSignalStrengthIndex = new int[2];
378     private int[] mSelectedMockDataNetworkTypeIndex = new int[2];
379     private String mEuiccInfoResult = "";
380 
381     private int mPreferredNetworkTypeResult;
382     private int mCellInfoRefreshRateIndex;
383     private int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
384     private static final int DEFAULT_PHONE_ID = 0;
385 
386     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
387 
388     private String mActionEsos;
389     private String mActionEsosDemo;
390     private Intent mNonEsosIntent;
391     private TelephonyDisplayInfo mDisplayInfo;
392     private CarrierConfigManager mCarrierConfigManager;
393 
394     private List<PhysicalChannelConfig> mPhysicalChannelConfigs = new ArrayList<>();
395 
396     private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder()
397             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
398             .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
399             .build();
400 
401     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
402         public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) {
403             int dlbw = nc.getLinkDownstreamBandwidthKbps();
404             int ulbw = nc.getLinkUpstreamBandwidthKbps();
405             updateBandwidths(dlbw, ulbw);
406         }
407     };
408 
409     private static final int DEFAULT_TIMEOUT_MS = 1000;
410 
411     // not final because we need to recreate this object to register on a new subId (b/117555407)
412     private TelephonyCallback mTelephonyCallback = new RadioInfoTelephonyCallback();
413     private class RadioInfoTelephonyCallback extends TelephonyCallback implements
414             TelephonyCallback.DataConnectionStateListener,
415             TelephonyCallback.DataActivityListener,
416             TelephonyCallback.CallStateListener,
417             TelephonyCallback.MessageWaitingIndicatorListener,
418             TelephonyCallback.CallForwardingIndicatorListener,
419             TelephonyCallback.CellInfoListener,
420             TelephonyCallback.SignalStrengthsListener,
421             TelephonyCallback.ServiceStateListener,
422             TelephonyCallback.PhysicalChannelConfigListener,
423             TelephonyCallback.DisplayInfoListener {
424 
425         @Override
onDataConnectionStateChanged(int state, int networkType)426         public void onDataConnectionStateChanged(int state, int networkType) {
427             updateDataState();
428             updateNetworkType();
429         }
430 
431         @Override
onDataActivity(int direction)432         public void onDataActivity(int direction) {
433             updateDataStats2();
434         }
435 
436         @Override
onCallStateChanged(int state)437         public void onCallStateChanged(int state) {
438             updateNetworkType();
439             updatePhoneState(state);
440         }
441 
442         @Override
onMessageWaitingIndicatorChanged(boolean mwi)443         public void onMessageWaitingIndicatorChanged(boolean mwi) {
444             mMwiValue = mwi;
445             updateMessageWaiting();
446         }
447 
448         @Override
onCallForwardingIndicatorChanged(boolean cfi)449         public void onCallForwardingIndicatorChanged(boolean cfi) {
450             mCfiValue = cfi;
451             updateCallRedirect();
452         }
453 
454         @Override
onCellInfoChanged(List<CellInfo> arrayCi)455         public void onCellInfoChanged(List<CellInfo> arrayCi) {
456             log("onCellInfoChanged: arrayCi=" + arrayCi);
457             mCellInfoResult = arrayCi;
458             updateCellInfo(mCellInfoResult);
459         }
460 
461         @Override
onSignalStrengthsChanged(SignalStrength signalStrength)462         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
463             log("onSignalStrengthChanged: SignalStrength=" + signalStrength);
464             updateSignalStrength(signalStrength);
465         }
466 
467         @Override
onServiceStateChanged(ServiceState serviceState)468         public void onServiceStateChanged(ServiceState serviceState) {
469             log("onServiceStateChanged: ServiceState=" + serviceState);
470             updateServiceState(serviceState);
471             updateRadioPowerState();
472             updateNetworkType();
473             updateRawRegistrationState(serviceState);
474             updateImsProvisionedState();
475 
476             // Since update NR stats includes a ril message to get slicing information, it runs
477             // as blocking during the timeout period of 1 second. if ServiceStateChanged event
478             // fires consecutively, RadioInfo can run for more than 10 seconds. This can cause ANR.
479             // Therefore, send event only when there is no same event being processed.
480             if (!mHandler.hasMessages(EVENT_UPDATE_NR_STATS)) {
481                 mHandler.obtainMessage(EVENT_UPDATE_NR_STATS).sendToTarget();
482             }
483         }
484 
485         @Override
onDisplayInfoChanged(TelephonyDisplayInfo displayInfo)486         public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
487             mDisplayInfo = displayInfo;
488             updateNetworkType();
489         }
490 
491         @Override
onPhysicalChannelConfigChanged(@onNull List<PhysicalChannelConfig> configs)492         public void onPhysicalChannelConfigChanged(@NonNull List<PhysicalChannelConfig> configs) {
493             updatePhysicalChannelConfiguration(configs);
494         }
495     }
496 
updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs)497     private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
498         mPhysicalChannelConfigs = configs;
499         StringBuilder sb = new StringBuilder();
500         String div = "";
501         sb.append("{");
502         if (mPhysicalChannelConfigs != null) {
503             for (PhysicalChannelConfig c : mPhysicalChannelConfigs) {
504                 sb.append(div).append(c);
505                 div = ",";
506             }
507         }
508         sb.append("}");
509         mPhyChanConfig.setText(sb.toString());
510     }
511 
updatePreferredNetworkType(int type)512     private void updatePreferredNetworkType(int type) {
513         if (type >= PREFERRED_NETWORK_LABELS.length || type < 0) {
514             log("Network type: unknown type value=" + type);
515             type = PREFERRED_NETWORK_LABELS.length - 1; //set to Unknown
516         }
517         mPreferredNetworkTypeResult = type;
518 
519         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
520     }
521 
updatePhoneIndex()522     private void updatePhoneIndex() {
523         // unregister listeners on the old subId
524         unregisterPhoneStateListener();
525         mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mSubId);
526 
527         // update the subId
528         mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
529 
530         // update the phoneId
531         if (mSystemUser) {
532             mPhone = PhoneFactory.getPhone(mPhoneId);
533         }
534         mImsManager = new ImsManager(this);
535         try {
536             mProvisioningManager = ProvisioningManager.createForSubscriptionId(mSubId);
537         } catch (IllegalArgumentException e) {
538             log("updatePhoneIndex : IllegalArgumentException " + e.getMessage());
539             mProvisioningManager = null;
540         }
541 
542         updateAllFields();
543     }
544 
545     private Handler mHandler = new Handler() {
546         @Override
547         public void handleMessage(Message msg) {
548             AsyncResult ar;
549             switch (msg.what) {
550                 case EVENT_QUERY_SMSC_DONE:
551                     ar = (AsyncResult) msg.obj;
552                     if (ar.exception != null) {
553                         mSmsc.setText("refresh error");
554                     } else {
555                         mSmsc.setText((String) ar.result);
556                     }
557                     break;
558                 case EVENT_UPDATE_SMSC_DONE:
559                     mUpdateSmscButton.setEnabled(true);
560                     ar = (AsyncResult) msg.obj;
561                     if (ar.exception != null) {
562                         mSmsc.setText("update error");
563                     }
564                     break;
565                 case EVENT_UPDATE_NR_STATS:
566                     log("got EVENT_UPDATE_NR_STATS");
567                     updateNrStats();
568                     break;
569                 default:
570                     super.handleMessage(msg);
571                     break;
572 
573             }
574         }
575     };
576 
577     @Override
onCreate(Bundle icicle)578     public void onCreate(Bundle icicle) {
579         super.onCreate(icicle);
580         SettingsConstants.setupEdgeToEdge(this);
581         mSystemUser = android.os.Process.myUserHandle().isSystem();
582         log("onCreate: mSystemUser=" + mSystemUser);
583         UserManager userManager = getSystemService(UserManager.class);
584         if (userManager != null
585                 && userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
586             Log.w(TAG, "User is restricted from configuring mobile networks.");
587             finish();
588             return;
589         }
590 
591         setContentView(R.layout.radio_info);
592         Resources r = getResources();
593         mActionEsos =
594             r.getString(
595                     com.android.internal.R.string
596                             .config_satellite_test_with_esp_replies_intent_action);
597 
598         mActionEsosDemo =
599             r.getString(
600                     com.android.internal.R.string.config_satellite_demo_mode_sos_intent_action);
601 
602         mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
603                 new LinkedBlockingDeque<>());
604         mConnectivityManager = getSystemService(ConnectivityManager.class);
605         if (mSystemUser) {
606             mPhone = getPhone(SubscriptionManager.getDefaultSubscriptionId());
607         }
608         mSubId = SubscriptionManager.getDefaultSubscriptionId();
609         if (mPhone != null) {
610             mPhoneId = mPhone.getPhoneId();
611         } else {
612             mPhoneId = SubscriptionManager.getPhoneId(mSubId);
613         }
614         if (!SubscriptionManager.isValidPhoneId(mPhoneId)) {
615             mPhoneId = DEFAULT_PHONE_ID;
616         }
617 
618         mTelephonyManager = getSystemService(TelephonyManager.class)
619                 .createForSubscriptionId(mSubId);
620         mEuiccManager = getSystemService(EuiccManager.class);
621 
622         mImsManager = new ImsManager(this);
623         try {
624             mProvisioningManager = ProvisioningManager.createForSubscriptionId(mSubId);
625         } catch (IllegalArgumentException e) {
626             log("onCreate : IllegalArgumentException " + e.getMessage());
627             mProvisioningManager = null;
628         }
629 
630         sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager);
631 
632         mDeviceId = (TextView) findViewById(R.id.imei);
633         mLine1Number = (TextView) findViewById(R.id.number);
634         mSubscriptionId = (TextView) findViewById(R.id.subid);
635         mDds = (TextView) findViewById(R.id.dds);
636         mSubscriberId = (TextView) findViewById(R.id.imsi);
637         mCallState = (TextView) findViewById(R.id.call);
638         mOperatorName = (TextView) findViewById(R.id.operator);
639         mRoamingState = (TextView) findViewById(R.id.roaming);
640         mGsmState = (TextView) findViewById(R.id.gsm);
641         mGprsState = (TextView) findViewById(R.id.gprs);
642         mVoiceNetwork = (TextView) findViewById(R.id.voice_network);
643         mDataNetwork = (TextView) findViewById(R.id.data_network);
644         mVoiceRawReg = (TextView) findViewById(R.id.voice_raw_registration_state);
645         mDataRawReg = (TextView) findViewById(R.id.data_raw_registration_state);
646         mWlanDataRawReg = (TextView) findViewById(R.id.wlan_data_raw_registration_state);
647         mOverrideNetwork = (TextView) findViewById(R.id.override_network);
648         mDBm = (TextView) findViewById(R.id.dbm);
649         mMwi = (TextView) findViewById(R.id.mwi);
650         mCfi = (TextView) findViewById(R.id.cfi);
651         mCellInfo = (TextView) findViewById(R.id.cellinfo);
652         mCellInfo.setTypeface(Typeface.MONOSPACE);
653 
654         mSent = (TextView) findViewById(R.id.sent);
655         mReceived = (TextView) findViewById(R.id.received);
656         mSmsc = (EditText) findViewById(R.id.smsc);
657         mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
658         mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
659         mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
660         mEndcAvailable = (TextView) findViewById(R.id.endc_available);
661         mDcnrRestricted = (TextView) findViewById(R.id.dcnr_restricted);
662         mNrAvailable = (TextView) findViewById(R.id.nr_available);
663         mNrState = (TextView) findViewById(R.id.nr_state);
664         mNrFrequency = (TextView) findViewById(R.id.nr_frequency);
665         mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
666         mNetworkSlicingConfig = (TextView) findViewById(R.id.network_slicing_config);
667         mEuiccInfo = (TextView) findViewById(R.id.euicc_info);
668 
669         // hide 5G stats on devices that don't support 5G
670         if ((mTelephonyManager.getSupportedRadioAccessFamily()
671                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
672             setNrStatsVisibility(View.GONE);
673         }
674 
675         mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
676         ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this,
677                 android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS);
678         mPreferredNetworkTypeAdapter
679                 .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
680         mPreferredNetworkType.setAdapter(mPreferredNetworkTypeAdapter);
681 
682         mMockSignalStrength = (Spinner) findViewById(R.id.signalStrength);
683         if (!Build.isDebuggable() || !mSystemUser) {
684             mMockSignalStrength.setVisibility(View.GONE);
685             findViewById(R.id.signalStrength).setVisibility(View.GONE);
686             findViewById(R.id.signal_strength_label).setVisibility(View.GONE);
687         } else {
688             ArrayAdapter<Integer> mSignalStrengthAdapter = new ArrayAdapter<>(this,
689                     android.R.layout.simple_spinner_item, SIGNAL_STRENGTH_LEVEL);
690             mSignalStrengthAdapter
691                     .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
692             mMockSignalStrength.setAdapter(mSignalStrengthAdapter);
693         }
694 
695         mMockDataNetworkType = (Spinner) findViewById(R.id.dataNetworkType);
696         if (!Build.isDebuggable() || !mSystemUser) {
697             mMockDataNetworkType.setVisibility(View.GONE);
698             findViewById(R.id.dataNetworkType).setVisibility(View.GONE);
699             findViewById(R.id.data_network_type_label).setVisibility(View.GONE);
700         } else {
701             ArrayAdapter<String> mNetworkTypeAdapter = new ArrayAdapter<>(this,
702                     android.R.layout.simple_spinner_item, Arrays.stream(MOCK_DATA_NETWORK_TYPE)
703                     .map(ServiceState::rilRadioTechnologyToString).toArray(String[]::new));
704             mNetworkTypeAdapter
705                     .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
706             mMockDataNetworkType.setAdapter(mNetworkTypeAdapter);
707         }
708 
709         mSelectPhoneIndex = (Spinner) findViewById(R.id.phoneIndex);
710         ArrayAdapter<String> phoneIndexAdapter = new ArrayAdapter<String>(this,
711                 android.R.layout.simple_spinner_item, sPhoneIndexLabels);
712         phoneIndexAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
713         mSelectPhoneIndex.setAdapter(phoneIndexAdapter);
714 
715         mCellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select);
716         ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this,
717                 android.R.layout.simple_spinner_item, CELL_INFO_REFRESH_RATE_LABELS);
718         cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
719         mCellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter);
720 
721         mImsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
722         mImsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
723         mImsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
724         mEabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
725 
726         if (!isImsSupportedOnDevice()) {
727             mImsVolteProvisionedSwitch.setVisibility(View.GONE);
728             mImsVtProvisionedSwitch.setVisibility(View.GONE);
729             mImsWfcProvisionedSwitch.setVisibility(View.GONE);
730             mEabProvisionedSwitch.setVisibility(View.GONE);
731         }
732 
733         mCbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch);
734         mCbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE);
735 
736         mDsdsSwitch = findViewById(R.id.dsds_switch);
737         if (isDsdsSupported() && !dsdsModeOnly()) {
738             mDsdsSwitch.setVisibility(View.VISIBLE);
739             mDsdsSwitch.setOnClickListener(v -> {
740                 if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) {
741                     // Undo the click action until user clicks the confirm dialog.
742                     mDsdsSwitch.toggle();
743                     showDsdsChangeDialog();
744                 } else {
745                     performDsdsSwitch();
746                 }
747             });
748             mDsdsSwitch.setChecked(isDsdsEnabled());
749         } else {
750             mDsdsSwitch.setVisibility(View.GONE);
751         }
752 
753         mRemovableEsimSwitch = (Switch) findViewById(R.id.removable_esim_switch);
754         if (!IS_USER_BUILD) {
755             mRemovableEsimSwitch.setEnabled(true);
756             mRemovableEsimSwitch.setChecked(mTelephonyManager.isRemovableEsimDefaultEuicc());
757             mRemovableEsimSwitch.setOnCheckedChangeListener(mRemovableEsimChangeListener);
758         }
759 
760         mRadioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
761 
762         mSimulateOutOfServiceSwitch = (Switch) findViewById(R.id.simulate_out_of_service);
763         if (!Build.isDebuggable()) {
764             mSimulateOutOfServiceSwitch.setVisibility(View.GONE);
765         }
766         mMockSatellite = (Switch) findViewById(R.id.mock_carrier_roaming_satellite);
767         mMockSatelliteDataSwitch = (Switch) findViewById(R.id.satellite_data_controller_switch);
768         mMockSatelliteData = findViewById(R.id.satellite_data_controller);
769         mEnforceSatelliteChannel = (Switch) findViewById(R.id.enforce_satellite_channel);
770         if (!Build.isDebuggable()) {
771             mMockSatellite.setVisibility(View.GONE);
772             mMockSatelliteDataSwitch.setVisibility(View.GONE);
773             mMockSatelliteData.setVisibility(View.GONE);
774             mEnforceSatelliteChannel.setVisibility(View.GONE);
775         }
776 
777         mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
778         mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
779         updateBandwidths(0, 0);
780 
781         mPingTestButton = (Button) findViewById(R.id.ping_test);
782         mPingTestButton.setOnClickListener(mPingButtonHandler);
783         mUpdateSmscButton = (Button) findViewById(R.id.update_smsc);
784         mUpdateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
785         mRefreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
786         mRefreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
787         if (!mSystemUser) {
788             mSmsc.setVisibility(View.GONE);
789             mUpdateSmscButton.setVisibility(View.GONE);
790             mRefreshSmscButton.setVisibility(View.GONE);
791             findViewById(R.id.smsc_label).setVisibility(View.GONE);
792         }
793         mCarrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning);
794         if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) {
795             mCarrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler);
796         } else {
797             mCarrierProvisioningButton.setEnabled(false);
798         }
799 
800         mTriggerCarrierProvisioningButton = (Button) findViewById(
801                 R.id.trigger_carrier_provisioning);
802         if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) {
803             mTriggerCarrierProvisioningButton.setOnClickListener(
804                     mTriggerCarrierProvisioningButtonHandler);
805         } else {
806             mTriggerCarrierProvisioningButton.setEnabled(false);
807         }
808 
809         mEsosButton = (Button) findViewById(R.id.esos_questionnaire);
810         mEsosDemoButton  = (Button) findViewById(R.id.demo_esos_questionnaire);
811         mSatelliteEnableNonEmergencyModeButton = (Button) findViewById(
812                 R.id.satellite_enable_non_emergency_mode);
813         mSatelliteConfigViewerButton = (Button) findViewById(R.id.satellite_config_viewer);
814 
815         if (shouldHideButton(mActionEsos)) {
816             mEsosButton.setVisibility(View.GONE);
817         } else {
818             mEsosButton.setOnClickListener(v -> startActivityAsUser(
819                     new Intent(mActionEsos).addFlags(
820                             Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
821                     UserHandle.CURRENT)
822             );
823         }
824         if (shouldHideButton(mActionEsosDemo)) {
825             mEsosDemoButton.setVisibility(View.GONE);
826         } else {
827             mEsosDemoButton.setOnClickListener(v -> startActivityAsUser(
828                     new Intent(mActionEsosDemo).addFlags(
829                             Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
830                     UserHandle.CURRENT)
831             );
832         }
833         if (shouldHideNonEmergencyMode()) {
834             mSatelliteEnableNonEmergencyModeButton.setVisibility(View.GONE);
835         } else {
836             mSatelliteEnableNonEmergencyModeButton.setOnClickListener(v -> {
837                 if (mNonEsosIntent != null) {
838                     sendBroadcast(mNonEsosIntent);
839                 }
840             });
841         }
842 
843         mSatelliteConfigViewerButton.setOnClickListener(v -> {
844             Intent intent = new Intent(Intent.ACTION_VIEW);
845             intent.putExtra("mSubId", mSubId);
846             intent.setClassName("com.android.phone",
847                     "com.android.phone.settings.SatelliteConfigViewer");
848             startActivityAsUser(intent, UserHandle.CURRENT);
849         });
850 
851         mOemInfoButton = (Button) findViewById(R.id.oem_info);
852         mOemInfoButton.setOnClickListener(mOemInfoButtonHandler);
853         PackageManager pm = getPackageManager();
854         Intent oemInfoIntent = new Intent(OEM_RADIO_INFO_INTENT);
855         List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
856         if (oemInfoIntentList.size() == 0) {
857             mOemInfoButton.setEnabled(false);
858         }
859 
860         mCellInfoRefreshRateIndex = 0; //disabled
861         mPreferredNetworkTypeResult = PREFERRED_NETWORK_LABELS.length - 1; //Unknown
862 
863         new Thread(() -> {
864             int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
865             runOnUiThread(() -> updatePreferredNetworkType(
866                     RadioAccessFamily.getNetworkTypeFromRaf(networkType)));
867         }).start();
868         restoreFromBundle(icicle);
869     }
870 
shouldHideButton(String action)871     boolean shouldHideButton(String action) {
872         if (!Build.isDebuggable()) {
873             return true;
874         }
875         if (TextUtils.isEmpty(action)) {
876             return true;
877         }
878         PackageManager pm = getPackageManager();
879         Intent intent = new Intent(action);
880         if (pm.resolveActivity(intent, 0) == null) {
881             return true;
882         }
883         return false;
884     }
885 
886     @Override
getParentActivityIntent()887     public Intent getParentActivityIntent() {
888         Intent parentActivity = super.getParentActivityIntent();
889         if (parentActivity == null) {
890             parentActivity = (new Intent()).setClassName("com.android.settings",
891                     "com.android.settings.Settings$TestingSettingsActivity");
892         }
893         return parentActivity;
894     }
895 
896     @Override
onResume()897     protected void onResume() {
898         super.onResume();
899 
900         log("Started onResume");
901 
902         updateAllFields();
903     }
904 
updateAllFields()905     private void updateAllFields() {
906         updateMessageWaiting();
907         updateCallRedirect();
908         updateDataState();
909         updateDataStats2();
910         updateRadioPowerState();
911         updateImsProvisionedState();
912         updateProperties();
913         updateNetworkType();
914         updateNrStats();
915         updateEuiccInfo();
916 
917         updateCellInfo(mCellInfoResult);
918         updateSubscriptionIds();
919 
920         mPingHostnameV4.setText(mPingHostnameResultV4);
921         mPingHostnameV6.setText(mPingHostnameResultV6);
922         mHttpClientTest.setText(mHttpClientTestResult);
923 
924         mCellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler);
925         //set selection after registering listener to force update
926         mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
927         // Request cell information update from RIL.
928         mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex],
929                 mSubId);
930 
931         //set selection before registering to prevent update
932         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
933         mPreferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
934 
935         new Thread(() -> {
936             int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
937             runOnUiThread(() -> updatePreferredNetworkType(
938                     RadioAccessFamily.getNetworkTypeFromRaf(networkType)));
939         }).start();
940 
941         // mock signal strength
942         mMockSignalStrength.setSelection(mSelectedSignalStrengthIndex[mPhoneId]);
943         mMockSignalStrength.setOnItemSelectedListener(mOnMockSignalStrengthSelectedListener);
944 
945         // mock data network type
946         mMockDataNetworkType.setSelection(mSelectedMockDataNetworkTypeIndex[mPhoneId]);
947         mMockDataNetworkType.setOnItemSelectedListener(mOnMockDataNetworkTypeSelectedListener);
948 
949         // set phone index
950         mSelectPhoneIndex.setSelection(mPhoneId, true);
951         mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
952 
953         mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
954         mSimulateOutOfServiceSwitch.setChecked(mSimulateOos[mPhoneId]);
955         mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener);
956         mMockSatellite.setChecked(mCarrierSatelliteOriginalBundle[mPhoneId] != null);
957         mMockSatellite.setOnCheckedChangeListener(mMockSatelliteListener);
958         mMockSatelliteDataSwitch.setChecked(mSatelliteDataOriginalBundle[mPhoneId] != null);
959         mMockSatelliteDataSwitch.setOnCheckedChangeListener(mMockSatelliteDataSwitchListener);
960         mMockSatelliteData.setOnCheckedChangeListener(mMockSatelliteDataListener);
961 
962         updateSatelliteChannelDisplay(mPhoneId);
963         mEnforceSatelliteChannel.setOnCheckedChangeListener(mForceSatelliteChannelOnChangeListener);
964         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
965         mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
966         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
967         mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
968 
969         if (isCbrsSupported()) {
970             mCbrsDataSwitch.setChecked(getCbrsDataState());
971             mCbrsDataSwitch.setOnCheckedChangeListener(mCbrsDataSwitchChangeListener);
972         }
973 
974         unregisterPhoneStateListener();
975         registerPhoneStateListener();
976         mConnectivityManager.registerNetworkCallback(
977                 mDefaultNetworkRequest, mNetworkCallback, mHandler);
978         mSmsc.clearFocus();
979     }
980 
981     @Override
onPause()982     protected void onPause() {
983         super.onPause();
984 
985         log("onPause: unregister phone & data intents");
986 
987         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
988         mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mSubId);
989         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
990 
991     }
992 
restoreFromBundle(Bundle b)993     private void restoreFromBundle(Bundle b) {
994         if (b == null) {
995             return;
996         }
997 
998         mPingHostnameResultV4 = b.getString("mPingHostnameResultV4", "");
999         mPingHostnameResultV6 = b.getString("mPingHostnameResultV6", "");
1000         mHttpClientTestResult = b.getString("mHttpClientTestResult", "");
1001 
1002         mPingHostnameV4.setText(mPingHostnameResultV4);
1003         mPingHostnameV6.setText(mPingHostnameResultV6);
1004         mHttpClientTest.setText(mHttpClientTestResult);
1005 
1006         mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult",
1007                 PREFERRED_NETWORK_LABELS.length - 1);
1008 
1009         mPhoneId = b.getInt("mSelectedPhoneIndex", 0);
1010         mSubId = SubscriptionManager.getSubscriptionId(mPhoneId);
1011 
1012         mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0);
1013     }
1014 
1015     @SuppressWarnings("MissingSuperCall") // TODO: Fix me
1016     @Override
onSaveInstanceState(Bundle outState)1017     protected void onSaveInstanceState(Bundle outState) {
1018         outState.putString("mPingHostnameResultV4", mPingHostnameResultV4);
1019         outState.putString("mPingHostnameResultV6", mPingHostnameResultV6);
1020         outState.putString("mHttpClientTestResult", mHttpClientTestResult);
1021 
1022         outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult);
1023         outState.putInt("mSelectedPhoneIndex", mPhoneId);
1024         outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex);
1025 
1026     }
1027 
1028     @Override
onCreateOptionsMenu(Menu menu)1029     public boolean onCreateOptionsMenu(Menu menu) {
1030         // Removed "select Radio band". If need it back, use setSystemSelectionChannels()
1031         menu.add(1, MENU_ITEM_VIEW_ADN, 0,
1032                 R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
1033         menu.add(1, MENU_ITEM_VIEW_FDN, 0,
1034                 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
1035         menu.add(1, MENU_ITEM_VIEW_SDN, 0,
1036                 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
1037         if (isImsSupportedOnDevice()) {
1038             menu.add(1, MENU_ITEM_GET_IMS_STATUS,
1039                     0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
1040         }
1041         menu.add(1, MENU_ITEM_TOGGLE_DATA,
1042                 0, R.string.radio_info_data_connection_disable)
1043                 .setOnMenuItemClickListener(mToggleData);
1044         return true;
1045     }
1046 
1047     @Override
onPrepareOptionsMenu(Menu menu)1048     public boolean onPrepareOptionsMenu(Menu menu) {
1049         // Get the TOGGLE DATA menu item in the right state.
1050         MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
1051         int state = mTelephonyManager.getDataState();
1052         boolean visible = true;
1053 
1054         switch (state) {
1055             case TelephonyManager.DATA_CONNECTED:
1056             case TelephonyManager.DATA_SUSPENDED:
1057                 item.setTitle(R.string.radio_info_data_connection_disable);
1058                 break;
1059             case TelephonyManager.DATA_DISCONNECTED:
1060                 item.setTitle(R.string.radio_info_data_connection_enable);
1061                 break;
1062             default:
1063                 visible = false;
1064                 break;
1065         }
1066         item.setVisible(visible);
1067         return true;
1068     }
1069 
1070     @Override
onDestroy()1071     protected void onDestroy() {
1072         log("onDestroy");
1073         clearOverride();
1074         super.onDestroy();
1075         if (mQueuedWork != null) {
1076             mQueuedWork.shutdown();
1077         }
1078     }
1079 
clearOverride()1080     private void clearOverride() {
1081         for (int phoneId = 0; phoneId < sPhoneIndexLabels.length; phoneId++) {
1082             if (mSystemUser) {
1083                 mPhone = PhoneFactory.getPhone(phoneId);
1084             }
1085             if (mSimulateOos[mPhoneId])  {
1086                 mSimulateOosOnChangeListener.onCheckedChanged(mSimulateOutOfServiceSwitch, false);
1087             }
1088             if (mCarrierSatelliteOriginalBundle[mPhoneId] != null) {
1089                 mMockSatelliteListener.onCheckedChanged(mMockSatellite, false);
1090             }
1091             if (mSatelliteDataOriginalBundle[mPhoneId] != null) {
1092                 mMockSatelliteDataSwitchListener.onCheckedChanged(mMockSatelliteDataSwitch, false);
1093                 mSatelliteDataOriginalBundle[mPhoneId] = null;
1094             }
1095             if (mSelectedSignalStrengthIndex[mPhoneId] > 0) {
1096                 mOnMockSignalStrengthSelectedListener.onItemSelected(null, null, 0/*pos*/, 0);
1097             }
1098             if (mSelectedMockDataNetworkTypeIndex[mPhoneId] > 0) {
1099                 mOnMockDataNetworkTypeSelectedListener.onItemSelected(null, null, 0/*pos*/, 0);
1100             }
1101         }
1102     }
1103 
1104     // returns array of string labels for each phone index. The array index is equal to the phone
1105     // index.
getPhoneIndexLabels(TelephonyManager tm)1106     private static String[] getPhoneIndexLabels(TelephonyManager tm) {
1107         int phones = tm.getPhoneCount();
1108         String[] labels = new String[phones];
1109         for (int i = 0; i < phones; i++) {
1110             labels[i] = "Phone " + i;
1111         }
1112         return labels;
1113     }
1114 
unregisterPhoneStateListener()1115     private void unregisterPhoneStateListener() {
1116         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
1117 
1118         // clear all fields so they are blank until the next listener event occurs
1119         mOperatorName.setText("");
1120         mGprsState.setText("");
1121         mDataNetwork.setText("");
1122         mDataRawReg.setText("");
1123         mOverrideNetwork.setText("");
1124         mVoiceNetwork.setText("");
1125         mVoiceRawReg.setText("");
1126         mWlanDataRawReg.setText("");
1127         mSent.setText("");
1128         mReceived.setText("");
1129         mCallState.setText("");
1130         mMwiValue = false;
1131         mMwi.setText("");
1132         mCfiValue = false;
1133         mCfi.setText("");
1134         mCellInfo.setText("");
1135         mDBm.setText("");
1136         mGsmState.setText("");
1137         mRoamingState.setText("");
1138         mPhyChanConfig.setText("");
1139         mDownlinkKbps.setText("");
1140         mUplinkKbps.setText("");
1141     }
1142 
1143     // register mTelephonyCallback for relevant fields using the current TelephonyManager
registerPhoneStateListener()1144     private void registerPhoneStateListener() {
1145         mTelephonyCallback = new RadioInfoTelephonyCallback();
1146         mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mHandler),
1147                 mTelephonyCallback);
1148     }
1149 
setNrStatsVisibility(int visibility)1150     private void setNrStatsVisibility(int visibility) {
1151         ((TextView) findViewById(R.id.endc_available_label)).setVisibility(visibility);
1152         mEndcAvailable.setVisibility(visibility);
1153         ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(visibility);
1154         mDcnrRestricted.setVisibility(visibility);
1155         ((TextView) findViewById(R.id.nr_available_label)).setVisibility(visibility);
1156         mNrAvailable.setVisibility(visibility);
1157         ((TextView) findViewById(R.id.nr_state_label)).setVisibility(visibility);
1158         mNrState.setVisibility(visibility);
1159         ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(visibility);
1160         mNrFrequency.setVisibility(visibility);
1161         ((TextView) findViewById(R.id.network_slicing_config_label)).setVisibility(visibility);
1162         mNetworkSlicingConfig.setVisibility(visibility);
1163     }
1164 
updateBandwidths(int dlbw, int ulbw)1165     private void updateBandwidths(int dlbw, int ulbw) {
1166         dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw;
1167         ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw;
1168         mDownlinkKbps.setText(String.format("%-5d", dlbw));
1169         mUplinkKbps.setText(String.format("%-5d", ulbw));
1170     }
1171 
updateSignalStrength(SignalStrength signalStrength)1172     private void updateSignalStrength(SignalStrength signalStrength) {
1173         Resources r = getResources();
1174 
1175         int signalDbm = signalStrength.getDbm();
1176 
1177         int signalAsu = signalStrength.getAsuLevel();
1178 
1179         if (-1 == signalAsu) signalAsu = 0;
1180 
1181         mDBm.setText(String.valueOf(signalDbm) + " "
1182                 + r.getString(R.string.radioInfo_display_dbm) + "   "
1183                 + String.valueOf(signalAsu) + " "
1184                 + r.getString(R.string.radioInfo_display_asu));
1185     }
1186 
getCellInfoDisplayString(int i)1187     private String getCellInfoDisplayString(int i) {
1188         return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
1189     }
1190 
getCellInfoDisplayString(long i)1191     private String getCellInfoDisplayString(long i) {
1192         return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
1193     }
1194 
getConnectionStatusString(CellInfo ci)1195     private String getConnectionStatusString(CellInfo ci) {
1196         String regStr = "";
1197         String connStatStr = "";
1198         String connector = "";
1199 
1200         if (ci.isRegistered()) {
1201             regStr = "R";
1202         }
1203         switch (ci.getCellConnectionStatus()) {
1204             case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break;
1205             case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break;
1206             case CellInfo.CONNECTION_NONE: connStatStr = "N"; break;
1207             case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break;
1208             default: break;
1209         }
1210         if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) {
1211             connector = "+";
1212         }
1213 
1214         return regStr + connector + connStatStr;
1215     }
1216 
buildCdmaInfoString(CellInfoCdma ci)1217     private String buildCdmaInfoString(CellInfoCdma ci) {
1218         CellIdentityCdma cidCdma = ci.getCellIdentity();
1219         CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
1220 
1221         return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
1222                 getConnectionStatusString(ci),
1223                 getCellInfoDisplayString(cidCdma.getSystemId()),
1224                 getCellInfoDisplayString(cidCdma.getNetworkId()),
1225                 getCellInfoDisplayString(cidCdma.getBasestationId()),
1226                 getCellInfoDisplayString(ssCdma.getCdmaDbm()),
1227                 getCellInfoDisplayString(ssCdma.getCdmaEcio()),
1228                 getCellInfoDisplayString(ssCdma.getEvdoDbm()),
1229                 getCellInfoDisplayString(ssCdma.getEvdoEcio()),
1230                 getCellInfoDisplayString(ssCdma.getEvdoSnr()));
1231     }
1232 
buildGsmInfoString(CellInfoGsm ci)1233     private String buildGsmInfoString(CellInfoGsm ci) {
1234         CellIdentityGsm cidGsm = ci.getCellIdentity();
1235         CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
1236 
1237         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
1238                 getConnectionStatusString(ci),
1239                 getCellInfoDisplayString(cidGsm.getMcc()),
1240                 getCellInfoDisplayString(cidGsm.getMnc()),
1241                 getCellInfoDisplayString(cidGsm.getLac()),
1242                 getCellInfoDisplayString(cidGsm.getCid()),
1243                 getCellInfoDisplayString(cidGsm.getArfcn()),
1244                 getCellInfoDisplayString(cidGsm.getBsic()),
1245                 getCellInfoDisplayString(ssGsm.getDbm()));
1246     }
1247 
buildLteInfoString(CellInfoLte ci)1248     private String buildLteInfoString(CellInfoLte ci) {
1249         CellIdentityLte cidLte = ci.getCellIdentity();
1250         CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
1251 
1252         return String.format(
1253                 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
1254                 getConnectionStatusString(ci),
1255                 getCellInfoDisplayString(cidLte.getMcc()),
1256                 getCellInfoDisplayString(cidLte.getMnc()),
1257                 getCellInfoDisplayString(cidLte.getTac()),
1258                 getCellInfoDisplayString(cidLte.getCi()),
1259                 getCellInfoDisplayString(cidLte.getPci()),
1260                 getCellInfoDisplayString(cidLte.getEarfcn()),
1261                 getCellInfoDisplayString(cidLte.getBandwidth()),
1262                 getCellInfoDisplayString(ssLte.getDbm()),
1263                 getCellInfoDisplayString(ssLte.getRsrq()),
1264                 getCellInfoDisplayString(ssLte.getTimingAdvance()));
1265     }
1266 
buildNrInfoString(CellInfoNr ci)1267     private String buildNrInfoString(CellInfoNr ci) {
1268         CellIdentityNr cidNr = (CellIdentityNr) ci.getCellIdentity();
1269         CellSignalStrengthNr ssNr = (CellSignalStrengthNr) ci.getCellSignalStrength();
1270 
1271         return String.format(
1272                 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s\n",
1273                 getConnectionStatusString(ci),
1274                 cidNr.getMccString(),
1275                 cidNr.getMncString(),
1276                 getCellInfoDisplayString(cidNr.getTac()),
1277                 getCellInfoDisplayString(cidNr.getNci()),
1278                 getCellInfoDisplayString(cidNr.getPci()),
1279                 getCellInfoDisplayString(cidNr.getNrarfcn()),
1280                 getCellInfoDisplayString(ssNr.getSsRsrp()),
1281                 getCellInfoDisplayString(ssNr.getSsRsrq()));
1282     }
1283 
buildWcdmaInfoString(CellInfoWcdma ci)1284     private String buildWcdmaInfoString(CellInfoWcdma ci) {
1285         CellIdentityWcdma cidWcdma = ci.getCellIdentity();
1286         CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
1287 
1288         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
1289                 getConnectionStatusString(ci),
1290                 getCellInfoDisplayString(cidWcdma.getMcc()),
1291                 getCellInfoDisplayString(cidWcdma.getMnc()),
1292                 getCellInfoDisplayString(cidWcdma.getLac()),
1293                 getCellInfoDisplayString(cidWcdma.getCid()),
1294                 getCellInfoDisplayString(cidWcdma.getUarfcn()),
1295                 getCellInfoDisplayString(cidWcdma.getPsc()),
1296                 getCellInfoDisplayString(ssWcdma.getDbm()));
1297     }
1298 
buildCellInfoString(List<CellInfo> arrayCi)1299     private String buildCellInfoString(List<CellInfo> arrayCi) {
1300         String value = new String();
1301         StringBuilder cdmaCells = new StringBuilder(),
1302                 gsmCells = new StringBuilder(),
1303                 lteCells = new StringBuilder(),
1304                 wcdmaCells = new StringBuilder(),
1305                 nrCells = new StringBuilder();
1306 
1307         if (arrayCi != null) {
1308             for (CellInfo ci : arrayCi) {
1309 
1310                 if (ci instanceof CellInfoLte) {
1311                     lteCells.append(buildLteInfoString((CellInfoLte) ci));
1312                 } else if (ci instanceof CellInfoWcdma) {
1313                     wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci));
1314                 } else if (ci instanceof CellInfoGsm) {
1315                     gsmCells.append(buildGsmInfoString((CellInfoGsm) ci));
1316                 } else if (ci instanceof CellInfoCdma) {
1317                     cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci));
1318                 } else if (ci instanceof CellInfoNr) {
1319                     nrCells.append(buildNrInfoString((CellInfoNr) ci));
1320                 }
1321             }
1322             if (nrCells.length() != 0) {
1323                 value += String.format(
1324                         "NR\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
1325                                 + " %-6.6s %-4.4s %-4.4s\n",
1326                         "SRV", "MCC", "MNC", "TAC", "NCI", "PCI",
1327                         "NRARFCN", "SS-RSRP", "SS-RSRQ");
1328                 value += nrCells.toString();
1329             }
1330 
1331             if (lteCells.length() != 0) {
1332                 value += String.format(
1333                         "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
1334                                 + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
1335                         "SRV", "MCC", "MNC", "TAC", "CID", "PCI",
1336                         "EARFCN", "BW", "RSRP", "RSRQ", "TA");
1337                 value += lteCells.toString();
1338             }
1339             if (wcdmaCells.length() != 0) {
1340                 value += String.format(
1341                         "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
1342                         "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP");
1343                 value += wcdmaCells.toString();
1344             }
1345             if (gsmCells.length() != 0) {
1346                 value += String.format(
1347                         "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
1348                         "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI");
1349                 value += gsmCells.toString();
1350             }
1351             if (cdmaCells.length() != 0) {
1352                 value += String.format(
1353                         "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s"
1354                                 + " %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n",
1355                         "SRV", "SID", "NID", "BSID",
1356                         "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR");
1357                 value += cdmaCells.toString();
1358             }
1359         } else {
1360             value = "unknown";
1361         }
1362 
1363         return value.toString();
1364     }
1365 
updateCellInfo(List<CellInfo> arrayCi)1366     private void updateCellInfo(List<CellInfo> arrayCi) {
1367         mCellInfo.setText(buildCellInfoString(arrayCi));
1368     }
1369 
updateSubscriptionIds()1370     private void updateSubscriptionIds() {
1371         mSubscriptionId.setText(String.format(Locale.ROOT, "%d", mSubId));
1372         mDds.setText(Integer.toString(SubscriptionManager.getDefaultDataSubscriptionId()));
1373     }
1374 
updateMessageWaiting()1375     private void updateMessageWaiting() {
1376         mMwi.setText(String.valueOf(mMwiValue));
1377     }
1378 
updateCallRedirect()1379     private void updateCallRedirect() {
1380         mCfi.setText(String.valueOf(mCfiValue));
1381     }
1382 
1383 
updateServiceState(ServiceState serviceState)1384     private void updateServiceState(ServiceState serviceState) {
1385         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
1386             // When SIM is absent, we can't listen service state change from absent slot. Need
1387             // explicitly get service state from the specific slot.
1388             serviceState = mTelephonyManager.getServiceStateForSlot(mPhoneId);
1389         }
1390         log("Update service state " + serviceState);
1391         int state = serviceState.getState();
1392         Resources r = getResources();
1393         String display = r.getString(R.string.radioInfo_unknown);
1394 
1395         switch (state) {
1396             case ServiceState.STATE_IN_SERVICE:
1397                 display = r.getString(R.string.radioInfo_service_in);
1398                 break;
1399             case ServiceState.STATE_OUT_OF_SERVICE:
1400                 display = r.getString(R.string.radioInfo_service_out);
1401                 break;
1402             case ServiceState.STATE_EMERGENCY_ONLY:
1403                 display = r.getString(R.string.radioInfo_service_emergency);
1404                 break;
1405             case ServiceState.STATE_POWER_OFF:
1406                 display = r.getString(R.string.radioInfo_service_off);
1407                 break;
1408         }
1409 
1410         mGsmState.setText(display);
1411 
1412         if (serviceState.getRoaming()) {
1413             mRoamingState.setText(R.string.radioInfo_roaming_in);
1414         } else {
1415             mRoamingState.setText(R.string.radioInfo_roaming_not);
1416         }
1417 
1418         mOperatorName.setText(serviceState.getOperatorAlphaLong());
1419     }
1420 
updatePhoneState(int state)1421     private void updatePhoneState(int state) {
1422         Resources r = getResources();
1423         String display = r.getString(R.string.radioInfo_unknown);
1424 
1425         switch (state) {
1426             case TelephonyManager.CALL_STATE_IDLE:
1427                 display = r.getString(R.string.radioInfo_phone_idle);
1428                 break;
1429             case TelephonyManager.CALL_STATE_RINGING:
1430                 display = r.getString(R.string.radioInfo_phone_ringing);
1431                 break;
1432             case TelephonyManager.CALL_STATE_OFFHOOK:
1433                 display = r.getString(R.string.radioInfo_phone_offhook);
1434                 break;
1435         }
1436 
1437         mCallState.setText(display);
1438     }
1439 
updateDataState()1440     private void updateDataState() {
1441         int state = mTelephonyManager.getDataState();
1442         Resources r = getResources();
1443         String display = r.getString(R.string.radioInfo_unknown);
1444 
1445         if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
1446             switch (state) {
1447                 case TelephonyManager.DATA_CONNECTED:
1448                     display = r.getString(R.string.radioInfo_data_connected);
1449                     break;
1450                 case TelephonyManager.DATA_CONNECTING:
1451                     display = r.getString(R.string.radioInfo_data_connecting);
1452                     break;
1453                 case TelephonyManager.DATA_DISCONNECTED:
1454                     display = r.getString(R.string.radioInfo_data_disconnected);
1455                     break;
1456                 case TelephonyManager.DATA_SUSPENDED:
1457                     display = r.getString(R.string.radioInfo_data_suspended);
1458                     break;
1459             }
1460         } else {
1461             display = r.getString(R.string.radioInfo_data_disconnected);
1462         }
1463 
1464         mGprsState.setText(display);
1465     }
1466 
updateNetworkType()1467     private void updateNetworkType() {
1468         SubscriptionManager mSm = getSystemService(SubscriptionManager.class);
1469         if (SubscriptionManager.isValidPhoneId(mPhoneId)
1470                 && mSm.isActiveSubscriptionId(mSubId)) {
1471             mDataNetwork.setText(ServiceState.rilRadioTechnologyToString(
1472                     mTelephonyManager.getServiceStateForSlot(mPhoneId)
1473                             .getRilDataRadioTechnology()));
1474             mVoiceNetwork.setText(ServiceState.rilRadioTechnologyToString(
1475                     mTelephonyManager.getServiceStateForSlot(mPhoneId)
1476                             .getRilVoiceRadioTechnology()));
1477             int overrideNetwork = (mDisplayInfo != null
1478                     && SubscriptionManager.isValidSubscriptionId(mSubId))
1479                     ? mDisplayInfo.getOverrideNetworkType()
1480                     : TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
1481             mOverrideNetwork.setText(
1482                     TelephonyDisplayInfo.overrideNetworkTypeToString(overrideNetwork));
1483         }
1484     }
1485 
getRawRegistrationStateText(ServiceState ss, int domain, int transportType)1486     private String getRawRegistrationStateText(ServiceState ss, int domain, int transportType) {
1487         if (ss != null) {
1488             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(domain, transportType);
1489             if (nri != null) {
1490                 return NetworkRegistrationInfo.registrationStateToString(
1491                         nri.getNetworkRegistrationState())
1492                         + (nri.isEmergencyEnabled() ? "_EM" : "");
1493             }
1494         }
1495         return "";
1496     }
1497 
updateRawRegistrationState(ServiceState serviceState)1498     private void updateRawRegistrationState(ServiceState serviceState) {
1499         ServiceState ss = serviceState;
1500         ss = mTelephonyManager.getServiceStateForSlot(mPhoneId);
1501 
1502         mVoiceRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_CS,
1503                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
1504         mDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS,
1505                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
1506         mWlanDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS,
1507                     AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
1508     }
1509 
updateNrStats()1510     private void updateNrStats() {
1511         if ((mTelephonyManager.getSupportedRadioAccessFamily()
1512                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
1513             return;
1514         }
1515         ServiceState ss = mTelephonyManager.getServiceStateForSlot(mPhoneId);
1516         if (ss != null) {
1517             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
1518                     NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1519             if (nri != null) {
1520                 DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
1521                 if (dsri != null) {
1522                     mEndcAvailable.setText(String.valueOf(dsri.isEnDcAvailable));
1523                     mDcnrRestricted.setText(String.valueOf(dsri.isDcNrRestricted));
1524                     mNrAvailable.setText(String.valueOf(dsri.isNrAvailable));
1525                 }
1526             }
1527             mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
1528             mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
1529         } else {
1530             Log.e(TAG, "Clear Nr stats by null service state");
1531             mEndcAvailable.setText("");
1532             mDcnrRestricted.setText("");
1533             mNrAvailable.setText("");
1534             mNrState.setText("");
1535             mNrFrequency.setText("");
1536         }
1537 
1538         CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
1539         mTelephonyManager.getNetworkSlicingConfiguration(Runnable::run, resultFuture::complete);
1540         try {
1541             NetworkSlicingConfig networkSlicingConfig =
1542                     resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS);
1543             mNetworkSlicingConfig.setText(networkSlicingConfig.toString());
1544         } catch (ExecutionException | InterruptedException | TimeoutException e) {
1545             loge("Unable to get slicing config: " + e);
1546             mNetworkSlicingConfig.setText("Unable to get slicing config.");
1547         }
1548 
1549     }
1550 
updateProperties()1551     private void updateProperties() {
1552         String s;
1553         Resources r = getResources();
1554 
1555         s = mTelephonyManager.getImei(mPhoneId);
1556         mDeviceId.setText(s);
1557 
1558         s = mTelephonyManager.getSubscriberId();
1559         if (s == null || !SubscriptionManager.isValidSubscriptionId(mSubId)) {
1560             s = r.getString(R.string.radioInfo_unknown);
1561         }
1562 
1563         mSubscriberId.setText(s);
1564 
1565         SubscriptionManager subMgr = getSystemService(SubscriptionManager.class);
1566         int subId = mSubId;
1567         s = subMgr.getPhoneNumber(subId)
1568                 + " { CARRIER:"
1569                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER)
1570                 + ", UICC:"
1571                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC)
1572                 + ", IMS:"
1573                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS)
1574                 + " }";
1575         mLine1Number.setText(s);
1576     }
1577 
updateDataStats2()1578     private void updateDataStats2() {
1579         Resources r = getResources();
1580 
1581         long txPackets = TrafficStats.getMobileTxPackets();
1582         long rxPackets = TrafficStats.getMobileRxPackets();
1583         long txBytes   = TrafficStats.getMobileTxBytes();
1584         long rxBytes   = TrafficStats.getMobileRxBytes();
1585 
1586         String packets = r.getString(R.string.radioInfo_display_packets);
1587         String bytes   = r.getString(R.string.radioInfo_display_bytes);
1588 
1589         mSent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
1590         mReceived.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
1591     }
1592 
updateEuiccInfo()1593     private void updateEuiccInfo() {
1594         final Runnable setEuiccInfo = new Runnable() {
1595             public void run() {
1596                 mEuiccInfo.setText(mEuiccInfoResult);
1597             }
1598         };
1599 
1600         mQueuedWork.execute(new Runnable() {
1601             @Override
1602             public void run() {
1603                 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_EUICC)) {
1604                     mEuiccInfoResult = "Euicc Feature is disabled";
1605                 } else if (mEuiccManager == null || !mEuiccManager.isEnabled()) {
1606                     mEuiccInfoResult = "EuiccManager is not enabled";
1607                 } else {
1608                     try {
1609                         mEuiccInfoResult = " { Available memory in bytes:"
1610                                 + mEuiccManager.getAvailableMemoryInBytes()
1611                                 + " }";
1612                     } catch (Exception e) {
1613                         mEuiccInfoResult = e.getMessage();
1614                     }
1615                 }
1616                 mHandler.post(setEuiccInfo);
1617             }
1618         });
1619     }
1620 
1621     /**
1622      *  Ping a host name
1623      */
pingHostname()1624     private void pingHostname() {
1625         try {
1626             try {
1627                 Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com");
1628                 int status4 = p4.waitFor();
1629                 if (status4 == 0) {
1630                     mPingHostnameResultV4 = "Pass";
1631                 } else {
1632                     mPingHostnameResultV4 = String.format("Fail(%d)", status4);
1633                 }
1634             } catch (IOException e) {
1635                 mPingHostnameResultV4 = "Fail: IOException";
1636             }
1637             try {
1638                 Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com");
1639                 int status6 = p6.waitFor();
1640                 if (status6 == 0) {
1641                     mPingHostnameResultV6 = "Pass";
1642                 } else {
1643                     mPingHostnameResultV6 = String.format("Fail(%d)", status6);
1644                 }
1645             } catch (IOException e) {
1646                 mPingHostnameResultV6 = "Fail: IOException";
1647             }
1648         } catch (InterruptedException e) {
1649             mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException";
1650         }
1651     }
1652 
1653     /**
1654      * This function checks for basic functionality of HTTP Client.
1655      */
httpClientTest()1656     private void httpClientTest() {
1657         HttpURLConnection urlConnection = null;
1658         try {
1659             // TODO: Hardcoded for now, make it UI configurable
1660             URL url = new URL("https://www.google.com");
1661             urlConnection = (HttpURLConnection) url.openConnection();
1662             if (urlConnection.getResponseCode() == 200) {
1663                 mHttpClientTestResult = "Pass";
1664             } else {
1665                 mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage();
1666             }
1667         } catch (IOException e) {
1668             mHttpClientTestResult = "Fail: IOException";
1669         } finally {
1670             if (urlConnection != null) {
1671                 urlConnection.disconnect();
1672             }
1673         }
1674     }
1675 
refreshSmsc()1676     private void refreshSmsc() {
1677         mQueuedWork.execute(() -> {
1678             if (mSystemUser) {
1679                 mPhone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
1680             }
1681         });
1682     }
1683 
updateAllCellInfo()1684     private void updateAllCellInfo() {
1685 
1686         mCellInfo.setText("");
1687 
1688         final Runnable updateAllCellInfoResults = new Runnable() {
1689             public void run() {
1690                 updateCellInfo(mCellInfoResult);
1691             }
1692         };
1693 
1694         mQueuedWork.execute(new Runnable() {
1695             @Override
1696             public void run() {
1697                 mCellInfoResult = mTelephonyManager.getAllCellInfo();
1698 
1699                 mHandler.post(updateAllCellInfoResults);
1700             }
1701         });
1702     }
1703 
updatePingState()1704     private void updatePingState() {
1705         // Set all to unknown since the threads will take a few secs to update.
1706         mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown);
1707         mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown);
1708         mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
1709 
1710         mPingHostnameV4.setText(mPingHostnameResultV4);
1711         mPingHostnameV6.setText(mPingHostnameResultV6);
1712         mHttpClientTest.setText(mHttpClientTestResult);
1713 
1714         final Runnable updatePingResults = new Runnable() {
1715             public void run() {
1716                 mPingHostnameV4.setText(mPingHostnameResultV4);
1717                 mPingHostnameV6.setText(mPingHostnameResultV6);
1718                 mHttpClientTest.setText(mHttpClientTestResult);
1719             }
1720         };
1721 
1722         Thread hostname = new Thread() {
1723             @Override
1724             public void run() {
1725                 pingHostname();
1726                 mHandler.post(updatePingResults);
1727             }
1728         };
1729         hostname.start();
1730 
1731         Thread httpClient = new Thread() {
1732             @Override
1733             public void run() {
1734                 httpClientTest();
1735                 mHandler.post(updatePingResults);
1736             }
1737         };
1738         httpClient.start();
1739     }
1740 
1741     private MenuItem.OnMenuItemClickListener mViewADNCallback =
1742             new MenuItem.OnMenuItemClickListener() {
1743                 public boolean onMenuItemClick(MenuItem item) {
1744                     Intent intent = new Intent(Intent.ACTION_VIEW);
1745                     // XXX We need to specify the component here because if we don't
1746                     // the activity manager will try to resolve the type by calling
1747                     // the content provider, which causes it to be loaded in a process
1748                     // other than the Dialer process, which causes a lot of stuff to
1749                     // break.
1750                     intent.setClassName("com.android.phone", "com.android.phone.SimContacts");
1751                     startActivityAsUser(intent, UserHandle.CURRENT);
1752                     return true;
1753                 }
1754             };
1755 
1756     private MenuItem.OnMenuItemClickListener mViewFDNCallback =
1757             new MenuItem.OnMenuItemClickListener() {
1758                 public boolean onMenuItemClick(MenuItem item) {
1759                     Intent intent = new Intent(Intent.ACTION_VIEW);
1760                     // XXX We need to specify the component here because if we don't
1761                     // the activity manager will try to resolve the type by calling
1762                     // the content provider, which causes it to be loaded in a process
1763                     // other than the Dialer process, which causes a lot of stuff to
1764                     // break.
1765                     intent.setClassName("com.android.phone",
1766                             "com.android.phone.settings.fdn.FdnList");
1767                     startActivityAsUser(intent, UserHandle.CURRENT);
1768                     return true;
1769                 }
1770             };
1771 
1772     private MenuItem.OnMenuItemClickListener mViewSDNCallback =
1773             new MenuItem.OnMenuItemClickListener() {
1774                 public boolean onMenuItemClick(MenuItem item) {
1775                     Intent intent = new Intent(
1776                             Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
1777                     // XXX We need to specify the component here because if we don't
1778                     // the activity manager will try to resolve the type by calling
1779                     // the content provider, which causes it to be loaded in a process
1780                     // other than the Dialer process, which causes a lot of stuff to
1781                     // break.
1782                     intent.setClassName("com.android.phone", "com.android.phone.ADNList");
1783                     startActivityAsUser(intent, UserHandle.CURRENT);
1784                     return true;
1785                 }
1786             };
1787 
1788     private MenuItem.OnMenuItemClickListener mGetImsStatus =
1789             new MenuItem.OnMenuItemClickListener() {
1790                 public boolean onMenuItemClick(MenuItem item) {
1791                     boolean isSimValid = SubscriptionManager.isValidSubscriptionId(mSubId);
1792                     boolean isImsRegistered = isSimValid && mTelephonyManager.isImsRegistered();
1793                     boolean availableVolte = false;
1794                     boolean availableWfc = false;
1795                     boolean availableVt = false;
1796                     AtomicBoolean availableUt = new AtomicBoolean(false);
1797 
1798                     if (isSimValid) {
1799                         ImsMmTelManager imsMmTelManager = mImsManager.getImsMmTelManager(mSubId);
1800                         availableVolte = isVoiceServiceAvailable(imsMmTelManager);
1801                         availableVt = isVideoServiceAvailable(imsMmTelManager);
1802                         availableWfc = isWfcServiceAvailable(imsMmTelManager);
1803                         CountDownLatch latch = new CountDownLatch(1);
1804                         try {
1805                             HandlerThread handlerThread = new HandlerThread("RadioInfo");
1806                             handlerThread.start();
1807                             imsMmTelManager.isSupported(
1808                                     MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
1809                                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
1810                                     handlerThread.getThreadExecutor(), (result) -> {
1811                                         latch.countDown();
1812                                         availableUt.set(result);
1813                                     });
1814                             latch.await(2, TimeUnit.SECONDS);
1815                             handlerThread.quit();
1816                         } catch (Exception e) {
1817                             loge("Failed to get UT state.");
1818                         }
1819                     }
1820 
1821                     final String imsRegString = isImsRegistered
1822                             ? getString(R.string.radio_info_ims_reg_status_registered)
1823                             : getString(R.string.radio_info_ims_reg_status_not_registered);
1824 
1825                     final String available = getString(
1826                             R.string.radio_info_ims_feature_status_available);
1827                     final String unavailable = getString(
1828                             R.string.radio_info_ims_feature_status_unavailable);
1829 
1830                     String imsStatus = getString(R.string.radio_info_ims_reg_status,
1831                             imsRegString,
1832                             availableVolte ? available : unavailable,
1833                             availableWfc ? available : unavailable,
1834                             availableVt ? available : unavailable,
1835                             availableUt.get() ? available : unavailable);
1836 
1837                     AlertDialog imsDialog = new  AlertDialog.Builder(RadioInfo.this)
1838                             .setMessage(imsStatus)
1839                             .setTitle(getString(R.string.radio_info_ims_reg_status_title))
1840                             .create();
1841 
1842                     imsDialog.show();
1843 
1844                     return true;
1845                 }
1846             };
1847 
1848     private MenuItem.OnMenuItemClickListener mToggleData =
1849             new MenuItem.OnMenuItemClickListener() {
1850         public boolean onMenuItemClick(MenuItem item) {
1851             int state = mTelephonyManager.getDataState();
1852             switch (state) {
1853                 case TelephonyManager.DATA_CONNECTED:
1854                     mTelephonyManager.setDataEnabled(false);
1855                     break;
1856                 case TelephonyManager.DATA_DISCONNECTED:
1857                     mTelephonyManager.setDataEnabled(true);
1858                     break;
1859                 default:
1860                     // do nothing
1861                     break;
1862             }
1863             return true;
1864         }
1865     };
1866 
isRadioOn()1867     private boolean isRadioOn() {
1868         return mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_ON;
1869     }
1870 
updateRadioPowerState()1871     private void updateRadioPowerState() {
1872         //delightful hack to prevent on-checked-changed calls from
1873         //actually forcing the radio preference to its transient/current value.
1874         mRadioPowerOnSwitch.setOnCheckedChangeListener(null);
1875         mRadioPowerOnSwitch.setChecked(isRadioOn());
1876         mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
1877     }
1878 
setImsVolteProvisionedState(boolean state)1879     private void setImsVolteProvisionedState(boolean state) {
1880         Log.d(TAG, "setImsVolteProvisioned state: " + ((state) ? "on" : "off"));
1881         setImsConfigProvisionedState(CAPABILITY_TYPE_VOICE,
1882                 REGISTRATION_TECH_LTE, state);
1883     }
1884 
setImsVtProvisionedState(boolean state)1885     private void setImsVtProvisionedState(boolean state) {
1886         Log.d(TAG, "setImsVtProvisioned() state: " + ((state) ? "on" : "off"));
1887         setImsConfigProvisionedState(CAPABILITY_TYPE_VIDEO,
1888                 REGISTRATION_TECH_LTE, state);
1889     }
1890 
setImsWfcProvisionedState(boolean state)1891     private void setImsWfcProvisionedState(boolean state) {
1892         Log.d(TAG, "setImsWfcProvisioned() state: " + ((state) ? "on" : "off"));
1893         setImsConfigProvisionedState(CAPABILITY_TYPE_VOICE,
1894                 REGISTRATION_TECH_IWLAN, state);
1895     }
1896 
setEabProvisionedState(boolean state)1897     private void setEabProvisionedState(boolean state) {
1898         Log.d(TAG, "setEabProvisioned() state: " + ((state) ? "on" : "off"));
1899         setRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
1900                 REGISTRATION_TECH_LTE, state);
1901     }
1902 
setImsConfigProvisionedState(int capability, int tech, boolean state)1903     private void setImsConfigProvisionedState(int capability, int tech, boolean state) {
1904         if (mProvisioningManager != null) {
1905             mQueuedWork.execute(new Runnable() {
1906                 public void run() {
1907                     try {
1908                         mProvisioningManager.setProvisioningStatusForCapability(
1909                                 capability, tech, state);
1910                     } catch (RuntimeException e) {
1911                         Log.e(TAG, "setImsConfigProvisioned() exception:", e);
1912                     }
1913                 }
1914             });
1915         }
1916     }
1917 
setRcsConfigProvisionedState(int capability, int tech, boolean state)1918     private void setRcsConfigProvisionedState(int capability, int tech, boolean state) {
1919         if (mProvisioningManager != null) {
1920             mQueuedWork.execute(new Runnable() {
1921                 public void run() {
1922                     try {
1923                         mProvisioningManager.setRcsProvisioningStatusForCapability(
1924                                 capability, tech, state);
1925                     } catch (RuntimeException e) {
1926                         Log.e(TAG, "setRcsConfigProvisioned() exception:", e);
1927                     }
1928                 }
1929             });
1930         }
1931     }
1932 
isImsVolteProvisioningRequired()1933     private boolean isImsVolteProvisioningRequired() {
1934         return isImsConfigProvisioningRequired(
1935                 CAPABILITY_TYPE_VOICE,
1936                 REGISTRATION_TECH_LTE);
1937     }
1938 
isImsVtProvisioningRequired()1939     private boolean isImsVtProvisioningRequired() {
1940         return isImsConfigProvisioningRequired(
1941                 CAPABILITY_TYPE_VIDEO,
1942                 REGISTRATION_TECH_LTE);
1943     }
1944 
isImsWfcProvisioningRequired()1945     private boolean isImsWfcProvisioningRequired() {
1946         return isImsConfigProvisioningRequired(
1947                 CAPABILITY_TYPE_VOICE,
1948                 REGISTRATION_TECH_IWLAN);
1949     }
1950 
isEabProvisioningRequired()1951     private boolean isEabProvisioningRequired() {
1952         return isRcsConfigProvisioningRequired(
1953                 ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
1954                 REGISTRATION_TECH_LTE);
1955     }
1956 
isImsConfigProvisioningRequired(int capability, int tech)1957     private boolean isImsConfigProvisioningRequired(int capability, int tech) {
1958         if (mProvisioningManager != null) {
1959             try {
1960                 return mProvisioningManager.isProvisioningRequiredForCapability(
1961                         capability, tech);
1962             } catch (RuntimeException e) {
1963                 Log.e(TAG, "isImsConfigProvisioningRequired() exception:", e);
1964             }
1965         }
1966 
1967         return false;
1968     }
1969 
isRcsConfigProvisioningRequired(int capability, int tech)1970     private boolean isRcsConfigProvisioningRequired(int capability, int tech) {
1971         if (mProvisioningManager != null) {
1972             try {
1973                 return mProvisioningManager.isRcsProvisioningRequiredForCapability(
1974                         capability, tech);
1975             } catch (RuntimeException e) {
1976                 Log.e(TAG, "isRcsConfigProvisioningRequired() exception:", e);
1977             }
1978         }
1979 
1980         return false;
1981     }
1982 
1983     OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
1984         @Override
1985         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1986             // TODO: b/145681511. Within current design, radio power on all of the phones need
1987             // to be controlled at the same time.
1988             Phone[] phones = PhoneFactory.getPhones();
1989             if (phones == null) {
1990                 return;
1991             }
1992             log("toggle radio power: phone*" + phones.length + " " + (isRadioOn() ? "on" : "off"));
1993             for (int phoneIndex = 0; phoneIndex < phones.length; phoneIndex++) {
1994                 if (phones[phoneIndex] != null) {
1995                     phones[phoneIndex].setRadioPower(isChecked);
1996                 }
1997             }
1998         }
1999     };
2000 
2001     private final OnCheckedChangeListener mSimulateOosOnChangeListener = (bv, isChecked) -> {
2002         Intent intent = new Intent("com.android.internal.telephony.TestServiceState");
2003         if (isChecked) {
2004             log("Send OOS override broadcast intent.");
2005             intent.putExtra("data_reg_state", 1);
2006             mSimulateOos[mPhoneId] = true;
2007         } else {
2008             log("Remove OOS override.");
2009             intent.putExtra("action", "reset");
2010             mSimulateOos[mPhoneId] = false;
2011         }
2012         mPhone.getTelephonyTester().setServiceStateTestIntent(intent);
2013     };
2014 
2015     private static final int SATELLITE_CHANNEL = 8665;
2016     private final OnCheckedChangeListener mForceSatelliteChannelOnChangeListener =
2017             (buttonView, isChecked) -> {
2018 
2019                 if (!isValidSubscription(mSubId)) {
2020                     loge("Force satellite channel invalid subId " + mSubId);
2021                     return;
2022                 }
2023                 if (getCarrierConfig() == null) {
2024                     loge("Force satellite channel cm == null");
2025                     return;
2026                 }
2027                 TelephonyManager tm = mTelephonyManager.createForSubscriptionId(mSubId);
2028                 // To be used in thread in case mPhone changes.
2029                 int subId = mSubId;
2030                 int phoneId = mPhoneId;
2031                 if (isChecked) {
2032                     (new Thread(() -> {
2033                         // Override carrier config
2034                         PersistableBundle originalBundle = getCarrierConfig().getConfigForSubId(
2035                                 subId,
2036                                 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
2037                                 KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
2038                                 CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL
2039                         );
2040                         PersistableBundle overrideBundle = new PersistableBundle();
2041                         overrideBundle.putBoolean(
2042                                 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
2043                         overrideBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
2044                         overrideBundle.putBoolean(CarrierConfigManager
2045                                 .KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, true);
2046 
2047                         // Set only allow LTE network type
2048                         try {
2049                             tm.setAllowedNetworkTypesForReason(
2050                                     TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_TEST,
2051                                     RadioAccessFamily.getRafFromNetworkType(
2052                                             RILConstants.NETWORK_MODE_LTE_ONLY));
2053                             log("Force satellite channel set to LTE only");
2054                         } catch (Exception e) {
2055                             loge("Force satellite channel failed to set network type to LTE " + e);
2056                             return;
2057                         }
2058 
2059                         // Set force channel selection
2060                         List<RadioAccessSpecifier> mock = List.of(
2061                                 new RadioAccessSpecifier(
2062                                         AccessNetworkConstants.AccessNetworkType.EUTRAN,
2063                                         new int[]{AccessNetworkConstants.EutranBand.BAND_25},
2064                                         new int[]{SATELLITE_CHANNEL}));
2065                         try {
2066                             log("Force satellite channel new channels " + mock);
2067                             tm.setSystemSelectionChannels(mock);
2068                         } catch (Exception e) {
2069                             loge("Force satellite channel failed to set channels " + e);
2070                             return;
2071                         }
2072                         log("Force satellite channel new config " + overrideBundle);
2073                         getCarrierConfig().overrideConfig(subId, overrideBundle, false);
2074 
2075                         mOriginalSystemChannels[phoneId] = originalBundle;
2076                         log("Force satellite channel old " + mock  + originalBundle);
2077                     })).start();
2078                 } else {
2079                     (new Thread(() -> {
2080                         try {
2081                             tm.setSystemSelectionChannels(
2082                                     Collections.emptyList() /* isSpecifyChannels false */);
2083                             log("Force satellite channel successfully cleared channels ");
2084                             tm.setAllowedNetworkTypesForReason(
2085                                     TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_TEST,
2086                                     TelephonyManager.getAllNetworkTypesBitmask());
2087                             log("Force satellite channel successfully reset network type to "
2088                                     + TelephonyManager.getAllNetworkTypesBitmask());
2089                             PersistableBundle original = mOriginalSystemChannels[phoneId];
2090                             if (original != null) {
2091                                 getCarrierConfig().overrideConfig(subId, original, false);
2092                                 log("Force satellite channel successfully restored config to "
2093                                         + original);
2094                                 mOriginalSystemChannels[phoneId] = null;
2095                             }
2096                         } catch (Exception e) {
2097                             loge("Force satellite channel: Can't clear mock " + e);
2098                         }
2099                     })).start();
2100                 }
2101     };
2102 
updateSatelliteChannelDisplay(int phoneId)2103     private void updateSatelliteChannelDisplay(int phoneId) {
2104         if (mEnforceSatelliteChannel.isChecked()) return;
2105         // Assume in testing mode
2106         (new Thread(() -> {
2107             TelephonyManager tm = mTelephonyManager.createForSubscriptionId(
2108                     SubscriptionManager.getSubscriptionId(phoneId));
2109             try {
2110                 List<RadioAccessSpecifier> channels = tm.getSystemSelectionChannels();
2111                 long networkTypeBitMask = tm.getAllowedNetworkTypesForReason(
2112                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_TEST);
2113                 long lteNetworkBitMask = RadioAccessFamily.getRafFromNetworkType(
2114                         RILConstants.NETWORK_MODE_LTE_ONLY);
2115                 mHandler.post(() -> {
2116                     log("Force satellite get channel " + channels
2117                             + " get networkTypeBitMask " + networkTypeBitMask
2118                             + " lte " + lteNetworkBitMask);
2119                     // if SATELLITE_CHANNEL is the current channel
2120                     mEnforceSatelliteChannel.setChecked(channels.stream().filter(specifier ->
2121                                     specifier.getRadioAccessNetwork()
2122                                             == AccessNetworkConstants.AccessNetworkType.EUTRAN)
2123                             .flatMapToInt(specifier -> Arrays.stream(specifier.getChannels()))
2124                             .anyMatch(channel -> channel == SATELLITE_CHANNEL)
2125                             // OR ALLOWED_NETWORK_TYPES_REASON_TEST is LTE only.
2126                             || (networkTypeBitMask & lteNetworkBitMask) == networkTypeBitMask);
2127                 });
2128             } catch (Exception e) {
2129                 loge("updateSatelliteChannelDisplay " + e);
2130             }
2131         })).start();
2132     }
2133 
2134     /**
2135      * Method will create the PersistableBundle and pack the satellite services like
2136      * SMS, MMS, EMERGENCY CALL, DATA in it.
2137      *
2138      * @return PersistableBundle
2139      */
getSatelliteServicesBundleForOperatorPlmn( PersistableBundle originalBundle)2140     public PersistableBundle getSatelliteServicesBundleForOperatorPlmn(
2141             PersistableBundle originalBundle) {
2142         String plmn = mTelephonyManager.getNetworkOperatorForPhone(mPhoneId);
2143         if (TextUtils.isEmpty(plmn)) {
2144             loge("satData: NetworkOperator PLMN is empty");
2145             plmn = mTelephonyManager.getSimOperatorNumeric(mSubId);
2146             loge("satData: SimOperator PLMN = " + plmn);
2147         }
2148         int[] supportedServicesArray = {NetworkRegistrationInfo.SERVICE_TYPE_DATA,
2149                 NetworkRegistrationInfo.SERVICE_TYPE_SMS,
2150                 NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY,
2151                 NetworkRegistrationInfo.SERVICE_TYPE_MMS};
2152 
2153         PersistableBundle satServicesPerBundle = originalBundle.getPersistableBundle(
2154                 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE);
2155         // New bundle is required, as existed one will throw `ArrayMap is immutable` when we try
2156         // to modify.
2157         PersistableBundle newSatServicesPerBundle = new PersistableBundle();
2158         //Copy the values from the old bundle into the new bundle.
2159         boolean hasPlmnKey = false;
2160         if (satServicesPerBundle != null) {
2161             for (String key : satServicesPerBundle.keySet()) {
2162                 if (!TextUtils.isEmpty(key) && key.equalsIgnoreCase(plmn)) {
2163                     newSatServicesPerBundle.putIntArray(plmn, supportedServicesArray);
2164                     hasPlmnKey = true;
2165                 } else {
2166                     newSatServicesPerBundle.putIntArray(key, satServicesPerBundle.getIntArray(key));
2167                 }
2168             }
2169         }
2170         if (!hasPlmnKey) {
2171             newSatServicesPerBundle.putIntArray(plmn, supportedServicesArray);
2172         }
2173         log("satData: New SatelliteServicesBundle = " + newSatServicesPerBundle);
2174         return newSatServicesPerBundle;
2175     }
2176 
2177     /**
2178      * This method will check the required carrier config keys which plays role in enabling /
2179      * supporting satellite data and update the keys accordingly.
2180      * @param bundleToModify : PersistableBundle
2181      */
updateCarrierConfigToSupportData(PersistableBundle bundleToModify)2182     private void updateCarrierConfigToSupportData(PersistableBundle bundleToModify) {
2183         // KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY key info update
2184         int[] availableServices = bundleToModify.getIntArray(
2185                 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
2186         int[] newServices;
2187         if (availableServices != null && availableServices.length > 0) {
2188             if (Arrays.stream(availableServices).anyMatch(
2189                     element -> element == NetworkRegistrationInfo.SERVICE_TYPE_DATA)) {
2190                 newServices = new int[availableServices.length];
2191                 System.arraycopy(availableServices, 0, newServices, 0, availableServices.length);
2192             } else {
2193                 newServices = new int[availableServices.length + 1];
2194                 System.arraycopy(availableServices, 0, newServices, 0, availableServices.length);
2195                 newServices[newServices.length - 1] = NetworkRegistrationInfo.SERVICE_TYPE_DATA;
2196             }
2197         } else {
2198             newServices = new int[1];
2199             newServices[0] = NetworkRegistrationInfo.SERVICE_TYPE_DATA;
2200         }
2201         bundleToModify.putIntArray(KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
2202                 newServices);
2203         // KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL setting to false.
2204         bundleToModify.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
2205         // Below one not required to update as we are not changing this value.
2206         bundleToModify.remove(KEY_SATELLITE_DATA_SUPPORT_MODE_INT);
2207         log("satData: changing carrierConfig to : " + bundleToModify);
2208         getCarrierConfig().overrideConfig(mSubId, bundleToModify, false);
2209     }
2210 
2211     /**
2212      * Method that restore the previous satellite data mode selection.
2213      */
updateSatelliteDataButton()2214     private void updateSatelliteDataButton() {
2215         if (mSatelliteDataOriginalBundle[mPhoneId] == null) {
2216             // It executes only at first time
2217             PersistableBundle originalBundle = getCarrierConfig().getConfigForSubId(mSubId,
2218                     KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
2219                     KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
2220                     KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
2221                     KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE);
2222             mSatelliteDataOriginalBundle[mPhoneId] = originalBundle;
2223             log("satData: OriginalConfig = " + originalBundle);
2224         }
2225         PersistableBundle currentBundle = getCarrierConfig().getConfigForSubId(mSubId,
2226                 KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
2227                 KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
2228                 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE);
2229         int dataMode = currentBundle.getInt(
2230                 KEY_SATELLITE_DATA_SUPPORT_MODE_INT, -1);
2231         log("satData: present dataMode = " + dataMode);
2232         if (dataMode != -1) {
2233             int checkedId = 0;
2234             switch (dataMode) {
2235                 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED:
2236                     checkedId = R.id.satellite_data_restricted;
2237                     break;
2238                 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED:
2239                     checkedId = R.id.satellite_data_constrained;
2240                     break;
2241                 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL:
2242                     checkedId = R.id.satellite_data_unConstrained;
2243                     break;
2244             }
2245             mMockSatelliteData.check(checkedId);
2246         }
2247         updateCarrierConfigToSupportData(currentBundle);
2248     }
2249 
2250     private final RadioGroup.OnCheckedChangeListener mMockSatelliteDataListener =
2251             (group, checkedId) -> {
2252                 int dataMode = CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
2253                 switch (checkedId) {
2254                     case R.id.satellite_data_restricted:
2255                         dataMode = CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
2256                         break;
2257                     case R.id.satellite_data_constrained:
2258                         dataMode =
2259                                 CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
2260                         break;
2261                     case R.id.satellite_data_unConstrained:
2262                         dataMode = CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
2263                         break;
2264                 }
2265                 log("satData: OnCheckedChangeListener setting dataMode = " + dataMode);
2266                 if (getCarrierConfig() == null) return;
2267                 PersistableBundle overrideBundle = new PersistableBundle();
2268                 overrideBundle.putInt(KEY_SATELLITE_DATA_SUPPORT_MODE_INT, dataMode);
2269                 overrideBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
2270                 if (isValidSubscription(mSubId)) {
2271                     getCarrierConfig().overrideConfig(mSubId, overrideBundle, false);
2272                     log("satData: mMockSatelliteDataListener: Updated new config" + overrideBundle);
2273                 }
2274             };
2275 
2276     private final OnCheckedChangeListener mMockSatelliteDataSwitchListener =
2277             (buttonView, isChecked) -> {
2278         log("satData: ServiceData enabling = " + isChecked);
2279         if (isChecked) {
2280             if (isValidOperator(mSubId)) {
2281                 updateSatelliteDataButton();
2282             } else {
2283                 log("satData: Not a valid Operator");
2284                 mMockSatelliteDataSwitch.setChecked(false);
2285                 return;
2286             }
2287         } else {
2288             reloadCarrierConfigDefaults();
2289         }
2290         setDataModeChangeVisibility(isChecked);
2291     };
2292 
setDataModeChangeVisibility(boolean isChecked)2293     private void setDataModeChangeVisibility(boolean isChecked) {
2294         if (isChecked) {
2295             mMockSatelliteData.setVisibility(View.VISIBLE);
2296         } else {
2297             mMockSatelliteData.setVisibility(View.GONE);
2298         }
2299     }
2300 
reloadCarrierConfigDefaults()2301     private void reloadCarrierConfigDefaults() {
2302         if (mSatelliteDataOriginalBundle[mPhoneId] != null) {
2303             log("satData: Setting originalCarrierConfig = "
2304                     + mSatelliteDataOriginalBundle[mPhoneId]);
2305             getCarrierConfig().overrideConfig(mSubId, mSatelliteDataOriginalBundle[mPhoneId],
2306                     false);
2307             mSatelliteDataOriginalBundle[mPhoneId] = null;
2308         }
2309     }
2310 
isValidOperator(int subId)2311     private boolean isValidOperator(int subId) {
2312         String operatorNumeric = null;
2313         if (isValidSubscription(subId)) {
2314             operatorNumeric = mTelephonyManager.getNetworkOperatorForPhone(mPhoneId);
2315             TelephonyManager tm;
2316             if (TextUtils.isEmpty(operatorNumeric) && (tm = getSystemService(
2317                     TelephonyManager.class)) != null) {
2318                 operatorNumeric = tm.getSimOperatorNumericForPhone(mPhoneId);
2319             }
2320         }
2321         return !TextUtils.isEmpty(operatorNumeric);
2322     }
2323 
2324     /**
2325      * This method will do extra check to validate the subId.
2326      * <p>
2327      * In case user opens the radioInfo when sim is active and enable some checks and go to the
2328      * SIM settings screen and disabled the screen. Upon return to radioInfo screen subId is still
2329      * valid but not in active state any more.
2330      */
isValidSubscription(int subId)2331     private boolean isValidSubscription(int subId) {
2332         boolean isValidSubId = false;
2333         if (SubscriptionManager.isValidSubscriptionId(subId)) {
2334             SubscriptionManager mSm = getSystemService(SubscriptionManager.class);
2335             isValidSubId = mSm.isActiveSubscriptionId(subId);
2336         }
2337         log("isValidSubscription, subId [ " + subId + " ] = " + isValidSubId);
2338         return isValidSubId;
2339     }
2340 
2341     private final OnCheckedChangeListener mMockSatelliteListener =
2342             (buttonView, isChecked) -> {
2343                 int subId = mSubId;
2344                 int phoneId = mPhoneId;
2345                 if (SubscriptionManager.isValidPhoneId(phoneId) && isValidSubscription(subId)) {
2346                     if (getCarrierConfig() == null) return;
2347                     if (isChecked) {
2348                         if (!isValidOperator(subId)) {
2349                             mMockSatellite.setChecked(false);
2350                             loge("mMockSatelliteListener: Can't mock because no operator for phone "
2351                                     + phoneId);
2352                             return;
2353                         }
2354                         PersistableBundle originalBundle = getCarrierConfig().getConfigForSubId(
2355                                 subId, KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
2356                                 KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
2357                                 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE);
2358                         mCarrierSatelliteOriginalBundle[phoneId] = originalBundle;
2359 
2360                         PersistableBundle overrideBundle = new PersistableBundle();
2361                         overrideBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
2362                         // NOTE: In case of TMO setting KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL
2363                         // to false will result in SIM Settings not to show few items, which is
2364                         // expected.
2365                         overrideBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
2366                         overrideBundle.putPersistableBundle(
2367                                 KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
2368                                 getSatelliteServicesBundleForOperatorPlmn(originalBundle));
2369                         log("mMockSatelliteListener: old " + originalBundle);
2370                         log("mMockSatelliteListener: new " + overrideBundle);
2371                         getCarrierConfig().overrideConfig(subId, overrideBundle, false);
2372                     } else {
2373                         try {
2374                             getCarrierConfig().overrideConfig(subId,
2375                                     mCarrierSatelliteOriginalBundle[phoneId], false);
2376                             mCarrierSatelliteOriginalBundle[phoneId] = null;
2377                             log("mMockSatelliteListener: Successfully cleared mock for phone "
2378                                     + phoneId);
2379                         } catch (Exception e) {
2380                             loge("mMockSatelliteListener: Can't clear mock because invalid sub Id "
2381                                     + subId
2382                                     + ", insert SIM and use adb shell cmd phone cc clear-values");
2383                             // Keep show toggle ON if the view is not destroyed. If destroyed, must
2384                             // use cmd to reset, because upon creation the view doesn't remember the
2385                             // last toggle state while override mock is still in place.
2386                             mMockSatellite.setChecked(true);
2387                         }
2388                     }
2389                 }
2390             };
2391 
shouldHideNonEmergencyMode()2392     private boolean shouldHideNonEmergencyMode() {
2393         if (!Build.isDebuggable()) {
2394             return true;
2395         }
2396         String action  = SatelliteManager.ACTION_SATELLITE_START_NON_EMERGENCY_SESSION;
2397         if (TextUtils.isEmpty(action)) {
2398             return true;
2399         }
2400         if (mNonEsosIntent != null) {
2401             mNonEsosIntent = null;
2402         }
2403         if (getCarrierConfig() == null) {
2404             loge("shouldHideNonEmergencyMode: cm is null");
2405             return true;
2406         }
2407         PersistableBundle bundle = getCarrierConfig().getConfigForSubId(mSubId,
2408                 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
2409                 CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
2410         if (!bundle.getBoolean(
2411                 CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false)) {
2412             log("shouldHideNonEmergencyMode: esos_supported false");
2413             return true;
2414         }
2415         if (!bundle.getBoolean(
2416                 KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false)) {
2417             log("shouldHideNonEmergencyMode: attach_supported false");
2418             return true;
2419         }
2420 
2421         String packageName = getStringFromOverlayConfig(
2422                 com.android.internal.R.string.config_satellite_gateway_service_package);
2423 
2424         String className = getStringFromOverlayConfig(com.android.internal.R.string
2425                 .config_satellite_carrier_roaming_non_emergency_session_class);
2426         if (packageName == null || className == null
2427                 || packageName.isEmpty() || className.isEmpty()) {
2428             Log.d(TAG, "shouldHideNonEmergencyMode:"
2429                     + " packageName or className is null or empty.");
2430             return true;
2431         }
2432         PackageManager pm = getPackageManager();
2433         Intent intent = new Intent(action);
2434         intent.setComponent(new ComponentName(packageName, className));
2435         if (pm.queryBroadcastReceivers(intent, 0).isEmpty()) {
2436             Log.d(TAG, "shouldHideNonEmergencyMode: Broadcast receiver not found for intent: "
2437                     + intent);
2438             return true;
2439         }
2440         mNonEsosIntent = intent;
2441         return false;
2442     }
2443 
getStringFromOverlayConfig(int resourceId)2444     private String getStringFromOverlayConfig(int resourceId) {
2445         String name;
2446         try {
2447             name = getResources().getString(resourceId);
2448         } catch (Resources.NotFoundException ex) {
2449             loge("getStringFromOverlayConfig: ex=" + ex);
2450             name = null;
2451         }
2452         return name;
2453     }
2454 
isImsVolteProvisioned()2455     private boolean isImsVolteProvisioned() {
2456         return getImsConfigProvisionedState(CAPABILITY_TYPE_VOICE,
2457                 REGISTRATION_TECH_LTE);
2458     }
2459 
2460     OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
2461         @Override
2462         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2463             setImsVolteProvisionedState(isChecked);
2464         }
2465     };
2466 
isImsVtProvisioned()2467     private boolean isImsVtProvisioned() {
2468         return getImsConfigProvisionedState(CAPABILITY_TYPE_VIDEO,
2469                 REGISTRATION_TECH_LTE);
2470     }
2471 
2472     OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
2473         @Override
2474         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2475             setImsVtProvisionedState(isChecked);
2476         }
2477     };
2478 
isImsWfcProvisioned()2479     private boolean isImsWfcProvisioned() {
2480         return getImsConfigProvisionedState(CAPABILITY_TYPE_VOICE,
2481                 REGISTRATION_TECH_IWLAN);
2482     }
2483 
2484     OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
2485         @Override
2486         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2487             setImsWfcProvisionedState(isChecked);
2488         }
2489     };
2490 
isEabProvisioned()2491     private boolean isEabProvisioned() {
2492         return getRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
2493                 REGISTRATION_TECH_LTE);
2494     }
2495 
2496     OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
2497         @Override
2498         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2499             setEabProvisionedState(isChecked);
2500         }
2501     };
2502 
getImsConfigProvisionedState(int capability, int tech)2503     private boolean getImsConfigProvisionedState(int capability, int tech) {
2504         if (mProvisioningManager != null) {
2505             try {
2506                 return mProvisioningManager.getProvisioningStatusForCapability(
2507                         capability, tech);
2508             } catch (RuntimeException e) {
2509                 Log.e(TAG, "getImsConfigProvisionedState() exception:", e);
2510             }
2511         }
2512 
2513         return false;
2514     }
2515 
getRcsConfigProvisionedState(int capability, int tech)2516     private boolean getRcsConfigProvisionedState(int capability, int tech) {
2517         if (mProvisioningManager != null) {
2518             try {
2519                 return mProvisioningManager.getRcsProvisioningStatusForCapability(
2520                         capability, tech);
2521             } catch (RuntimeException e) {
2522                 Log.e(TAG, "getRcsConfigProvisionedState() exception:", e);
2523             }
2524         }
2525 
2526         return false;
2527     }
2528 
isEabEnabledByPlatform()2529     private boolean isEabEnabledByPlatform() {
2530         if (SubscriptionManager.isValidPhoneId(mPhoneId)) {
2531             PersistableBundle b = getCarrierConfig().getConfigForSubId(mSubId);
2532             if (b != null) {
2533                 return b.getBoolean(
2534                         CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false) || b.getBoolean(
2535                         CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL,
2536                         false);
2537             }
2538         }
2539         return false;
2540     }
2541 
updateImsProvisionedState()2542     private void updateImsProvisionedState() {
2543         if (!isImsSupportedOnDevice()) {
2544             return;
2545         }
2546 
2547         updateServiceEnabledByPlatform();
2548 
2549         updateEabProvisionedSwitch(isEabEnabledByPlatform());
2550     }
2551 
updateVolteProvisionedSwitch(boolean isEnabledByPlatform)2552     private void updateVolteProvisionedSwitch(boolean isEnabledByPlatform) {
2553         boolean isProvisioned = isEnabledByPlatform && isImsVolteProvisioned();
2554         log("updateVolteProvisionedSwitch isProvisioned" + isProvisioned);
2555 
2556         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
2557         mImsVolteProvisionedSwitch.setChecked(isProvisioned);
2558         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
2559         mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD
2560                 && isEnabledByPlatform && isImsVolteProvisioningRequired());
2561     }
2562 
updateVtProvisionedSwitch(boolean isEnabledByPlatform)2563     private void updateVtProvisionedSwitch(boolean isEnabledByPlatform) {
2564         boolean isProvisioned = isEnabledByPlatform && isImsVtProvisioned();
2565         log("updateVtProvisionedSwitch isProvisioned" + isProvisioned);
2566 
2567         mImsVtProvisionedSwitch.setOnCheckedChangeListener(null);
2568         mImsVtProvisionedSwitch.setChecked(isProvisioned);
2569         mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
2570         mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD
2571                 && isEnabledByPlatform && isImsVtProvisioningRequired());
2572     }
2573 
updateWfcProvisionedSwitch(boolean isEnabledByPlatform)2574     private void updateWfcProvisionedSwitch(boolean isEnabledByPlatform) {
2575         boolean isProvisioned = isEnabledByPlatform && isImsWfcProvisioned();
2576         log("updateWfcProvisionedSwitch isProvisioned" + isProvisioned);
2577 
2578         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
2579         mImsWfcProvisionedSwitch.setChecked(isProvisioned);
2580         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
2581         mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD
2582                 && isEnabledByPlatform && isImsWfcProvisioningRequired());
2583     }
2584 
updateEabProvisionedSwitch(boolean isEnabledByPlatform)2585     private void updateEabProvisionedSwitch(boolean isEnabledByPlatform) {
2586         log("updateEabProvisionedSwitch isEabWfcProvisioned()=" + isEabProvisioned());
2587 
2588         mEabProvisionedSwitch.setOnCheckedChangeListener(null);
2589         mEabProvisionedSwitch.setChecked(isEabProvisioned());
2590         mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
2591         mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD
2592                 && isEnabledByPlatform && isEabProvisioningRequired());
2593     }
2594 
2595     OnClickListener mOemInfoButtonHandler = new OnClickListener() {
2596         public void onClick(View v) {
2597             Intent intent = new Intent(OEM_RADIO_INFO_INTENT);
2598             try {
2599                 startActivityAsUser(intent, UserHandle.CURRENT);
2600             } catch (ActivityNotFoundException ex) {
2601                 log("OEM-specific Info/Settings Activity Not Found : " + ex);
2602                 // If the activity does not exist, there are no OEM
2603                 // settings, and so we can just do nothing...
2604             }
2605         }
2606     };
2607 
2608     OnClickListener mPingButtonHandler = new OnClickListener() {
2609         public void onClick(View v) {
2610             updatePingState();
2611         }
2612     };
2613 
2614     OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
2615         public void onClick(View v) {
2616             mUpdateSmscButton.setEnabled(false);
2617             mQueuedWork.execute(() -> {
2618                 if (mSystemUser) {
2619                     mPhone.setSmscAddress(mSmsc.getText().toString(),
2620                             mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
2621                 }
2622             });
2623         }
2624     };
2625 
2626     OnClickListener mRefreshSmscButtonHandler = v -> refreshSmsc();
2627 
2628     OnClickListener mCarrierProvisioningButtonHandler = v -> {
2629         String carrierProvisioningApp = getCarrierProvisioningAppString();
2630         if (!TextUtils.isEmpty(carrierProvisioningApp)) {
2631             final Intent intent = new Intent(CARRIER_PROVISIONING_ACTION);
2632             final ComponentName serviceComponent =
2633                     ComponentName.unflattenFromString(carrierProvisioningApp);
2634             intent.setComponent(serviceComponent);
2635             sendBroadcast(intent);
2636         }
2637     };
2638 
2639     OnClickListener mTriggerCarrierProvisioningButtonHandler = v -> {
2640         String carrierProvisioningApp = getCarrierProvisioningAppString();
2641         if (!TextUtils.isEmpty(carrierProvisioningApp)) {
2642             final Intent intent = new Intent(TRIGGER_CARRIER_PROVISIONING_ACTION);
2643             final ComponentName serviceComponent =
2644                     ComponentName.unflattenFromString(carrierProvisioningApp);
2645             intent.setComponent(serviceComponent);
2646             sendBroadcast(intent);
2647         }
2648     };
2649 
2650     AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
2651             new AdapterView.OnItemSelectedListener() {
2652 
2653         public void onItemSelected(AdapterView parent, View v, int pos, long id) {
2654             if (mPreferredNetworkTypeResult != pos && pos >= 0
2655                     && pos <= PREFERRED_NETWORK_LABELS.length - 2) {
2656                 mPreferredNetworkTypeResult = pos;
2657                 new Thread(() -> {
2658                     mTelephonyManager.setAllowedNetworkTypesForReason(
2659                             TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
2660                             RadioAccessFamily.getRafFromNetworkType(mPreferredNetworkTypeResult));
2661                 }).start();
2662             }
2663         }
2664 
2665         public void onNothingSelected(AdapterView parent) {
2666         }
2667     };
2668 
2669     AdapterView.OnItemSelectedListener mOnMockSignalStrengthSelectedListener =
2670             new AdapterView.OnItemSelectedListener() {
2671 
2672                 public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
2673                     log("mOnSignalStrengthSelectedListener: " + pos);
2674                     mSelectedSignalStrengthIndex[mPhoneId] = pos;
2675                     if (mSystemUser) {
2676                         mPhone.getTelephonyTester().setSignalStrength(SIGNAL_STRENGTH_LEVEL[pos]);
2677                     }
2678                 }
2679 
2680                 public void onNothingSelected(AdapterView<?> parent) {}
2681             };
2682 
2683 
2684     AdapterView.OnItemSelectedListener mOnMockDataNetworkTypeSelectedListener =
2685             new AdapterView.OnItemSelectedListener() {
2686 
2687                 public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
2688                     log("mOnMockDataNetworkTypeSelectedListener: " + pos);
2689                     mSelectedMockDataNetworkTypeIndex[mPhoneId] = pos;
2690                     Intent intent = new Intent("com.android.internal.telephony.TestServiceState");
2691                     if (pos > 0) {
2692                         log("mOnMockDataNetworkTypeSelectedListener: Override RAT: "
2693                                 + ServiceState.rilRadioTechnologyToString(
2694                                         MOCK_DATA_NETWORK_TYPE[pos]));
2695                         intent.putExtra("data_reg_state", ServiceState.STATE_IN_SERVICE);
2696                         intent.putExtra("data_rat", MOCK_DATA_NETWORK_TYPE[pos]);
2697                     } else {
2698                         log("mOnMockDataNetworkTypeSelectedListener: Remove RAT override.");
2699                         intent.putExtra("action", "reset");
2700                     }
2701 
2702                     if (mSystemUser) {
2703                         mPhone.getTelephonyTester().setServiceStateTestIntent(intent);
2704                     }
2705                 }
2706 
2707                 public void onNothingSelected(AdapterView<?> parent) {}
2708             };
2709 
2710     AdapterView.OnItemSelectedListener mSelectPhoneIndexHandler =
2711             new AdapterView.OnItemSelectedListener() {
2712 
2713                 public void onItemSelected(AdapterView parent, View v, int pos, long id) {
2714                     if (pos >= 0 && pos <= sPhoneIndexLabels.length - 1) {
2715                         if (mTelephonyManager.getActiveModemCount() <= pos) {
2716                             return;
2717                         }
2718 
2719                         mPhoneId = pos;
2720                         mSubId = SubscriptionManager.getSubscriptionId(mPhoneId);
2721                         log("Updated phone id to " + mPhoneId + ", sub id to " + mSubId);
2722                         updatePhoneIndex();
2723                     }
2724                 }
2725 
2726                 public void onNothingSelected(AdapterView parent) {
2727                 }
2728             };
2729 
2730     AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler =
2731             new AdapterView.OnItemSelectedListener() {
2732 
2733                 public void onItemSelected(AdapterView parent, View v, int pos, long id) {
2734                     mCellInfoRefreshRateIndex = pos;
2735                     mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos], mPhoneId);
2736                     updateAllCellInfo();
2737                 }
2738 
2739                 public void onNothingSelected(AdapterView parent) {
2740                 }
2741             };
2742 
getCarrierProvisioningAppString()2743     private String getCarrierProvisioningAppString() {
2744         if (SubscriptionManager.isValidPhoneId(mPhoneId)) {
2745             PersistableBundle b = getCarrierConfig().getConfigForSubId(mSubId);
2746             if (b != null) {
2747                 return b.getString(
2748                         CarrierConfigManager.KEY_CARRIER_PROVISIONING_APP_STRING, "");
2749             }
2750         }
2751         return "";
2752     }
2753 
isCbrsSupported()2754     boolean isCbrsSupported() {
2755         return getResources().getBoolean(
2756               com.android.internal.R.bool.config_cbrs_supported);
2757     }
2758 
updateCbrsDataState(boolean state)2759     void updateCbrsDataState(boolean state) {
2760         Log.d(TAG, "setCbrsDataSwitchState() state:" + ((state) ? "on" : "off"));
2761         if (mTelephonyManager != null) {
2762             mQueuedWork.execute(new Runnable() {
2763                 public void run() {
2764                     mTelephonyManager.setOpportunisticNetworkState(state);
2765                     mHandler.post(() -> mCbrsDataSwitch.setChecked(getCbrsDataState()));
2766                 }
2767             });
2768         }
2769     }
2770 
getCbrsDataState()2771     boolean getCbrsDataState() {
2772         boolean state = false;
2773         if (mTelephonyManager != null) {
2774             state = mTelephonyManager.isOpportunisticNetworkEnabled();
2775         }
2776         Log.d(TAG, "getCbrsDataState() state:" + ((state) ? "on" : "off"));
2777         return state;
2778     }
2779 
2780     OnCheckedChangeListener mCbrsDataSwitchChangeListener = new OnCheckedChangeListener() {
2781         @Override
2782         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2783             updateCbrsDataState(isChecked);
2784         }
2785     };
2786 
showDsdsChangeDialog()2787     private void showDsdsChangeDialog() {
2788         final AlertDialog confirmDialog = new Builder(RadioInfo.this)
2789                 .setTitle(R.string.dsds_dialog_title)
2790                 .setMessage(R.string.dsds_dialog_message)
2791                 .setPositiveButton(R.string.dsds_dialog_confirm, mOnDsdsDialogConfirmedListener)
2792                 .setNegativeButton(R.string.dsds_dialog_cancel, mOnDsdsDialogConfirmedListener)
2793                 .create();
2794         confirmDialog.show();
2795     }
2796 
isDsdsSupported()2797     private static boolean isDsdsSupported() {
2798         return (TelephonyManager.getDefault().isMultiSimSupported()
2799             == TelephonyManager.MULTISIM_ALLOWED);
2800     }
2801 
isDsdsEnabled()2802     private static boolean isDsdsEnabled() {
2803         return TelephonyManager.getDefault().getPhoneCount() > 1;
2804     }
2805 
performDsdsSwitch()2806     private void performDsdsSwitch() {
2807         mTelephonyManager.switchMultiSimConfig(mDsdsSwitch.isChecked() ? 2 : 1);
2808     }
2809 
2810     /**
2811      * @return {@code True} if the device is only supported dsds mode.
2812      */
dsdsModeOnly()2813     private boolean dsdsModeOnly() {
2814         String dsdsMode = SystemProperties.get(DSDS_MODE_PROPERTY);
2815         return !TextUtils.isEmpty(dsdsMode) && Integer.parseInt(dsdsMode) == ALWAYS_ON_DSDS_MODE;
2816     }
2817 
2818     DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener =
2819             new DialogInterface.OnClickListener() {
2820         @Override
2821         public void onClick(DialogInterface dialog, int which) {
2822             if (which == DialogInterface.BUTTON_POSITIVE) {
2823                 mDsdsSwitch.toggle();
2824                 performDsdsSwitch();
2825             }
2826         }
2827     };
2828 
2829     OnCheckedChangeListener mRemovableEsimChangeListener = new OnCheckedChangeListener() {
2830         @Override
2831         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2832             setRemovableEsimAsDefaultEuicc(isChecked);
2833         }
2834     };
2835 
setRemovableEsimAsDefaultEuicc(boolean isChecked)2836     private void setRemovableEsimAsDefaultEuicc(boolean isChecked) {
2837         Log.d(TAG, "setRemovableEsimAsDefaultEuicc isChecked: " + isChecked);
2838         mTelephonyManager.setRemovableEsimAsDefaultEuicc(isChecked);
2839         // TODO(b/232528117): Instead of sending intent, add new APIs in platform,
2840         //  LPA can directly use the API.
2841         ComponentInfo componentInfo = EuiccConnector.findBestComponent(getPackageManager());
2842         if (componentInfo == null) {
2843             Log.d(TAG, "setRemovableEsimAsDefaultEuicc: unable to find suitable component info");
2844             return;
2845         }
2846         final Intent intent = new Intent(ACTION_REMOVABLE_ESIM_AS_DEFAULT);
2847         intent.setPackage(componentInfo.packageName);
2848         intent.putExtra("isDefault", isChecked);
2849         sendBroadcast(intent);
2850     }
2851 
isImsSupportedOnDevice()2852     private boolean isImsSupportedOnDevice() {
2853         return getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS);
2854     }
2855 
updateServiceEnabledByPlatform()2856     private void updateServiceEnabledByPlatform() {
2857         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
2858             log("updateServiceEnabledByPlatform subscription ID is invalid");
2859             return;
2860         }
2861 
2862         ImsMmTelManager imsMmTelManager = mImsManager.getImsMmTelManager(mSubId);
2863         try {
2864             imsMmTelManager.isSupported(CAPABILITY_TYPE_VOICE,
2865                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
2866                         updateVolteProvisionedSwitch(result);
2867                     });
2868             imsMmTelManager.isSupported(CAPABILITY_TYPE_VIDEO,
2869                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
2870                         updateVtProvisionedSwitch(result);
2871                     });
2872             imsMmTelManager.isSupported(CAPABILITY_TYPE_VOICE,
2873                     AccessNetworkConstants.TRANSPORT_TYPE_WLAN, getMainExecutor(), (result) -> {
2874                         updateWfcProvisionedSwitch(result);
2875                     });
2876         } catch (ImsException e) {
2877             e.printStackTrace();
2878         }
2879     }
2880 
getPhone(int subId)2881     private Phone getPhone(int subId) {
2882         log("getPhone subId = " + subId);
2883         Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
2884         if (phone == null) {
2885             log("return the default phone");
2886             return PhoneFactory.getDefaultPhone();
2887         }
2888 
2889         return phone;
2890     }
2891 
isVoiceServiceAvailable(ImsMmTelManager imsMmTelManager)2892     private boolean isVoiceServiceAvailable(ImsMmTelManager imsMmTelManager) {
2893         if (imsMmTelManager == null) {
2894             log("isVoiceServiceAvailable: ImsMmTelManager is null");
2895             return false;
2896         }
2897 
2898         final int[] radioTechs = {
2899             REGISTRATION_TECH_LTE,
2900             REGISTRATION_TECH_CROSS_SIM,
2901             REGISTRATION_TECH_NR,
2902             REGISTRATION_TECH_3G
2903         };
2904 
2905         boolean isAvailable = false;
2906         for (int tech : radioTechs) {
2907             try {
2908                 isAvailable |= imsMmTelManager.isAvailable(CAPABILITY_TYPE_VOICE, tech);
2909                 if (isAvailable) {
2910                     break;
2911                 }
2912             } catch (Exception e) {
2913                 log("isVoiceServiceAvailable: exception " + e.getMessage());
2914             }
2915         }
2916 
2917         log("isVoiceServiceAvailable: " + isAvailable);
2918         return isAvailable;
2919     }
2920 
isVideoServiceAvailable(ImsMmTelManager imsMmTelManager)2921     private boolean isVideoServiceAvailable(ImsMmTelManager imsMmTelManager) {
2922         if (imsMmTelManager == null) {
2923             log("isVideoServiceAvailable: ImsMmTelManager is null");
2924             return false;
2925         }
2926 
2927         final int[] radioTechs = {
2928             REGISTRATION_TECH_LTE,
2929             REGISTRATION_TECH_IWLAN,
2930             REGISTRATION_TECH_CROSS_SIM,
2931             REGISTRATION_TECH_NR,
2932             REGISTRATION_TECH_3G
2933         };
2934 
2935         boolean isAvailable = false;
2936         for (int tech : radioTechs) {
2937             try {
2938                 isAvailable |= imsMmTelManager.isAvailable(CAPABILITY_TYPE_VIDEO, tech);
2939                 if (isAvailable) {
2940                     break;
2941                 }
2942             } catch (Exception e) {
2943                 log("isVideoServiceAvailable: exception " + e.getMessage());
2944             }
2945         }
2946 
2947         log("isVideoServiceAvailable: " + isAvailable);
2948         return isAvailable;
2949     }
2950 
isWfcServiceAvailable(ImsMmTelManager imsMmTelManager)2951     private boolean isWfcServiceAvailable(ImsMmTelManager imsMmTelManager) {
2952         if (imsMmTelManager == null) {
2953             log("isWfcServiceAvailable: ImsMmTelManager is null");
2954             return false;
2955         }
2956 
2957         boolean isAvailable = false;
2958         try {
2959             isAvailable = imsMmTelManager.isAvailable(CAPABILITY_TYPE_VOICE,
2960                     REGISTRATION_TECH_IWLAN);
2961         } catch (Exception e) {
2962             log("isWfcServiceAvailable: exception " + e.getMessage());
2963         }
2964 
2965         log("isWfcServiceAvailable: " + isAvailable);
2966         return isAvailable;
2967     }
2968 
getCarrierConfig()2969     private CarrierConfigManager getCarrierConfig() {
2970         if (mCarrierConfigManager == null) {
2971             mCarrierConfigManager = getSystemService(CarrierConfigManager.class);
2972         }
2973         return mCarrierConfigManager;
2974     }
2975 }
2976