Home | History | Annotate | Download | only in simstatus
      1 /*
      2  * Copyright (C) 2017 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.settings.deviceinfo.simstatus;
     18 
     19 import static android.content.Context.CARRIER_CONFIG_SERVICE;
     20 import static android.content.Context.EUICC_SERVICE;
     21 import static android.content.Context.TELEPHONY_SERVICE;
     22 
     23 import android.Manifest;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.pm.PackageManager;
     29 import android.content.res.Resources;
     30 import android.os.Bundle;
     31 import android.os.PersistableBundle;
     32 import android.os.UserHandle;
     33 import android.support.annotation.NonNull;
     34 import android.support.annotation.VisibleForTesting;
     35 import android.telephony.CarrierConfigManager;
     36 import android.telephony.CellBroadcastMessage;
     37 import android.telephony.PhoneStateListener;
     38 import android.telephony.ServiceState;
     39 import android.telephony.SignalStrength;
     40 import android.telephony.SubscriptionInfo;
     41 import android.telephony.SubscriptionManager;
     42 import android.telephony.TelephonyManager;
     43 import android.telephony.euicc.EuiccManager;
     44 import android.text.BidiFormatter;
     45 import android.text.TextDirectionHeuristics;
     46 import android.text.TextUtils;
     47 import android.util.Log;
     48 
     49 import com.android.settings.R;
     50 import com.android.settingslib.DeviceInfoUtils;
     51 import com.android.settingslib.core.lifecycle.Lifecycle;
     52 import com.android.settingslib.core.lifecycle.LifecycleObserver;
     53 import com.android.settingslib.core.lifecycle.events.OnPause;
     54 import com.android.settingslib.core.lifecycle.events.OnResume;
     55 
     56 import java.util.List;
     57 
     58 public class SimStatusDialogController implements LifecycleObserver, OnResume, OnPause {
     59 
     60     private final static String TAG = "SimStatusDialogCtrl";
     61 
     62     @VisibleForTesting
     63     final static int NETWORK_PROVIDER_VALUE_ID = R.id.operator_name_value;
     64     @VisibleForTesting
     65     final static int PHONE_NUMBER_VALUE_ID = R.id.number_value;
     66     @VisibleForTesting
     67     final static int CELLULAR_NETWORK_STATE = R.id.data_state_value;
     68     @VisibleForTesting
     69     final static int OPERATOR_INFO_LABEL_ID = R.id.latest_area_info_label;
     70     @VisibleForTesting
     71     final static int OPERATOR_INFO_VALUE_ID = R.id.latest_area_info_value;
     72     @VisibleForTesting
     73     final static int SERVICE_STATE_VALUE_ID = R.id.service_state_value;
     74     @VisibleForTesting
     75     final static int SIGNAL_STRENGTH_LABEL_ID = R.id.signal_strength_label;
     76     @VisibleForTesting
     77     final static int SIGNAL_STRENGTH_VALUE_ID = R.id.signal_strength_value;
     78     @VisibleForTesting
     79     final static int CELL_VOICE_NETWORK_TYPE_VALUE_ID = R.id.voice_network_type_value;
     80     @VisibleForTesting
     81     final static int CELL_DATA_NETWORK_TYPE_VALUE_ID = R.id.data_network_type_value;
     82     @VisibleForTesting
     83     final static int ROAMING_INFO_VALUE_ID = R.id.roaming_state_value;
     84     @VisibleForTesting
     85     final static int ICCID_INFO_LABEL_ID = R.id.icc_id_label;
     86     @VisibleForTesting
     87     final static int ICCID_INFO_VALUE_ID = R.id.icc_id_value;
     88     @VisibleForTesting
     89     final static int EID_INFO_VALUE_ID = R.id.esim_id_value;
     90     @VisibleForTesting
     91     final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label;
     92     @VisibleForTesting
     93     final static int IMS_REGISTRATION_STATE_VALUE_ID = R.id.ims_reg_state_value;
     94 
     95     private final static String CB_AREA_INFO_RECEIVED_ACTION =
     96             "com.android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
     97     private final static String GET_LATEST_CB_AREA_INFO_ACTION =
     98             "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
     99     private final static String CELL_BROADCAST_RECEIVER_APP = "com.android.cellbroadcastreceiver";
    100 
    101     private final SimStatusDialogFragment mDialog;
    102     private final SubscriptionInfo mSubscriptionInfo;
    103     private final TelephonyManager mTelephonyManager;
    104     private final CarrierConfigManager mCarrierConfigManager;
    105     private final EuiccManager mEuiccManager;
    106     private final Resources mRes;
    107     private final Context mContext;
    108 
    109     private boolean mShowLatestAreaInfo;
    110 
    111     private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
    112         @Override
    113         public void onReceive(Context context, Intent intent) {
    114             final String action = intent.getAction();
    115             if (TextUtils.equals(action, CB_AREA_INFO_RECEIVED_ACTION)) {
    116                 final Bundle extras = intent.getExtras();
    117                 if (extras == null) {
    118                     return;
    119                 }
    120                 final CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
    121                 if (cbMessage != null
    122                         && mSubscriptionInfo.getSubscriptionId() == cbMessage.getSubId()) {
    123                     final String latestAreaInfo = cbMessage.getMessageBody();
    124                     mDialog.setText(OPERATOR_INFO_VALUE_ID, latestAreaInfo);
    125                 }
    126             }
    127         }
    128     };
    129 
    130     private PhoneStateListener mPhoneStateListener;
    131 
    132     public SimStatusDialogController(@NonNull SimStatusDialogFragment dialog, Lifecycle lifecycle,
    133             int slotId) {
    134         mDialog = dialog;
    135         mContext = dialog.getContext();
    136         mSubscriptionInfo = getPhoneSubscriptionInfo(slotId);
    137         mTelephonyManager = (TelephonyManager) mContext.getSystemService(
    138                 TELEPHONY_SERVICE);
    139         mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
    140                 CARRIER_CONFIG_SERVICE);
    141         mEuiccManager = (EuiccManager) mContext.getSystemService(EUICC_SERVICE);
    142 
    143         mRes = mContext.getResources();
    144 
    145         if (lifecycle != null) {
    146             lifecycle.addObserver(this);
    147         }
    148     }
    149 
    150     public void initialize() {
    151         updateEid();
    152 
    153         if (mSubscriptionInfo == null) {
    154             return;
    155         }
    156 
    157         mPhoneStateListener = getPhoneStateListener();
    158 
    159         final ServiceState serviceState = getCurrentServiceState();
    160         updateNetworkProvider(serviceState);
    161         updatePhoneNumber();
    162         updateLatestAreaInfo();
    163         updateServiceState(serviceState);
    164         updateSignalStrength(getSignalStrength());
    165         updateNetworkType();
    166         updateRoamingStatus(serviceState);
    167         updateIccidNumber();
    168         updateImsRegistrationState();
    169     }
    170 
    171     @Override
    172     public void onResume() {
    173         if (mSubscriptionInfo == null) {
    174             return;
    175         }
    176 
    177         mTelephonyManager.listen(mPhoneStateListener,
    178                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
    179                         | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
    180                         | PhoneStateListener.LISTEN_SERVICE_STATE);
    181 
    182         if (mShowLatestAreaInfo) {
    183             mContext.registerReceiver(mAreaInfoReceiver,
    184                     new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
    185                     Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, null /* scheduler */);
    186             // Ask CellBroadcastReceiver to broadcast the latest area info received
    187             final Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
    188             getLatestIntent.setPackage(CELL_BROADCAST_RECEIVER_APP);
    189             mContext.sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
    190                     Manifest.permission.RECEIVE_EMERGENCY_BROADCAST);
    191         }
    192     }
    193 
    194     @Override
    195     public void onPause() {
    196         if (mSubscriptionInfo == null) {
    197             return;
    198         }
    199 
    200         mTelephonyManager.listen(mPhoneStateListener,
    201                 PhoneStateListener.LISTEN_NONE);
    202 
    203         if (mShowLatestAreaInfo) {
    204             mContext.unregisterReceiver(mAreaInfoReceiver);
    205         }
    206     }
    207 
    208     private void updateNetworkProvider(ServiceState serviceState) {
    209         mDialog.setText(NETWORK_PROVIDER_VALUE_ID, serviceState.getOperatorAlphaLong());
    210     }
    211 
    212     private void updatePhoneNumber() {
    213         // If formattedNumber is null or empty, it'll display as "Unknown".
    214         mDialog.setText(PHONE_NUMBER_VALUE_ID, BidiFormatter.getInstance().unicodeWrap(
    215                 getPhoneNumber(), TextDirectionHeuristics.LTR));
    216     }
    217 
    218     private void updateDataState(int state) {
    219         String networkStateValue;
    220 
    221         switch (state) {
    222             case TelephonyManager.DATA_CONNECTED:
    223                 networkStateValue = mRes.getString(R.string.radioInfo_data_connected);
    224                 break;
    225             case TelephonyManager.DATA_SUSPENDED:
    226                 networkStateValue = mRes.getString(R.string.radioInfo_data_suspended);
    227                 break;
    228             case TelephonyManager.DATA_CONNECTING:
    229                 networkStateValue = mRes.getString(R.string.radioInfo_data_connecting);
    230                 break;
    231             case TelephonyManager.DATA_DISCONNECTED:
    232                 networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected);
    233                 break;
    234             default:
    235                 networkStateValue = mRes.getString(R.string.radioInfo_unknown);
    236                 break;
    237         }
    238 
    239         mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue);
    240     }
    241 
    242 
    243     private void updateLatestAreaInfo() {
    244         mShowLatestAreaInfo = Resources.getSystem().getBoolean(
    245                 com.android.internal.R.bool.config_showAreaUpdateInfoSettings)
    246                 && mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA;
    247 
    248         if (!mShowLatestAreaInfo) {
    249             mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID);
    250             mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID);
    251         }
    252     }
    253 
    254     private void updateServiceState(ServiceState serviceState) {
    255         final int state = serviceState.getState();
    256         if (state == ServiceState.STATE_OUT_OF_SERVICE || state == ServiceState.STATE_POWER_OFF) {
    257             resetSignalStrength();
    258         }
    259 
    260         String serviceStateValue;
    261 
    262         switch (state) {
    263             case ServiceState.STATE_IN_SERVICE:
    264                 serviceStateValue = mRes.getString(R.string.radioInfo_service_in);
    265                 break;
    266             case ServiceState.STATE_OUT_OF_SERVICE:
    267             case ServiceState.STATE_EMERGENCY_ONLY:
    268                 // Set summary string of service state to radioInfo_service_out when
    269                 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
    270                 serviceStateValue = mRes.getString(R.string.radioInfo_service_out);
    271                 break;
    272             case ServiceState.STATE_POWER_OFF:
    273                 serviceStateValue = mRes.getString(R.string.radioInfo_service_off);
    274                 break;
    275             default:
    276                 serviceStateValue = mRes.getString(R.string.radioInfo_unknown);
    277                 break;
    278         }
    279 
    280         mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue);
    281     }
    282 
    283     private void updateSignalStrength(SignalStrength signalStrength) {
    284         final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
    285         final PersistableBundle carrierConfig =
    286                 mCarrierConfigManager.getConfigForSubId(subscriptionId);
    287         // by default we show the signal strength
    288         boolean showSignalStrength = true;
    289         if (carrierConfig != null) {
    290             showSignalStrength = carrierConfig.getBoolean(
    291                     CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL);
    292         }
    293         if (!showSignalStrength) {
    294             mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID);
    295             mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID);
    296             return;
    297         }
    298 
    299         final int state = getCurrentServiceState().getState();
    300 
    301         if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
    302                 (ServiceState.STATE_POWER_OFF == state)) {
    303             return;
    304         }
    305 
    306         int signalDbm = getDbm(signalStrength);
    307         int signalAsu = getAsuLevel(signalStrength);
    308 
    309         if (signalDbm == -1) {
    310             signalDbm = 0;
    311         }
    312 
    313         if (signalAsu == -1) {
    314             signalAsu = 0;
    315         }
    316 
    317         mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength,
    318                 signalDbm, signalAsu));
    319     }
    320 
    321     private void resetSignalStrength() {
    322         mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0");
    323     }
    324 
    325     private void updateNetworkType() {
    326         // Whether EDGE, UMTS, etc...
    327         String dataNetworkTypeName = null;
    328         String voiceNetworkTypeName = null;
    329         final int subId = mSubscriptionInfo.getSubscriptionId();
    330         final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(subId);
    331         final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(subId);
    332         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
    333             dataNetworkTypeName = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
    334         }
    335         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
    336             voiceNetworkTypeName = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
    337         }
    338 
    339         boolean show4GForLTE = false;
    340         try {
    341             final Context con = mContext.createPackageContext(
    342                     "com.android.systemui", 0 /* flags */);
    343             final int id = con.getResources().getIdentifier("config_show4GForLTE",
    344                     "bool" /* default type */, "com.android.systemui" /* default package */);
    345             show4GForLTE = con.getResources().getBoolean(id);
    346         } catch (PackageManager.NameNotFoundException e) {
    347             Log.e(TAG, "NameNotFoundException for show4GForLTE");
    348         }
    349 
    350         if (show4GForLTE) {
    351             if ("LTE".equals(dataNetworkTypeName)) {
    352                 dataNetworkTypeName = "4G";
    353             }
    354             if ("LTE".equals(voiceNetworkTypeName)) {
    355                 voiceNetworkTypeName = "4G";
    356             }
    357         }
    358 
    359         mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, voiceNetworkTypeName);
    360         mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, dataNetworkTypeName);
    361     }
    362 
    363     private void updateRoamingStatus(ServiceState serviceState) {
    364         if (serviceState.getRoaming()) {
    365             mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in));
    366         } else {
    367             mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not));
    368         }
    369     }
    370 
    371     private void updateIccidNumber() {
    372         final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
    373         final PersistableBundle carrierConfig =
    374                 mCarrierConfigManager.getConfigForSubId(subscriptionId);
    375         // do not show iccid by default
    376         boolean showIccId = false;
    377         if (carrierConfig != null) {
    378             showIccId = carrierConfig.getBoolean(
    379                     CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
    380         }
    381         if (!showIccId) {
    382             mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID);
    383             mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID);
    384         } else {
    385             mDialog.setText(ICCID_INFO_VALUE_ID, getSimSerialNumber(subscriptionId));
    386         }
    387     }
    388 
    389     private void updateEid() {
    390         mDialog.setText(EID_INFO_VALUE_ID, mEuiccManager.getEid());
    391     }
    392 
    393     private void updateImsRegistrationState() {
    394         final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
    395         final PersistableBundle carrierConfig =
    396             mCarrierConfigManager.getConfigForSubId(subscriptionId);
    397         final boolean showImsRegState = carrierConfig == null ? false :
    398             carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL);
    399         if (showImsRegState) {
    400             final boolean isImsRegistered = mTelephonyManager.isImsRegistered(subscriptionId);
    401             mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(isImsRegistered ?
    402                 R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered));
    403         } else {
    404             mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID);
    405             mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID);
    406         }
    407     }
    408 
    409     private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) {
    410         final List<SubscriptionInfo> subscriptionInfoList = SubscriptionManager.from(
    411                 mContext).getActiveSubscriptionInfoList();
    412         if (subscriptionInfoList != null && subscriptionInfoList.size() > slotId) {
    413             return subscriptionInfoList.get(slotId);
    414         } else {
    415             return null;
    416         }
    417     }
    418 
    419     @VisibleForTesting
    420     ServiceState getCurrentServiceState() {
    421         return mTelephonyManager.getServiceStateForSubscriber(
    422                 mSubscriptionInfo.getSubscriptionId());
    423     }
    424 
    425     @VisibleForTesting
    426     int getDbm(SignalStrength signalStrength) {
    427         return signalStrength.getDbm();
    428     }
    429 
    430     @VisibleForTesting
    431     int getAsuLevel(SignalStrength signalStrength) {
    432         return signalStrength.getAsuLevel();
    433     }
    434 
    435     @VisibleForTesting
    436     PhoneStateListener getPhoneStateListener() {
    437         return new PhoneStateListener(
    438                 mSubscriptionInfo.getSubscriptionId()) {
    439             @Override
    440             public void onDataConnectionStateChanged(int state) {
    441                 updateDataState(state);
    442                 updateNetworkType();
    443             }
    444 
    445             @Override
    446             public void onSignalStrengthsChanged(SignalStrength signalStrength) {
    447                 updateSignalStrength(signalStrength);
    448             }
    449 
    450             @Override
    451             public void onServiceStateChanged(ServiceState serviceState) {
    452                 updateNetworkProvider(serviceState);
    453                 updateServiceState(serviceState);
    454                 updateRoamingStatus(serviceState);
    455             }
    456         };
    457     }
    458 
    459     @VisibleForTesting
    460     String getPhoneNumber() {
    461         return DeviceInfoUtils.getFormattedPhoneNumber(mContext, mSubscriptionInfo);
    462     }
    463 
    464     @VisibleForTesting
    465     SignalStrength getSignalStrength() {
    466         return mTelephonyManager.getSignalStrength();
    467     }
    468 
    469     @VisibleForTesting
    470     String getSimSerialNumber(int subscriptionId) {
    471         return mTelephonyManager.getSimSerialNumber(subscriptionId);
    472     }
    473 }
    474